src/symboltablebuilder/Scope.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright (c) 2021-2026 ChilliBits. All rights reserved. | ||
| 2 | |||
| 3 | #include "Scope.h" | ||
| 4 | |||
| 5 | #include <SourceFile.h> | ||
| 6 | #include <ast/ASTNodes.h> | ||
| 7 | #include <exception/SemanticError.h> | ||
| 8 | #include <global/GlobalResourceManager.h> | ||
| 9 | #include <symboltablebuilder/SymbolTableBuilder.h> | ||
| 10 | |||
| 11 | namespace spice::compiler { | ||
| 12 | |||
| 13 | 216302 | Scope::Scope(Scope *parent, SourceFile *sourceFile, ScopeType scopeType, const CodeLoc *codeLoc) | |
| 14 | 216302 | : parent(parent), sourceFile(sourceFile), scopeId(sourceFile->resourceManager.getNextScopeId()), codeLoc(codeLoc), | |
| 15 |
2/2✓ Branch 4 → 5 taken 210722 times.
✓ Branch 4 → 6 taken 5580 times.
|
216302 | type(scopeType) {} |
| 16 | |||
| 17 | /** | ||
| 18 | * Create a child scope and return it | ||
| 19 | * | ||
| 20 | * @param scopeName Name of the child scope | ||
| 21 | * @param scopeType Type of the child scope | ||
| 22 | * @param declCodeLoc Code location of the scope | ||
| 23 | * @return Child scope (heap allocated) | ||
| 24 | */ | ||
| 25 | 210722 | Scope *Scope::createChildScope(const std::string &scopeName, ScopeType scopeType, const CodeLoc *declCodeLoc) { | |
| 26 |
2/4✓ Branch 2 → 3 taken 210722 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 210722 times.
✗ Branch 3 → 13 not taken.
|
210722 | const auto &[scope, inserted] = children.emplace(scopeName, std::make_shared<Scope>(this, sourceFile, scopeType, declCodeLoc)); |
| 27 |
1/2✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 210722 times.
|
210722 | assert(inserted); |
| 28 | 421444 | return scope->second.get(); | |
| 29 | } | ||
| 30 | |||
| 31 | /** | ||
| 32 | * Rename the child scope. This is useful for realizing function overloading by storing a function with not | ||
| 33 | * only its name, but also its signature | ||
| 34 | * | ||
| 35 | * @param oldName Old name of the child table | ||
| 36 | * @param newName New name of the child table | ||
| 37 | */ | ||
| 38 | 73415 | void Scope::renameChildScope(const std::string &oldName, const std::string &newName) { | |
| 39 |
4/8✓ Branch 2 → 3 taken 73415 times.
✗ Branch 2 → 20 not taken.
✓ Branch 3 → 4 taken 73415 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 73415 times.
✗ Branch 4 → 20 not taken.
✓ Branch 5 → 6 taken 73415 times.
✗ Branch 5 → 7 not taken.
|
73415 | assert(children.contains(oldName) && !children.contains(newName)); |
| 40 |
1/2✓ Branch 8 → 9 taken 73415 times.
✗ Branch 8 → 20 not taken.
|
73415 | auto nodeHandler = children.extract(oldName); |
| 41 |
1/2✓ Branch 10 → 11 taken 73415 times.
✗ Branch 10 → 18 not taken.
|
73415 | nodeHandler.key() = newName; |
| 42 |
1/2✓ Branch 13 → 14 taken 73415 times.
✗ Branch 13 → 17 not taken.
|
146830 | children.insert(std::move(nodeHandler)); |
| 43 | 73415 | } | |
| 44 | |||
| 45 | /** | ||
| 46 | * Duplicates the child scope by copying it. The duplicated symbols point to the original ones. | ||
| 47 | * | ||
| 48 | * @param oldName Old name of the child block | ||
| 49 | * @param newName New block name | ||
| 50 | */ | ||
| 51 | 28961 | Scope *Scope::copyChildScope(const std::string &oldName, const std::string &newName) { | |
| 52 |
4/8✓ Branch 2 → 3 taken 28961 times.
✗ Branch 2 → 18 not taken.
✓ Branch 3 → 4 taken 28961 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 28961 times.
✗ Branch 4 → 18 not taken.
✓ Branch 5 → 6 taken 28961 times.
✗ Branch 5 → 7 not taken.
|
28961 | assert(children.contains(oldName) && !children.contains(newName)); |
| 53 | // Create copy | ||
| 54 |
2/4✓ Branch 8 → 9 taken 28961 times.
✗ Branch 8 → 18 not taken.
✓ Branch 10 → 11 taken 28961 times.
✗ Branch 10 → 18 not taken.
|
28961 | const std::shared_ptr<Scope> newScope = children.at(oldName)->deepCopyScope(); |
| 55 | // Save copy under new name | ||
| 56 |
1/2✓ Branch 11 → 12 taken 28961 times.
✗ Branch 11 → 16 not taken.
|
28961 | children.emplace(newName, newScope); |
| 57 | 57922 | return newScope.get(); | |
| 58 | 28961 | } | |
| 59 | |||
| 60 | /** | ||
| 61 | * Deep copy the current scope and all its children | ||
| 62 | * | ||
| 63 | * @return Deep copy of the current scope | ||
| 64 | */ | ||
| 65 | 155425 | std::shared_ptr<Scope> Scope::deepCopyScope() { // NOLINT(misc-no-recursion) | |
| 66 | 155425 | const auto newScope = std::make_shared<Scope>(*this); | |
| 67 |
1/2✓ Branch 3 → 4 taken 155425 times.
✗ Branch 3 → 41 not taken.
|
155425 | newScope->scopeId = sourceFile->resourceManager.getNextScopeId(); |
| 68 |
2/2✓ Branch 32 → 7 taken 126464 times.
✓ Branch 32 → 33 taken 155425 times.
|
281889 | for (const auto &[childName, oldChild] : children) { |
| 69 |
2/4✓ Branch 11 → 12 taken 126464 times.
✗ Branch 11 → 39 not taken.
✓ Branch 13 → 14 taken 126464 times.
✗ Branch 13 → 37 not taken.
|
126464 | newScope->children[childName] = oldChild->deepCopyScope(); |
| 70 |
1/2✓ Branch 18 → 19 taken 126464 times.
✗ Branch 18 → 40 not taken.
|
126464 | newScope->children[childName]->parent = newScope.get(); |
| 71 |
2/4✓ Branch 21 → 22 taken 126464 times.
✗ Branch 21 → 40 not taken.
✓ Branch 24 → 25 taken 126464 times.
✗ Branch 24 → 40 not taken.
|
126464 | newScope->children[childName]->symbolTable.scope = newScope->children[childName].get(); |
| 72 |
1/2✓ Branch 28 → 29 taken 126464 times.
✗ Branch 28 → 40 not taken.
|
126464 | newScope->children[childName]->symbolTable.parent = &newScope->symbolTable; |
| 73 | } | ||
| 74 | 155425 | newScope->symbolTable.scope = newScope.get(); | |
| 75 | 155425 | return newScope; | |
| 76 | − | } // LCOV_EXCL_LINE - false positive | |
| 77 | |||
| 78 | /** | ||
| 79 | * Get a child scope of the current scope by its name | ||
| 80 | * | ||
| 81 | * @param scopeName Child scope name | ||
| 82 | * @return Child scope | ||
| 83 | */ | ||
| 84 | 459681 | Scope *Scope::getChildScope(const std::string &scopeName) const { | |
| 85 |
1/2✓ Branch 2 → 3 taken 459681 times.
✗ Branch 2 → 12 not taken.
|
459681 | const auto it = children.find(scopeName); |
| 86 |
2/2✓ Branch 5 → 6 taken 459603 times.
✓ Branch 5 → 8 taken 78 times.
|
919362 | return it != children.end() ? it->second.get() : nullptr; |
| 87 | } | ||
| 88 | |||
| 89 | /** | ||
| 90 | * Retrieve all variables in the current scope, that have reached the end of their lifetime at the end of this scope | ||
| 91 | * | ||
| 92 | * @return Collection of EOL variables | ||
| 93 | */ | ||
| 94 | 205194 | std::vector<SymbolTableEntry *> Scope::getVarsGoingOutOfScope() { // NOLINT(misc-no-recursion) | |
| 95 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 205194 times.
|
205194 | assert(!isRootScope()); // Should not be called in root scope |
| 96 | 205194 | std::vector<SymbolTableEntry *> varsGoingOutOfScope; | |
| 97 | |||
| 98 | // Collect all variables in this scope | ||
| 99 |
2/2✓ Branch 26 → 8 taken 216510 times.
✓ Branch 26 → 27 taken 205194 times.
|
421704 | for (const auto &[name, entry] : symbolTable.symbols) { |
| 100 | // Skip 'this' and result variables | ||
| 101 |
8/10✓ Branch 11 → 12 taken 216510 times.
✗ Branch 11 → 52 not taken.
✓ Branch 12 → 13 taken 175062 times.
✓ Branch 12 → 15 taken 41448 times.
✓ Branch 13 → 14 taken 175062 times.
✗ Branch 13 → 52 not taken.
✓ Branch 14 → 15 taken 41625 times.
✓ Branch 14 → 16 taken 133437 times.
✓ Branch 17 → 18 taken 83073 times.
✓ Branch 17 → 19 taken 133437 times.
|
216510 | if (name == THIS_VARIABLE_NAME || name == RETURN_VARIABLE_NAME) |
| 102 | 83073 | continue; | |
| 103 | // Skip parameters (ToDo: Remove when copy constructors work for by-value argument passing) | ||
| 104 |
2/2✓ Branch 19 → 20 taken 79002 times.
✓ Branch 19 → 21 taken 54435 times.
|
133437 | if (entry.isParam) |
| 105 | 79002 | continue; | |
| 106 | // Found variable, that goes out of scope | ||
| 107 |
2/4✓ Branch 21 → 22 taken 54435 times.
✗ Branch 21 → 51 not taken.
✓ Branch 22 → 23 taken 54435 times.
✗ Branch 22 → 51 not taken.
|
54435 | varsGoingOutOfScope.push_back(&symbolTable.symbols.at(name)); |
| 108 | } | ||
| 109 | |||
| 110 | // If this is the scope of a dtor, also return all fields of the struct | ||
| 111 |
2/2✓ Branch 27 → 28 taken 1136 times.
✓ Branch 27 → 49 taken 204058 times.
|
205194 | if (isDtorScope) { |
| 112 |
2/4✓ Branch 30 → 31 taken 1136 times.
✗ Branch 30 → 33 not taken.
✓ Branch 31 → 32 taken 1136 times.
✗ Branch 31 → 33 not taken.
|
1136 | assert(!isRootScope() && parent->type == ScopeType::STRUCT); |
| 113 | // Get all fields of the struct | ||
| 114 |
2/2✓ Branch 47 → 36 taken 37134 times.
✓ Branch 47 → 48 taken 1136 times.
|
38270 | for (const auto &[name, entry] : parent->symbolTable.symbols) |
| 115 |
4/6✓ Branch 39 → 40 taken 37134 times.
✗ Branch 39 → 55 not taken.
✓ Branch 40 → 41 taken 37134 times.
✗ Branch 40 → 53 not taken.
✓ Branch 41 → 42 taken 3660 times.
✓ Branch 41 → 45 taken 33474 times.
|
37134 | if (!entry.getQualType().isOneOf({TY_FUNCTION, TY_PROCEDURE})) |
| 116 |
2/4✓ Branch 42 → 43 taken 3660 times.
✗ Branch 42 → 54 not taken.
✓ Branch 43 → 44 taken 3660 times.
✗ Branch 43 → 54 not taken.
|
3660 | varsGoingOutOfScope.push_back(&parent->symbolTable.symbols.at(name)); |
| 117 | } | ||
| 118 | |||
| 119 | 205194 | return varsGoingOutOfScope; | |
| 120 | − | } // LCOV_EXCL_LINE - false positive | |
| 121 | |||
| 122 | /** | ||
| 123 | * Insert a new generic type in this scope | ||
| 124 | * | ||
| 125 | * @param typeName Generic type name | ||
| 126 | * @param genericType Generic type itself | ||
| 127 | */ | ||
| 128 | 28436 | void Scope::insertGenericType(const std::string &typeName, const GenericType &genericType) { | |
| 129 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 28436 times.
|
28436 | assert(!genericTypes.contains(typeName)); |
| 130 | 28436 | genericTypes.emplace(typeName, genericType); | |
| 131 | 28436 | } | |
| 132 | |||
| 133 | /** | ||
| 134 | * Search for a generic type by its name in this scope. | ||
| 135 | * If the generic type is not found, a nullptr is returned. | ||
| 136 | * | ||
| 137 | * @param typeName Name of the generic type | ||
| 138 | * @return Generic type | ||
| 139 | */ | ||
| 140 | 220928 | GenericType *Scope::lookupGenericTypeStrict(const std::string &typeName) { | |
| 141 |
1/2✓ Branch 2 → 3 taken 220928 times.
✗ Branch 2 → 12 not taken.
|
220928 | const auto it = genericTypes.find(typeName); |
| 142 |
2/2✓ Branch 5 → 6 taken 83390 times.
✓ Branch 5 → 8 taken 137538 times.
|
441856 | return it != genericTypes.end() ? &it->second : nullptr; |
| 143 | } | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Collect all warnings, produced within this scope | ||
| 147 | * | ||
| 148 | * @param warnings List of warnings | ||
| 149 | * @return Collection of warnings | ||
| 150 | */ | ||
| 151 | 9033 | void Scope::collectWarnings(std::vector<CompilerWarning> &warnings) const { // NOLINT(misc-no-recursion) | |
| 152 | // Visit own symbols | ||
| 153 |
5/8✓ Branch 2 → 3 taken 9033 times.
✗ Branch 2 → 241 not taken.
✓ Branch 3 → 4 taken 9033 times.
✗ Branch 3 → 241 not taken.
✓ Branch 4 → 5 taken 9033 times.
✗ Branch 4 → 241 not taken.
✓ Branch 165 → 6 taken 25680 times.
✓ Branch 165 → 166 taken 9033 times.
|
34713 | for (const SymbolTableEntry &entry : symbolTable.symbols | std::views::values) { |
| 154 | // Do not produce a warning if the symbol is used or has a special name | ||
| 155 | 25680 | const std::string &name = entry.name; | |
| 156 |
9/10✓ Branch 7 → 8 taken 797 times.
✓ Branch 7 → 12 taken 24883 times.
✓ Branch 9 → 10 taken 533 times.
✓ Branch 9 → 12 taken 264 times.
✓ Branch 10 → 11 taken 533 times.
✗ Branch 10 → 240 not taken.
✓ Branch 11 → 12 taken 106 times.
✓ Branch 11 → 13 taken 427 times.
✓ Branch 14 → 15 taken 25253 times.
✓ Branch 14 → 16 taken 427 times.
|
25680 | if (entry.used || name.starts_with(UNUSED_VARIABLE_NAME) || name == THIS_VARIABLE_NAME) |
| 157 | 25401 | continue; | |
| 158 | |||
| 159 |
1/2✓ Branch 16 → 17 taken 427 times.
✗ Branch 16 → 240 not taken.
|
427 | const QualType entryType = entry.getQualType(); |
| 160 | |||
| 161 | // When compiling a static or shared library, publicly accessible symbols form part of the library's exported | ||
| 162 | // API. They may legitimately go unused within the library itself, since external consumers are expected to | ||
| 163 | // use them, so do not report them as unused. isPublic() is only defined for the type categories checked here | ||
| 164 | // (see the assertion in QualType::isPublic()), so guard the call accordingly. | ||
| 165 |
12/18✓ Branch 17 → 18 taken 427 times.
✗ Branch 17 → 240 not taken.
✓ Branch 18 → 19 taken 86 times.
✓ Branch 18 → 21 taken 341 times.
✓ Branch 19 → 20 taken 86 times.
✗ Branch 19 → 240 not taken.
✓ Branch 20 → 21 taken 4 times.
✓ Branch 20 → 26 taken 82 times.
✓ Branch 21 → 22 taken 345 times.
✗ Branch 21 → 240 not taken.
✓ Branch 22 → 23 taken 171 times.
✓ Branch 22 → 26 taken 174 times.
✓ Branch 23 → 24 taken 171 times.
✗ Branch 23 → 240 not taken.
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 26 taken 171 times.
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 427 times.
|
427 | if ((entryType.isExtendedPrimitive() || entryType.is(TY_ENUM)) && entryType.isPublic() && sourceFile->isLibraryOutput()) |
| 166 | ✗ | continue; | |
| 167 | |||
| 168 | // Determine warning type and message by the scope type and the symbol type | ||
| 169 | 427 | CompilerWarningType warningType = UNUSED_VARIABLE; | |
| 170 | 427 | std::string warningMessage; | |
| 171 |
4/4✓ Branch 30 → 31 taken 36 times.
✓ Branch 30 → 114 taken 254 times.
✓ Branch 30 → 143 taken 8 times.
✓ Branch 30 → 149 taken 129 times.
|
427 | switch (type) { |
| 172 | 36 | case ScopeType::GLOBAL: { | |
| 173 | // Skip generic function/procedure/struct/interface/union entries | ||
| 174 |
4/6✓ Branch 31 → 32 taken 36 times.
✗ Branch 31 → 179 not taken.
✓ Branch 32 → 33 taken 22 times.
✓ Branch 32 → 37 taken 14 times.
✗ Branch 38 → 39 not taken.
✓ Branch 38 → 40 taken 36 times.
|
58 | if (entryType.isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_STRUCT, TY_INTERFACE, TY_UNION}) && |
| 175 |
2/4✓ Branch 33 → 34 taken 22 times.
✗ Branch 33 → 179 not taken.
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 22 times.
|
22 | !entryType.getTemplateTypes().empty()) |
| 176 | ✗ | continue; | |
| 177 | |||
| 178 |
3/4✓ Branch 40 → 41 taken 36 times.
✗ Branch 40 → 238 not taken.
✓ Branch 41 → 42 taken 10 times.
✓ Branch 41 → 52 taken 26 times.
|
36 | if (entryType.is(TY_FUNCTION)) { |
| 179 |
1/2✓ Branch 42 → 43 taken 10 times.
✗ Branch 42 → 238 not taken.
|
10 | const std::vector<Function *> *fctManifestations = entry.declNode->getFctManifestations(name); |
| 180 | 10 | warningType = UNUSED_FUNCTION; | |
| 181 |
3/6✓ Branch 44 → 45 taken 10 times.
✗ Branch 44 → 184 not taken.
✓ Branch 45 → 46 taken 10 times.
✗ Branch 45 → 182 not taken.
✓ Branch 46 → 47 taken 10 times.
✗ Branch 46 → 180 not taken.
|
10 | warningMessage = "'" + fctManifestations->front()->getSignature() + "' is unused"; |
| 182 |
3/4✓ Branch 52 → 53 taken 26 times.
✗ Branch 52 → 238 not taken.
✓ Branch 53 → 54 taken 6 times.
✓ Branch 53 → 64 taken 20 times.
|
26 | } else if (entryType.is(TY_PROCEDURE)) { |
| 183 |
1/2✓ Branch 54 → 55 taken 6 times.
✗ Branch 54 → 238 not taken.
|
6 | const std::vector<Function *> *fctManifestations = entry.declNode->getFctManifestations(name); |
| 184 | 6 | warningType = UNUSED_PROCEDURE; | |
| 185 |
3/6✓ Branch 56 → 57 taken 6 times.
✗ Branch 56 → 191 not taken.
✓ Branch 57 → 58 taken 6 times.
✗ Branch 57 → 189 not taken.
✓ Branch 58 → 59 taken 6 times.
✗ Branch 58 → 187 not taken.
|
6 | warningMessage = "'" + fctManifestations->front()->getSignature() + "' is unused"; |
| 186 |
3/4✓ Branch 64 → 65 taken 20 times.
✗ Branch 64 → 238 not taken.
✓ Branch 65 → 66 taken 2 times.
✓ Branch 65 → 72 taken 18 times.
|
20 | } else if (entryType.is(TY_STRUCT)) { |
| 187 | 2 | warningType = UNUSED_STRUCT; | |
| 188 |
2/4✓ Branch 66 → 67 taken 2 times.
✗ Branch 66 → 196 not taken.
✓ Branch 67 → 68 taken 2 times.
✗ Branch 67 → 194 not taken.
|
2 | warningMessage = "The struct '" + entry.name + "' is unused"; |
| 189 |
3/4✓ Branch 72 → 73 taken 18 times.
✗ Branch 72 → 238 not taken.
✓ Branch 73 → 74 taken 2 times.
✓ Branch 73 → 80 taken 16 times.
|
18 | } else if (entryType.is(TY_INTERFACE)) { |
| 190 | 2 | warningType = UNUSED_INTERFACE; | |
| 191 |
2/4✓ Branch 74 → 75 taken 2 times.
✗ Branch 74 → 200 not taken.
✓ Branch 75 → 76 taken 2 times.
✗ Branch 75 → 198 not taken.
|
2 | warningMessage = "The interface '" + entry.name + "' is unused"; |
| 192 |
3/4✓ Branch 80 → 81 taken 16 times.
✗ Branch 80 → 238 not taken.
✓ Branch 81 → 82 taken 2 times.
✓ Branch 81 → 88 taken 14 times.
|
16 | } else if (entryType.is(TY_UNION)) { |
| 193 | 2 | warningType = UNUSED_UNION; | |
| 194 |
2/4✓ Branch 82 → 83 taken 2 times.
✗ Branch 82 → 204 not taken.
✓ Branch 83 → 84 taken 2 times.
✗ Branch 83 → 202 not taken.
|
2 | warningMessage = "The union '" + entry.name + "' is unused"; |
| 195 |
3/4✓ Branch 88 → 89 taken 14 times.
✗ Branch 88 → 238 not taken.
✓ Branch 89 → 90 taken 4 times.
✓ Branch 89 → 91 taken 10 times.
|
14 | } else if (entryType.is(TY_ENUM)) { |
| 196 | 4 | continue; // Do not report unused enums. Only unused enum items are reported | |
| 197 |
3/4✓ Branch 91 → 92 taken 10 times.
✗ Branch 91 → 238 not taken.
✓ Branch 92 → 93 taken 8 times.
✓ Branch 92 → 99 taken 2 times.
|
10 | } else if (entryType.is(TY_IMPORT)) { |
| 198 | 8 | warningType = UNUSED_IMPORT; | |
| 199 |
2/4✓ Branch 93 → 94 taken 8 times.
✗ Branch 93 → 208 not taken.
✓ Branch 94 → 95 taken 8 times.
✗ Branch 94 → 206 not taken.
|
8 | warningMessage = "The import '" + entry.name + "' is unused"; |
| 200 |
2/4✓ Branch 99 → 100 taken 2 times.
✗ Branch 99 → 238 not taken.
✓ Branch 100 → 101 taken 2 times.
✗ Branch 100 → 107 not taken.
|
2 | } else if (entryType.is(TY_ALIAS)) { |
| 201 | 2 | warningType = UNUSED_ALIAS; | |
| 202 |
2/4✓ Branch 101 → 102 taken 2 times.
✗ Branch 101 → 212 not taken.
✓ Branch 102 → 103 taken 2 times.
✗ Branch 102 → 210 not taken.
|
2 | warningMessage = "The type alias '" + entry.name + "' is unused"; |
| 203 | } else { | ||
| 204 | ✗ | warningType = UNUSED_VARIABLE; | |
| 205 | ✗ | warningMessage = "The variable '" + entry.name + "' is unused"; | |
| 206 | } | ||
| 207 | |||
| 208 | 32 | break; | |
| 209 | } | ||
| 210 | 254 | case ScopeType::STRUCT: // fall-through | |
| 211 | case ScopeType::INTERFACE: // fall-through | ||
| 212 | case ScopeType::UNION: { | ||
| 213 |
3/4✓ Branch 114 → 115 taken 254 times.
✗ Branch 114 → 238 not taken.
✓ Branch 115 → 116 taken 90 times.
✓ Branch 115 → 122 taken 164 times.
|
254 | if (entry.isField()) { |
| 214 | 90 | warningType = UNUSED_FIELD; | |
| 215 |
2/4✓ Branch 116 → 117 taken 90 times.
✗ Branch 116 → 220 not taken.
✓ Branch 117 → 118 taken 90 times.
✗ Branch 117 → 218 not taken.
|
90 | warningMessage = "The field '" + entry.name + "' is unused"; |
| 216 |
2/4✓ Branch 122 → 123 taken 164 times.
✗ Branch 122 → 222 not taken.
✓ Branch 123 → 124 taken 164 times.
✗ Branch 123 → 142 not taken.
|
164 | } else if (entryType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) { |
| 217 | // Skip implicit method entries and generic templates | ||
| 218 |
1/2✓ Branch 124 → 125 taken 164 times.
✗ Branch 124 → 238 not taken.
|
164 | const std::vector<Function *> *fctManifestations = entry.declNode->getFctManifestations(name); |
| 219 |
5/6✓ Branch 126 → 127 taken 20 times.
✓ Branch 126 → 129 taken 144 times.
✗ Branch 128 → 129 not taken.
✓ Branch 128 → 130 taken 20 times.
✓ Branch 131 → 132 taken 144 times.
✓ Branch 131 → 133 taken 20 times.
|
164 | if (fctManifestations->empty() || fctManifestations->front()->implicitDefault) |
| 220 | 144 | continue; | |
| 221 | |||
| 222 | 20 | warningType = UNUSED_METHOD; | |
| 223 |
3/6✓ Branch 134 → 135 taken 20 times.
✗ Branch 134 → 227 not taken.
✓ Branch 135 → 136 taken 20 times.
✗ Branch 135 → 225 not taken.
✓ Branch 136 → 137 taken 20 times.
✗ Branch 136 → 223 not taken.
|
20 | warningMessage = "The method '" + fctManifestations->front()->getSignature() + "' is unused"; |
| 224 | } | ||
| 225 | 110 | break; | |
| 226 | } | ||
| 227 | 8 | case ScopeType::ENUM: { | |
| 228 | 8 | warningType = UNUSED_ENUM_ITEM; | |
| 229 |
2/4✓ Branch 143 → 144 taken 8 times.
✗ Branch 143 → 232 not taken.
✓ Branch 144 → 145 taken 8 times.
✗ Branch 144 → 230 not taken.
|
8 | warningMessage = "The enum item '" + entry.name + "' is unused"; |
| 230 | 8 | break; | |
| 231 | } | ||
| 232 | 129 | default: { | |
| 233 | 129 | warningType = UNUSED_VARIABLE; | |
| 234 |
2/4✓ Branch 149 → 150 taken 129 times.
✗ Branch 149 → 236 not taken.
✓ Branch 150 → 151 taken 129 times.
✗ Branch 150 → 234 not taken.
|
129 | warningMessage = "The variable '" + entry.name + "' is unused"; |
| 235 | 129 | break; | |
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | // Add warning | ||
| 240 |
2/4✓ Branch 155 → 156 taken 279 times.
✗ Branch 155 → 238 not taken.
✓ Branch 156 → 157 taken 279 times.
✗ Branch 156 → 238 not taken.
|
279 | warnings.emplace_back(entry.getDeclCodeLoc(), warningType, warningMessage); |
| 241 |
2/2✓ Branch 159 → 160 taken 279 times.
✓ Branch 159 → 162 taken 148 times.
|
427 | } |
| 242 | |||
| 243 | // Visit children | ||
| 244 |
5/8✓ Branch 166 → 167 taken 9033 times.
✗ Branch 166 → 242 not taken.
✓ Branch 167 → 168 taken 9033 times.
✗ Branch 167 → 242 not taken.
✓ Branch 168 → 169 taken 9033 times.
✗ Branch 168 → 242 not taken.
✓ Branch 177 → 170 taken 8458 times.
✓ Branch 177 → 178 taken 9033 times.
|
17491 | for (const auto &childScope : children | std::views::values) |
| 245 |
2/2✓ Branch 172 → 173 taken 8026 times.
✓ Branch 172 → 175 taken 432 times.
|
8458 | if (!childScope->isGenericScope) |
| 246 |
1/2✓ Branch 174 → 175 taken 8026 times.
✗ Branch 174 → 242 not taken.
|
8026 | childScope->collectWarnings(warnings); |
| 247 | 9033 | } | |
| 248 | |||
| 249 | /** | ||
| 250 | * Checks if all variables of this and all child scopes are of an explicit type. | ||
| 251 | * This is executed after type inference to check that all variables could be inferred correctly. | ||
| 252 | */ | ||
| 253 | 952707 | void Scope::ensureSuccessfulTypeInference() const { // NOLINT(misc-no-recursion) | |
| 254 | // Check symbols in this scope | ||
| 255 |
2/2✓ Branch 19 → 4 taken 1409769 times.
✓ Branch 19 → 20 taken 952705 times.
|
2362474 | for (auto &[name, entry] : symbolTable.symbols) |
| 256 |
4/6✓ Branch 7 → 8 taken 1409769 times.
✗ Branch 7 → 40 not taken.
✓ Branch 8 → 9 taken 1409769 times.
✗ Branch 8 → 40 not taken.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 17 taken 1409767 times.
|
1409769 | if (entry.getQualType().is(TY_DYN)) |
| 257 |
3/6✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 36 not taken.
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 34 not taken.
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 31 not taken.
|
2 | throw SemanticError(entry.declNode, UNEXPECTED_DYN_TYPE, "For the variable '" + name + "' no type could be inferred"); |
| 258 | |||
| 259 | // Check child scopes | ||
| 260 |
5/8✓ Branch 20 → 21 taken 952705 times.
✗ Branch 20 → 41 not taken.
✓ Branch 21 → 22 taken 952705 times.
✗ Branch 21 → 41 not taken.
✓ Branch 22 → 23 taken 952705 times.
✗ Branch 22 → 41 not taken.
✓ Branch 29 → 24 taken 939011 times.
✓ Branch 29 → 30 taken 952703 times.
|
1891714 | for (const auto &scope : children | std::views::values) |
| 261 |
2/2✓ Branch 26 → 27 taken 939009 times.
✓ Branch 26 → 41 taken 2 times.
|
939011 | scope->ensureSuccessfulTypeInference(); |
| 262 | 952703 | } | |
| 263 | |||
| 264 | /** | ||
| 265 | * Get the number of fields if this is a struct scope | ||
| 266 | * | ||
| 267 | * @return Number of fields | ||
| 268 | */ | ||
| 269 | 412211 | size_t Scope::getFieldCount() const { | |
| 270 |
3/4✓ Branch 2 → 3 taken 164 times.
✓ Branch 2 → 5 taken 412047 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 164 times.
|
412211 | assert(type == ScopeType::STRUCT || type == ScopeType::UNION); |
| 271 | 412211 | size_t fieldCount = 0; | |
| 272 |
5/8✓ Branch 5 → 6 taken 412211 times.
✗ Branch 5 → 32 not taken.
✓ Branch 6 → 7 taken 412211 times.
✗ Branch 6 → 32 not taken.
✓ Branch 7 → 8 taken 412211 times.
✗ Branch 7 → 32 not taken.
✓ Branch 29 → 9 taken 8377893 times.
✓ Branch 29 → 30 taken 412211 times.
|
8790103 | for (const auto &symbol : symbolTable.symbols | std::views::values) { |
| 273 |
1/2✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 8377892 times.
|
8377892 | if (symbol.anonymous) |
| 274 | ✗ | continue; | |
| 275 |
1/2✓ Branch 12 → 13 taken 8377892 times.
✗ Branch 12 → 32 not taken.
|
8377892 | const QualType &symbolType = symbol.getQualType(); |
| 276 |
2/4✓ Branch 13 → 14 taken 8377893 times.
✗ Branch 13 → 32 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 8377893 times.
|
8377892 | if (symbolType.is(TY_IMPORT)) |
| 277 | ✗ | continue; | |
| 278 | 8377893 | const ASTNode *declNode = symbol.declNode; | |
| 279 |
10/14✓ Branch 16 → 17 taken 8377892 times.
✗ Branch 16 → 32 not taken.
✓ Branch 17 → 18 taken 1552426 times.
✓ Branch 17 → 22 taken 6825466 times.
✓ Branch 18 → 19 taken 1552426 times.
✗ Branch 18 → 32 not taken.
✓ Branch 19 → 20 taken 1391492 times.
✓ Branch 19 → 22 taken 160934 times.
✓ Branch 20 → 21 taken 1391492 times.
✗ Branch 20 → 32 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 1391492 times.
✓ Branch 24 → 25 taken 6986401 times.
✓ Branch 24 → 26 taken 1391491 times.
|
8377893 | if (declNode->isFctOrProcDef() || declNode->isStructDef() || declNode->isUnionDef()) |
| 280 | 6986401 | continue; | |
| 281 | 1391491 | fieldCount++; | |
| 282 | } | ||
| 283 | 412211 | return fieldCount; | |
| 284 | } | ||
| 285 | |||
| 286 | /** | ||
| 287 | * Get all virtual methods in this scope, sorted by their VTable index | ||
| 288 | * | ||
| 289 | * The VTable index is assigned based on the declaration order of the methods in the implemented interface(s). This must match the | ||
| 290 | * order the call sites use to index into the VTable, which may differ from the order the methods are defined in within the struct. | ||
| 291 | * | ||
| 292 | * @return List of virtual method pointers | ||
| 293 | */ | ||
| 294 | 4800 | std::vector<const Function *> Scope::getVirtualMethods() { | |
| 295 |
3/4✓ Branch 2 → 3 taken 2148 times.
✓ Branch 2 → 5 taken 2652 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2148 times.
|
4800 | assert(type == ScopeType::STRUCT || type == ScopeType::INTERFACE); |
| 296 | |||
| 297 | // Collect all virtual methods | ||
| 298 | 4800 | std::vector<const Function *> methods; | |
| 299 |
2/2✓ Branch 37 → 7 taken 36398 times.
✓ Branch 37 → 38 taken 4800 times.
|
41198 | for (auto &[fctId, manifestationList] : functions) { |
| 300 |
1/2✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 36398 times.
|
36398 | assert(!manifestationList.empty()); |
| 301 |
2/2✓ Branch 34 → 15 taken 53552 times.
✓ Branch 34 → 35 taken 36398 times.
|
89950 | for (auto &[mangledName, function] : manifestationList) |
| 302 |
2/2✓ Branch 27 → 28 taken 10940 times.
✓ Branch 27 → 32 taken 42612 times.
|
53552 | if (function.isVirtualMethod()) |
| 303 |
3/6✓ Branch 28 → 29 taken 10940 times.
✗ Branch 28 → 41 not taken.
✓ Branch 29 → 30 taken 10940 times.
✗ Branch 29 → 41 not taken.
✓ Branch 30 → 31 taken 10940 times.
✗ Branch 30 → 41 not taken.
|
10940 | methods.push_back(&functions.at(fctId).at(mangledName)); |
| 304 | } | ||
| 305 | |||
| 306 | // Sort the list by VTable index, so that the VTable layout matches the slot indices used at the call sites | ||
| 307 | 13208 | const auto pred = [](const Function *a, const Function *b) { return a->vtableIndex < b->vtableIndex; }; | |
| 308 |
1/2✓ Branch 38 → 39 taken 4800 times.
✗ Branch 38 → 44 not taken.
|
4800 | std::ranges::sort(methods, pred); |
| 309 | |||
| 310 | 4800 | return methods; | |
| 311 | − | } // LCOV_EXCL_LINE - false positive | |
| 312 | |||
| 313 | /** | ||
| 314 | * Retrieve all struct manifestations in this scope in the order of their declaration | ||
| 315 | * | ||
| 316 | * @return All struct manifestations in declaration order | ||
| 317 | */ | ||
| 318 | 5482 | std::vector<Struct *> Scope::getAllStructManifestationsInDeclarationOrder() { | |
| 319 | // Retrieve all struct manifestations in this scope | ||
| 320 | 5482 | std::vector<Struct *> manifestations; | |
| 321 |
1/2✓ Branch 3 → 4 taken 5482 times.
✗ Branch 3 → 27 not taken.
|
5482 | manifestations.reserve(structs.size()); // Reserve at least the size of individual generic structs |
| 322 |
5/8✓ Branch 4 → 5 taken 5482 times.
✗ Branch 4 → 26 not taken.
✓ Branch 5 → 6 taken 5482 times.
✗ Branch 5 → 26 not taken.
✓ Branch 6 → 7 taken 5482 times.
✗ Branch 6 → 26 not taken.
✓ Branch 20 → 8 taken 4548 times.
✓ Branch 20 → 21 taken 5482 times.
|
10030 | for (auto &structManifestations : structs | std::views::values) |
| 323 |
5/8✓ Branch 9 → 10 taken 4548 times.
✗ Branch 9 → 25 not taken.
✓ Branch 10 → 11 taken 4548 times.
✗ Branch 10 → 25 not taken.
✓ Branch 11 → 12 taken 4548 times.
✗ Branch 11 → 25 not taken.
✓ Branch 17 → 13 taken 4572 times.
✓ Branch 17 → 18 taken 4548 times.
|
9120 | for (auto &manifestation : structManifestations | std::views::values) |
| 324 |
1/2✓ Branch 14 → 15 taken 4572 times.
✗ Branch 14 → 24 not taken.
|
4572 | manifestations.push_back(&manifestation); |
| 325 | |||
| 326 | // Sort manifestations by declaration code location | ||
| 327 |
2/2✓ Branch 4 → 5 taken 36 times.
✓ Branch 4 → 6 taken 2682 times.
|
5436 | auto sortLambda = [](const Struct *lhs, const Struct *rhs) { return lhs->getDeclCodeLoc() < rhs->getDeclCodeLoc(); }; |
| 328 |
1/2✓ Branch 21 → 22 taken 5482 times.
✗ Branch 21 → 27 not taken.
|
5482 | std::ranges::sort(manifestations, sortLambda); |
| 329 | 5482 | return manifestations; | |
| 330 | − | } // LCOV_EXCL_LINE - false positive | |
| 331 | |||
| 332 | /** | ||
| 333 | * Retrieve all union manifestations in this scope in the order of their declaration | ||
| 334 | * | ||
| 335 | * @return All union manifestations in declaration order | ||
| 336 | */ | ||
| 337 | ✗ | std::vector<Union *> Scope::getAllUnionManifestationsInDeclarationOrder() { | |
| 338 | // Retrieve all union manifestations in this scope | ||
| 339 | ✗ | std::vector<Union *> manifestations; | |
| 340 | ✗ | manifestations.reserve(unions.size()); // Reserve at least the size of individual generic unions | |
| 341 | ✗ | for (auto &unionManifestations : unions | std::views::values) | |
| 342 | ✗ | for (auto &manifestation : unionManifestations | std::views::values) | |
| 343 | ✗ | manifestations.push_back(&manifestation); | |
| 344 | |||
| 345 | // Sort manifestations by declaration code location | ||
| 346 | ✗ | auto sortLambda = [](const Union *lhs, const Union *rhs) { return lhs->getDeclCodeLoc() < rhs->getDeclCodeLoc(); }; | |
| 347 | ✗ | std::ranges::sort(manifestations, sortLambda); | |
| 348 | ✗ | return manifestations; | |
| 349 | − | } // LCOV_EXCL_LINE - false positive | |
| 350 | |||
| 351 | /** | ||
| 352 | * Append a fingerprint of the manifestations the IR generator emits into the object file of the owning source file. | ||
| 353 | * Only final once type checking has converged. | ||
| 354 | * | ||
| 355 | * @param fingerprint Stream to append to | ||
| 356 | */ | ||
| 357 | 24 | void Scope::collectManifestationFingerprint(std::stringstream &fingerprint) const { // NOLINT(misc-no-recursion) | |
| 358 | // Mirrors the emission conditions of the IR generator. The tag encodes the registry, lowercase if the manifestation is unused. | ||
| 359 | 96 | const auto append = [&](const auto ®istry, char usedTag, char unusedTag) { | |
| 360 |
13/24auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<spice::compiler::CodeLoc, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > >, std::less<spice::compiler::CodeLoc>, std::allocator<std::pair<spice::compiler::CodeLoc const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > > > > > >(std::map<spice::compiler::CodeLoc, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > >, std::less<spice::compiler::CodeLoc>, std::allocator<std::pair<spice::compiler::CodeLoc const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > > > > > const&, char, char) const:
✓ Branch 2 → 3 taken 24 times.
✗ Branch 2 → 28 not taken.
✓ Branch 3 → 4 taken 24 times.
✗ Branch 3 → 28 not taken.
✓ Branch 4 → 5 taken 24 times.
✗ Branch 4 → 28 not taken.
✗ Branch 25 → 6 not taken.
✓ Branch 25 → 26 taken 24 times.
auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > > > > > >(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > > > > > const&, char, char) const:
✓ Branch 2 → 3 taken 24 times.
✗ Branch 2 → 28 not taken.
✓ Branch 3 → 4 taken 24 times.
✗ Branch 3 → 28 not taken.
✓ Branch 4 → 5 taken 24 times.
✗ Branch 4 → 28 not taken.
✗ Branch 25 → 6 not taken.
✓ Branch 25 → 26 taken 24 times.
auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > > > > > >(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > > > > > const&, char, char) const:
✓ Branch 2 → 3 taken 24 times.
✗ Branch 2 → 28 not taken.
✓ Branch 3 → 4 taken 24 times.
✗ Branch 3 → 28 not taken.
✓ Branch 4 → 5 taken 24 times.
✗ Branch 4 → 28 not taken.
✓ Branch 25 → 6 taken 12 times.
✓ Branch 25 → 26 taken 24 times.
|
156 | for (const auto &manifestations : registry | std::views::values) |
| 361 |
2/6auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<spice::compiler::CodeLoc, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > >, std::less<spice::compiler::CodeLoc>, std::allocator<std::pair<spice::compiler::CodeLoc const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > > > > > >(std::map<spice::compiler::CodeLoc, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > >, std::less<spice::compiler::CodeLoc>, std::allocator<std::pair<spice::compiler::CodeLoc const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > > > > > const&, char, char) const:
✗ Branch 22 → 9 not taken.
✗ Branch 22 → 23 not taken.
auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > > > > > >(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > > > > > const&, char, char) const:
✗ Branch 22 → 9 not taken.
✗ Branch 22 → 23 not taken.
auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > > > > > >(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > > > > > const&, char, char) const:
✓ Branch 22 → 9 taken 16 times.
✓ Branch 22 → 23 taken 12 times.
|
28 | for (const auto &[mangledName, manifestation] : manifestations) |
| 362 |
3/12auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<spice::compiler::CodeLoc, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > >, std::less<spice::compiler::CodeLoc>, std::allocator<std::pair<spice::compiler::CodeLoc const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > > > > > >(std::map<spice::compiler::CodeLoc, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > >, std::less<spice::compiler::CodeLoc>, std::allocator<std::pair<spice::compiler::CodeLoc const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > > > > > const&, char, char) const:
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 27 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 20 not taken.
auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > > > > > >(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > > > > > const&, char, char) const:
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 27 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 20 not taken.
auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > > > > > >(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > > > > > const&, char, char) const:
✓ Branch 12 → 13 taken 16 times.
✗ Branch 12 → 27 not taken.
✓ Branch 13 → 14 taken 8 times.
✓ Branch 13 → 20 taken 8 times.
|
16 | if (manifestation.isFullySubstantiated()) |
| 363 |
4/24auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<spice::compiler::CodeLoc, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > >, std::less<spice::compiler::CodeLoc>, std::allocator<std::pair<spice::compiler::CodeLoc const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > > > > > >(std::map<spice::compiler::CodeLoc, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > >, std::less<spice::compiler::CodeLoc>, std::allocator<std::pair<spice::compiler::CodeLoc const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Interface, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Interface> > > > > > const&, char, char) const:
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 16 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 27 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 27 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 19 → 27 not taken.
auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > > > > > >(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Struct, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Struct> > > > > > const&, char, char) const:
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 16 not taken.
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 27 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 27 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 19 → 27 not taken.
auto spice::compiler::Scope::collectManifestationFingerprint(std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >&) const::{lambda(auto:1 const&, char, char)#1}::operator()<std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > > > > > >(std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, spice::compiler::Function, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, spice::compiler::Function> > > > > > const&, char, char) const:
✓ Branch 14 → 15 taken 8 times.
✗ Branch 14 → 16 not taken.
✓ Branch 17 → 18 taken 8 times.
✗ Branch 17 → 27 not taken.
✓ Branch 18 → 19 taken 8 times.
✗ Branch 18 → 27 not taken.
✓ Branch 19 → 20 taken 8 times.
✗ Branch 19 → 27 not taken.
|
8 | fingerprint << (manifestation.used ? usedTag : unusedTag) << mangledName << '\n'; |
| 364 | 96 | }; | |
| 365 |
1/2✓ Branch 2 → 3 taken 24 times.
✗ Branch 2 → 24 not taken.
|
24 | append(functions, 'F', 'f'); |
| 366 |
1/2✓ Branch 3 → 4 taken 24 times.
✗ Branch 3 → 24 not taken.
|
24 | append(structs, 'S', 's'); |
| 367 |
1/2✓ Branch 4 → 5 taken 24 times.
✗ Branch 4 → 24 not taken.
|
24 | append(interfaces, 'I', 'i'); |
| 368 | |||
| 369 | // Definitions cannot be nested into function bodies, so only struct and interface scopes hold further manifestations | ||
| 370 |
5/8✓ Branch 5 → 6 taken 24 times.
✗ Branch 5 → 23 not taken.
✓ Branch 6 → 7 taken 24 times.
✗ Branch 6 → 23 not taken.
✓ Branch 7 → 8 taken 24 times.
✗ Branch 7 → 23 not taken.
✓ Branch 21 → 9 taken 28 times.
✓ Branch 21 → 22 taken 24 times.
|
52 | for (const std::shared_ptr<Scope> &child : children | std::views::values) |
| 371 |
3/6✓ Branch 11 → 12 taken 28 times.
✗ Branch 11 → 14 not taken.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 28 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 19 taken 28 times.
|
28 | if (child->type == ScopeType::STRUCT || child->type == ScopeType::INTERFACE) |
| 372 | ✗ | child->collectManifestationFingerprint(fingerprint); | |
| 373 | 24 | } | |
| 374 | |||
| 375 | /** | ||
| 376 | * Get the current number of nested loops | ||
| 377 | * | ||
| 378 | * @return Number of loops | ||
| 379 | */ | ||
| 380 | 15992 | unsigned int Scope::getLoopNestingDepth() const { // NOLINT(misc-no-recursion) | |
| 381 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 15992 times.
|
15992 | assert(!isRootScope()); |
| 382 |
2/2✓ Branch 6 → 7 taken 3068 times.
✓ Branch 6 → 8 taken 12924 times.
|
15992 | if (parent->parent == nullptr) |
| 383 | 3068 | return 0; | |
| 384 | 12924 | unsigned int loopCount = parent->getLoopNestingDepth(); | |
| 385 |
6/6✓ Branch 9 → 10 taken 11791 times.
✓ Branch 9 → 12 taken 1133 times.
✓ Branch 10 → 11 taken 8441 times.
✓ Branch 10 → 12 taken 3350 times.
✓ Branch 11 → 12 taken 392 times.
✓ Branch 11 → 13 taken 8049 times.
|
12924 | if (type == ScopeType::WHILE_BODY || type == ScopeType::FOR_BODY || type == ScopeType::FOREACH_BODY) |
| 386 | 4875 | loopCount++; | |
| 387 | 12924 | return loopCount; | |
| 388 | } | ||
| 389 | |||
| 390 | /** | ||
| 391 | * Get the nearest enclosing function/procedure/lambda body scope, including this scope itself | ||
| 392 | * | ||
| 393 | * @return Nearest enclosing function/procedure/lambda body scope | ||
| 394 | */ | ||
| 395 | 108910 | Scope *Scope::getFunctionScope() { // NOLINT(misc-no-recursion) | |
| 396 |
4/4✓ Branch 2 → 3 taken 38302 times.
✓ Branch 2 → 4 taken 70608 times.
✓ Branch 3 → 4 taken 122 times.
✓ Branch 3 → 5 taken 38180 times.
|
108910 | if (type == ScopeType::FUNC_PROC_BODY || type == ScopeType::LAMBDA_BODY) |
| 397 | 70730 | return this; | |
| 398 |
1/2✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 38180 times.
|
38180 | assert(!isRootScope()); |
| 399 | 38180 | return parent->getFunctionScope(); | |
| 400 | } | ||
| 401 | |||
| 402 | /** | ||
| 403 | * Check if this scope is one of the child scopes of a switch statement | ||
| 404 | * | ||
| 405 | * @return Child scope of switch statement or not | ||
| 406 | */ | ||
| 407 | 14 | bool Scope::isInCaseBranch() const { // NOLINT(misc-no-recursion) | |
| 408 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 14 times.
|
14 | assert(!isRootScope()); |
| 409 |
2/2✓ Branch 6 → 7 taken 4 times.
✓ Branch 6 → 8 taken 10 times.
|
14 | if (parent->parent == nullptr) |
| 410 | 4 | return false; | |
| 411 |
2/2✓ Branch 8 → 9 taken 8 times.
✓ Branch 8 → 10 taken 2 times.
|
10 | if (type == ScopeType::CASE_BODY) |
| 412 | 8 | return true; | |
| 413 | 2 | return parent->isInCaseBranch(); | |
| 414 | } | ||
| 415 | |||
| 416 | /** | ||
| 417 | * Check if this scope is within an async scope | ||
| 418 | * | ||
| 419 | * @return Within async scope or not | ||
| 420 | */ | ||
| 421 | 362 | bool Scope::isInAsyncScope() const { // NOLINT(misc-no-recursion) | |
| 422 |
2/2✓ Branch 2 → 3 taken 42 times.
✓ Branch 2 → 4 taken 320 times.
|
362 | if (isAsyncScope) |
| 423 | 42 | return true; | |
| 424 |
3/4✓ Branch 6 → 7 taken 205 times.
✓ Branch 6 → 10 taken 115 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 205 times.
|
320 | return !isRootScope() && parent->isInAsyncScope(); |
| 425 | } | ||
| 426 | |||
| 427 | /** | ||
| 428 | * Check if unsafe operations are allowed in this scope | ||
| 429 | * | ||
| 430 | * @return Allowed or not | ||
| 431 | */ | ||
| 432 | 129656 | bool Scope::doesAllowUnsafeOperations() const { // NOLINT(misc-no-recursion) | |
| 433 |
2/2✓ Branch 2 → 3 taken 28544 times.
✓ Branch 2 → 4 taken 101112 times.
|
129656 | if (type == ScopeType::UNSAFE_BODY) |
| 434 | 28544 | return true; | |
| 435 |
4/4✓ Branch 6 → 7 taken 75389 times.
✓ Branch 6 → 10 taken 25723 times.
✓ Branch 8 → 9 taken 16507 times.
✓ Branch 8 → 10 taken 58882 times.
|
101112 | return !isRootScope() && parent->doesAllowUnsafeOperations(); |
| 436 | } | ||
| 437 | |||
| 438 | /** | ||
| 439 | * Checks if this scope is imported | ||
| 440 | * | ||
| 441 | * @param askingScope Scope, which asks whether the current one is imported from its point of view or not | ||
| 442 | * | ||
| 443 | * @return Imported / not imported | ||
| 444 | */ | ||
| 445 | 628911 | bool Scope::isImportedBy(const Scope *askingScope) const { return askingScope->sourceFile->imports(sourceFile); } | |
| 446 | |||
| 447 | /** | ||
| 448 | * Get JSON representation of the symbol table | ||
| 449 | * | ||
| 450 | * @return Symbol table as JSON object | ||
| 451 | */ | ||
| 452 | 952783 | nlohmann::json Scope::getSymbolTableJSON() const { // NOLINT(misc-no-recursion) | |
| 453 |
1/2✓ Branch 2 → 3 taken 952783 times.
✗ Branch 2 → 42 not taken.
|
952783 | nlohmann::json result = symbolTable.toJSON(); |
| 454 | |||
| 455 | // Collect all children | ||
| 456 | 952783 | std::vector<nlohmann::json> jsonChildren; | |
| 457 |
1/2✓ Branch 4 → 5 taken 952783 times.
✗ Branch 4 → 38 not taken.
|
952783 | jsonChildren.reserve(children.size()); |
| 458 |
2/2✓ Branch 20 → 7 taken 939097 times.
✓ Branch 20 → 21 taken 952783 times.
|
1891880 | for (const auto &[name, childScope] : children) { |
| 459 |
1/2✓ Branch 11 → 12 taken 939097 times.
✗ Branch 11 → 33 not taken.
|
939097 | nlohmann::json c = childScope->getSymbolTableJSON(); |
| 460 |
2/4✓ Branch 12 → 13 taken 939097 times.
✗ Branch 12 → 30 not taken.
✓ Branch 13 → 14 taken 939097 times.
✗ Branch 13 → 28 not taken.
|
939097 | c["name"] = name; // Inject symbol table name into JSON object |
| 461 |
1/2✓ Branch 16 → 17 taken 939097 times.
✗ Branch 16 → 31 not taken.
|
939097 | jsonChildren.emplace_back(c); |
| 462 | 939097 | } | |
| 463 |
2/4✓ Branch 21 → 22 taken 952783 times.
✗ Branch 21 → 37 not taken.
✓ Branch 22 → 23 taken 952783 times.
✗ Branch 22 → 35 not taken.
|
952783 | result["children"] = jsonChildren; |
| 464 | |||
| 465 | 952783 | return result; | |
| 466 | 952783 | } | |
| 467 | |||
| 468 | } // namespace spice::compiler | ||
| 469 |