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 | 202242 | Scope::Scope(Scope *parent, SourceFile *sourceFile, ScopeType scopeType, const CodeLoc *codeLoc) | |
| 14 | 202242 | : parent(parent), sourceFile(sourceFile), scopeId(sourceFile->resourceManager.getNextScopeId()), codeLoc(codeLoc), | |
| 15 |
2/2✓ Branch 4 → 5 taken 197035 times.
✓ Branch 4 → 6 taken 5207 times.
|
202242 | 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 | 197035 | Scope *Scope::createChildScope(const std::string &scopeName, ScopeType scopeType, const CodeLoc *declCodeLoc) { | |
| 26 |
2/4✓ Branch 2 → 3 taken 197035 times.
✗ Branch 2 → 15 not taken.
✓ Branch 3 → 4 taken 197035 times.
✗ Branch 3 → 13 not taken.
|
197035 | 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 197035 times.
|
197035 | assert(inserted); |
| 28 | 394070 | 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 | 68530 | void Scope::renameChildScope(const std::string &oldName, const std::string &newName) { | |
| 39 |
4/8✓ Branch 2 → 3 taken 68530 times.
✗ Branch 2 → 20 not taken.
✓ Branch 3 → 4 taken 68530 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 68530 times.
✗ Branch 4 → 20 not taken.
✓ Branch 5 → 6 taken 68530 times.
✗ Branch 5 → 7 not taken.
|
68530 | assert(children.contains(oldName) && !children.contains(newName)); |
| 40 |
1/2✓ Branch 8 → 9 taken 68530 times.
✗ Branch 8 → 20 not taken.
|
68530 | auto nodeHandler = children.extract(oldName); |
| 41 |
1/2✓ Branch 10 → 11 taken 68530 times.
✗ Branch 10 → 18 not taken.
|
68530 | nodeHandler.key() = newName; |
| 42 |
1/2✓ Branch 13 → 14 taken 68530 times.
✗ Branch 13 → 17 not taken.
|
137060 | children.insert(std::move(nodeHandler)); |
| 43 | 68530 | } | |
| 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 | 27199 | Scope *Scope::copyChildScope(const std::string &oldName, const std::string &newName) { | |
| 52 |
4/8✓ Branch 2 → 3 taken 27199 times.
✗ Branch 2 → 18 not taken.
✓ Branch 3 → 4 taken 27199 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 27199 times.
✗ Branch 4 → 18 not taken.
✓ Branch 5 → 6 taken 27199 times.
✗ Branch 5 → 7 not taken.
|
27199 | assert(children.contains(oldName) && !children.contains(newName)); |
| 53 | // Create copy | ||
| 54 |
2/4✓ Branch 8 → 9 taken 27199 times.
✗ Branch 8 → 18 not taken.
✓ Branch 10 → 11 taken 27199 times.
✗ Branch 10 → 18 not taken.
|
27199 | const std::shared_ptr<Scope> newScope = children.at(oldName)->deepCopyScope(); |
| 55 | // Save copy under new name | ||
| 56 |
1/2✓ Branch 11 → 12 taken 27199 times.
✗ Branch 11 → 16 not taken.
|
27199 | children.emplace(newName, newScope); |
| 57 | 54398 | return newScope.get(); | |
| 58 | 27199 | } | |
| 59 | |||
| 60 | /** | ||
| 61 | * Deep copy the current scope and all its children | ||
| 62 | * | ||
| 63 | * @return Deep copy of the current scope | ||
| 64 | */ | ||
| 65 | 145959 | std::shared_ptr<Scope> Scope::deepCopyScope() { // NOLINT(misc-no-recursion) | |
| 66 | 145959 | const auto newScope = std::make_shared<Scope>(*this); | |
| 67 |
1/2✓ Branch 3 → 4 taken 145959 times.
✗ Branch 3 → 41 not taken.
|
145959 | newScope->scopeId = sourceFile->resourceManager.getNextScopeId(); |
| 68 |
2/2✓ Branch 32 → 7 taken 118760 times.
✓ Branch 32 → 33 taken 145959 times.
|
264719 | for (const auto &[childName, oldChild] : children) { |
| 69 |
2/4✓ Branch 11 → 12 taken 118760 times.
✗ Branch 11 → 39 not taken.
✓ Branch 13 → 14 taken 118760 times.
✗ Branch 13 → 37 not taken.
|
118760 | newScope->children[childName] = oldChild->deepCopyScope(); |
| 70 |
1/2✓ Branch 18 → 19 taken 118760 times.
✗ Branch 18 → 40 not taken.
|
118760 | newScope->children[childName]->parent = newScope.get(); |
| 71 |
2/4✓ Branch 21 → 22 taken 118760 times.
✗ Branch 21 → 40 not taken.
✓ Branch 24 → 25 taken 118760 times.
✗ Branch 24 → 40 not taken.
|
118760 | newScope->children[childName]->symbolTable.scope = newScope->children[childName].get(); |
| 72 |
1/2✓ Branch 28 → 29 taken 118760 times.
✗ Branch 28 → 40 not taken.
|
118760 | newScope->children[childName]->symbolTable.parent = &newScope->symbolTable; |
| 73 | } | ||
| 74 | 145959 | newScope->symbolTable.scope = newScope.get(); | |
| 75 | 145959 | 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 | 431389 | Scope *Scope::getChildScope(const std::string &scopeName) const { | |
| 85 |
1/2✓ Branch 2 → 3 taken 431389 times.
✗ Branch 2 → 12 not taken.
|
431389 | const auto it = children.find(scopeName); |
| 86 |
2/2✓ Branch 5 → 6 taken 431343 times.
✓ Branch 5 → 8 taken 46 times.
|
862778 | 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 | 192801 | std::vector<SymbolTableEntry *> Scope::getVarsGoingOutOfScope() { // NOLINT(misc-no-recursion) | |
| 95 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 192801 times.
|
192801 | assert(!isRootScope()); // Should not be called in root scope |
| 96 | 192801 | std::vector<SymbolTableEntry *> varsGoingOutOfScope; | |
| 97 | |||
| 98 | // Collect all variables in this scope | ||
| 99 |
2/2✓ Branch 26 → 8 taken 203450 times.
✓ Branch 26 → 27 taken 192801 times.
|
396251 | for (const auto &[name, entry] : symbolTable.symbols) { |
| 100 | // Skip 'this' and result variables | ||
| 101 |
8/10✓ Branch 11 → 12 taken 203450 times.
✗ Branch 11 → 52 not taken.
✓ Branch 12 → 13 taken 164383 times.
✓ Branch 12 → 15 taken 39067 times.
✓ Branch 13 → 14 taken 164383 times.
✗ Branch 13 → 52 not taken.
✓ Branch 14 → 15 taken 38894 times.
✓ Branch 14 → 16 taken 125489 times.
✓ Branch 17 → 18 taken 77961 times.
✓ Branch 17 → 19 taken 125489 times.
|
203450 | if (name == THIS_VARIABLE_NAME || name == RETURN_VARIABLE_NAME) |
| 102 | 77961 | continue; | |
| 103 | // Skip parameters (ToDo: Remove when copy constructors work for by-value argument passing) | ||
| 104 |
2/2✓ Branch 19 → 20 taken 74726 times.
✓ Branch 19 → 21 taken 50763 times.
|
125489 | if (entry.isParam) |
| 105 | 74726 | continue; | |
| 106 | // Found variable, that goes out of scope | ||
| 107 |
2/4✓ Branch 21 → 22 taken 50763 times.
✗ Branch 21 → 51 not taken.
✓ Branch 22 → 23 taken 50763 times.
✗ Branch 22 → 51 not taken.
|
50763 | 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 1018 times.
✓ Branch 27 → 49 taken 191783 times.
|
192801 | if (isDtorScope) { |
| 112 |
2/4✓ Branch 30 → 31 taken 1018 times.
✗ Branch 30 → 33 not taken.
✓ Branch 31 → 32 taken 1018 times.
✗ Branch 31 → 33 not taken.
|
1018 | assert(!isRootScope() && parent->type == ScopeType::STRUCT); |
| 113 | // Get all fields of the struct | ||
| 114 |
2/2✓ Branch 47 → 36 taken 33882 times.
✓ Branch 47 → 48 taken 1018 times.
|
34900 | for (const auto &[name, entry] : parent->symbolTable.symbols) |
| 115 |
4/6✓ Branch 39 → 40 taken 33882 times.
✗ Branch 39 → 55 not taken.
✓ Branch 40 → 41 taken 33882 times.
✗ Branch 40 → 53 not taken.
✓ Branch 41 → 42 taken 3286 times.
✓ Branch 41 → 45 taken 30596 times.
|
33882 | if (!entry.getQualType().isOneOf({TY_FUNCTION, TY_PROCEDURE})) |
| 116 |
2/4✓ Branch 42 → 43 taken 3286 times.
✗ Branch 42 → 54 not taken.
✓ Branch 43 → 44 taken 3286 times.
✗ Branch 43 → 54 not taken.
|
3286 | varsGoingOutOfScope.push_back(&parent->symbolTable.symbols.at(name)); |
| 117 | } | ||
| 118 | |||
| 119 | 192801 | 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 | 26888 | void Scope::insertGenericType(const std::string &typeName, const GenericType &genericType) { | |
| 129 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 26888 times.
|
26888 | assert(!genericTypes.contains(typeName)); |
| 130 | 26888 | genericTypes.emplace(typeName, genericType); | |
| 131 | 26888 | } | |
| 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 | 206970 | GenericType *Scope::lookupGenericTypeStrict(const std::string &typeName) { | |
| 141 |
1/2✓ Branch 2 → 3 taken 206970 times.
✗ Branch 2 → 12 not taken.
|
206970 | const auto it = genericTypes.find(typeName); |
| 142 |
2/2✓ Branch 5 → 6 taken 78721 times.
✓ Branch 5 → 8 taken 128249 times.
|
413940 | 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 | 8109 | void Scope::collectWarnings(std::vector<CompilerWarning> &warnings) const { // NOLINT(misc-no-recursion) | |
| 152 | // Visit own symbols | ||
| 153 |
5/8✓ Branch 2 → 3 taken 8109 times.
✗ Branch 2 → 239 not taken.
✓ Branch 3 → 4 taken 8109 times.
✗ Branch 3 → 239 not taken.
✓ Branch 4 → 5 taken 8109 times.
✗ Branch 4 → 239 not taken.
✓ Branch 163 → 6 taken 23720 times.
✓ Branch 163 → 164 taken 8109 times.
|
31829 | 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 | 23720 | const std::string &name = entry.name; | |
| 156 |
6/6✓ Branch 7 → 8 taken 763 times.
✓ Branch 7 → 10 taken 22957 times.
✓ Branch 9 → 10 taken 260 times.
✓ Branch 9 → 11 taken 503 times.
✓ Branch 12 → 13 taken 23217 times.
✓ Branch 12 → 14 taken 503 times.
|
23720 | if (entry.used || name.starts_with(UNUSED_VARIABLE_NAME)) |
| 157 | 23347 | continue; | |
| 158 | |||
| 159 |
1/2✓ Branch 14 → 15 taken 503 times.
✗ Branch 14 → 238 not taken.
|
503 | 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 15 → 16 taken 503 times.
✗ Branch 15 → 238 not taken.
✓ Branch 16 → 17 taken 180 times.
✓ Branch 16 → 19 taken 323 times.
✓ Branch 17 → 18 taken 180 times.
✗ Branch 17 → 238 not taken.
✓ Branch 18 → 19 taken 4 times.
✓ Branch 18 → 24 taken 176 times.
✓ Branch 19 → 20 taken 327 times.
✗ Branch 19 → 238 not taken.
✓ Branch 20 → 21 taken 153 times.
✓ Branch 20 → 24 taken 174 times.
✓ Branch 21 → 22 taken 153 times.
✗ Branch 21 → 238 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 153 times.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 503 times.
|
503 | 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 | 503 | CompilerWarningType warningType = UNUSED_VARIABLE; | |
| 170 | 503 | std::string warningMessage; | |
| 171 |
4/4✓ Branch 28 → 29 taken 36 times.
✓ Branch 28 → 112 taken 236 times.
✓ Branch 28 → 141 taken 8 times.
✓ Branch 28 → 147 taken 223 times.
|
503 | switch (type) { |
| 172 | 36 | case ScopeType::GLOBAL: { | |
| 173 | // Skip generic function/procedure/struct/interface/union entries | ||
| 174 |
4/6✓ Branch 29 → 30 taken 36 times.
✗ Branch 29 → 177 not taken.
✓ Branch 30 → 31 taken 22 times.
✓ Branch 30 → 35 taken 14 times.
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 38 taken 36 times.
|
58 | if (entryType.isOneOf({TY_FUNCTION, TY_PROCEDURE, TY_STRUCT, TY_INTERFACE, TY_UNION}) && |
| 175 |
2/4✓ Branch 31 → 32 taken 22 times.
✗ Branch 31 → 177 not taken.
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 22 times.
|
22 | !entryType.getTemplateTypes().empty()) |
| 176 | ✗ | continue; | |
| 177 | |||
| 178 |
3/4✓ Branch 38 → 39 taken 36 times.
✗ Branch 38 → 236 not taken.
✓ Branch 39 → 40 taken 10 times.
✓ Branch 39 → 50 taken 26 times.
|
36 | if (entryType.is(TY_FUNCTION)) { |
| 179 |
1/2✓ Branch 40 → 41 taken 10 times.
✗ Branch 40 → 236 not taken.
|
10 | const std::vector<Function *> *fctManifestations = entry.declNode->getFctManifestations(name); |
| 180 | 10 | warningType = UNUSED_FUNCTION; | |
| 181 |
3/6✓ Branch 42 → 43 taken 10 times.
✗ Branch 42 → 182 not taken.
✓ Branch 43 → 44 taken 10 times.
✗ Branch 43 → 180 not taken.
✓ Branch 44 → 45 taken 10 times.
✗ Branch 44 → 178 not taken.
|
10 | warningMessage = "'" + fctManifestations->front()->getSignature() + "' is unused"; |
| 182 |
3/4✓ Branch 50 → 51 taken 26 times.
✗ Branch 50 → 236 not taken.
✓ Branch 51 → 52 taken 6 times.
✓ Branch 51 → 62 taken 20 times.
|
26 | } else if (entryType.is(TY_PROCEDURE)) { |
| 183 |
1/2✓ Branch 52 → 53 taken 6 times.
✗ Branch 52 → 236 not taken.
|
6 | const std::vector<Function *> *fctManifestations = entry.declNode->getFctManifestations(name); |
| 184 | 6 | warningType = UNUSED_PROCEDURE; | |
| 185 |
3/6✓ Branch 54 → 55 taken 6 times.
✗ Branch 54 → 189 not taken.
✓ Branch 55 → 56 taken 6 times.
✗ Branch 55 → 187 not taken.
✓ Branch 56 → 57 taken 6 times.
✗ Branch 56 → 185 not taken.
|
6 | warningMessage = "'" + fctManifestations->front()->getSignature() + "' is unused"; |
| 186 |
3/4✓ Branch 62 → 63 taken 20 times.
✗ Branch 62 → 236 not taken.
✓ Branch 63 → 64 taken 2 times.
✓ Branch 63 → 70 taken 18 times.
|
20 | } else if (entryType.is(TY_STRUCT)) { |
| 187 | 2 | warningType = UNUSED_STRUCT; | |
| 188 |
2/4✓ Branch 64 → 65 taken 2 times.
✗ Branch 64 → 194 not taken.
✓ Branch 65 → 66 taken 2 times.
✗ Branch 65 → 192 not taken.
|
2 | warningMessage = "The struct '" + entry.name + "' is unused"; |
| 189 |
3/4✓ Branch 70 → 71 taken 18 times.
✗ Branch 70 → 236 not taken.
✓ Branch 71 → 72 taken 2 times.
✓ Branch 71 → 78 taken 16 times.
|
18 | } else if (entryType.is(TY_INTERFACE)) { |
| 190 | 2 | warningType = UNUSED_INTERFACE; | |
| 191 |
2/4✓ Branch 72 → 73 taken 2 times.
✗ Branch 72 → 198 not taken.
✓ Branch 73 → 74 taken 2 times.
✗ Branch 73 → 196 not taken.
|
2 | warningMessage = "The interface '" + entry.name + "' is unused"; |
| 192 |
3/4✓ Branch 78 → 79 taken 16 times.
✗ Branch 78 → 236 not taken.
✓ Branch 79 → 80 taken 2 times.
✓ Branch 79 → 86 taken 14 times.
|
16 | } else if (entryType.is(TY_UNION)) { |
| 193 | 2 | warningType = UNUSED_UNION; | |
| 194 |
2/4✓ Branch 80 → 81 taken 2 times.
✗ Branch 80 → 202 not taken.
✓ Branch 81 → 82 taken 2 times.
✗ Branch 81 → 200 not taken.
|
2 | warningMessage = "The union '" + entry.name + "' is unused"; |
| 195 |
3/4✓ Branch 86 → 87 taken 14 times.
✗ Branch 86 → 236 not taken.
✓ Branch 87 → 88 taken 4 times.
✓ Branch 87 → 89 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 89 → 90 taken 10 times.
✗ Branch 89 → 236 not taken.
✓ Branch 90 → 91 taken 8 times.
✓ Branch 90 → 97 taken 2 times.
|
10 | } else if (entryType.is(TY_IMPORT)) { |
| 198 | 8 | warningType = UNUSED_IMPORT; | |
| 199 |
2/4✓ Branch 91 → 92 taken 8 times.
✗ Branch 91 → 206 not taken.
✓ Branch 92 → 93 taken 8 times.
✗ Branch 92 → 204 not taken.
|
8 | warningMessage = "The import '" + entry.name + "' is unused"; |
| 200 |
2/4✓ Branch 97 → 98 taken 2 times.
✗ Branch 97 → 236 not taken.
✓ Branch 98 → 99 taken 2 times.
✗ Branch 98 → 105 not taken.
|
2 | } else if (entryType.is(TY_ALIAS)) { |
| 201 | 2 | warningType = UNUSED_ALIAS; | |
| 202 |
2/4✓ Branch 99 → 100 taken 2 times.
✗ Branch 99 → 210 not taken.
✓ Branch 100 → 101 taken 2 times.
✗ Branch 100 → 208 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 | 236 | case ScopeType::STRUCT: // fall-through | |
| 211 | case ScopeType::INTERFACE: // fall-through | ||
| 212 | case ScopeType::UNION: { | ||
| 213 |
3/4✓ Branch 112 → 113 taken 236 times.
✗ Branch 112 → 236 not taken.
✓ Branch 113 → 114 taken 90 times.
✓ Branch 113 → 120 taken 146 times.
|
236 | if (entry.isField()) { |
| 214 | 90 | warningType = UNUSED_FIELD; | |
| 215 |
2/4✓ Branch 114 → 115 taken 90 times.
✗ Branch 114 → 218 not taken.
✓ Branch 115 → 116 taken 90 times.
✗ Branch 115 → 216 not taken.
|
90 | warningMessage = "The field '" + entry.name + "' is unused"; |
| 216 |
2/4✓ Branch 120 → 121 taken 146 times.
✗ Branch 120 → 220 not taken.
✓ Branch 121 → 122 taken 146 times.
✗ Branch 121 → 140 not taken.
|
146 | } else if (entryType.isOneOf({TY_FUNCTION, TY_PROCEDURE})) { |
| 217 | // Skip implicit method entries and generic templates | ||
| 218 |
1/2✓ Branch 122 → 123 taken 146 times.
✗ Branch 122 → 236 not taken.
|
146 | const std::vector<Function *> *fctManifestations = entry.declNode->getFctManifestations(name); |
| 219 |
5/6✓ Branch 124 → 125 taken 20 times.
✓ Branch 124 → 127 taken 126 times.
✗ Branch 126 → 127 not taken.
✓ Branch 126 → 128 taken 20 times.
✓ Branch 129 → 130 taken 126 times.
✓ Branch 129 → 131 taken 20 times.
|
146 | if (fctManifestations->empty() || fctManifestations->front()->implicitDefault) |
| 220 | 126 | continue; | |
| 221 | |||
| 222 | 20 | warningType = UNUSED_METHOD; | |
| 223 |
3/6✓ Branch 132 → 133 taken 20 times.
✗ Branch 132 → 225 not taken.
✓ Branch 133 → 134 taken 20 times.
✗ Branch 133 → 223 not taken.
✓ Branch 134 → 135 taken 20 times.
✗ Branch 134 → 221 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 141 → 142 taken 8 times.
✗ Branch 141 → 230 not taken.
✓ Branch 142 → 143 taken 8 times.
✗ Branch 142 → 228 not taken.
|
8 | warningMessage = "The enum item '" + entry.name + "' is unused"; |
| 230 | 8 | break; | |
| 231 | } | ||
| 232 | 223 | default: { | |
| 233 | 223 | warningType = UNUSED_VARIABLE; | |
| 234 |
2/4✓ Branch 147 → 148 taken 223 times.
✗ Branch 147 → 234 not taken.
✓ Branch 148 → 149 taken 223 times.
✗ Branch 148 → 232 not taken.
|
223 | warningMessage = "The variable '" + entry.name + "' is unused"; |
| 235 | 223 | break; | |
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | // Add warning | ||
| 240 |
2/4✓ Branch 153 → 154 taken 373 times.
✗ Branch 153 → 236 not taken.
✓ Branch 154 → 155 taken 373 times.
✗ Branch 154 → 236 not taken.
|
373 | warnings.emplace_back(entry.getDeclCodeLoc(), warningType, warningMessage); |
| 241 |
2/2✓ Branch 157 → 158 taken 373 times.
✓ Branch 157 → 160 taken 130 times.
|
503 | } |
| 242 | |||
| 243 | // Visit children | ||
| 244 |
5/8✓ Branch 164 → 165 taken 8109 times.
✗ Branch 164 → 240 not taken.
✓ Branch 165 → 166 taken 8109 times.
✗ Branch 165 → 240 not taken.
✓ Branch 166 → 167 taken 8109 times.
✗ Branch 166 → 240 not taken.
✓ Branch 175 → 168 taken 7567 times.
✓ Branch 175 → 176 taken 8109 times.
|
15676 | for (const auto &childScope : children | std::views::values) |
| 245 |
2/2✓ Branch 170 → 171 taken 7163 times.
✓ Branch 170 → 173 taken 404 times.
|
7567 | if (!childScope->isGenericScope) |
| 246 |
1/2✓ Branch 172 → 173 taken 7163 times.
✗ Branch 172 → 240 not taken.
|
7163 | childScope->collectWarnings(warnings); |
| 247 | 8109 | } | |
| 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 | 872621 | void Scope::ensureSuccessfulTypeInference() const { // NOLINT(misc-no-recursion) | |
| 254 | // Check symbols in this scope | ||
| 255 |
2/2✓ Branch 19 → 4 taken 1299621 times.
✓ Branch 19 → 20 taken 872619 times.
|
2172240 | for (auto &[name, entry] : symbolTable.symbols) |
| 256 |
4/6✓ Branch 7 → 8 taken 1299621 times.
✗ Branch 7 → 40 not taken.
✓ Branch 8 → 9 taken 1299621 times.
✗ Branch 8 → 40 not taken.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 17 taken 1299619 times.
|
1299621 | 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 872619 times.
✗ Branch 20 → 41 not taken.
✓ Branch 21 → 22 taken 872619 times.
✗ Branch 21 → 41 not taken.
✓ Branch 22 → 23 taken 872619 times.
✗ Branch 22 → 41 not taken.
✓ Branch 29 → 24 taken 859864 times.
✓ Branch 29 → 30 taken 872617 times.
|
1732481 | for (const auto &scope : children | std::views::values) |
| 261 |
2/2✓ Branch 26 → 27 taken 859862 times.
✓ Branch 26 → 41 taken 2 times.
|
859864 | scope->ensureSuccessfulTypeInference(); |
| 262 | 872617 | } | |
| 263 | |||
| 264 | /** | ||
| 265 | * Get the number of fields if this is a struct scope | ||
| 266 | * | ||
| 267 | * @return Number of fields | ||
| 268 | */ | ||
| 269 | 387783 | size_t Scope::getFieldCount() const { | |
| 270 |
3/4✓ Branch 2 → 3 taken 164 times.
✓ Branch 2 → 5 taken 387619 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 164 times.
|
387783 | assert(type == ScopeType::STRUCT || type == ScopeType::UNION); |
| 271 | 387783 | size_t fieldCount = 0; | |
| 272 |
5/8✓ Branch 5 → 6 taken 387783 times.
✗ Branch 5 → 32 not taken.
✓ Branch 6 → 7 taken 387783 times.
✗ Branch 6 → 32 not taken.
✓ Branch 7 → 8 taken 387783 times.
✗ Branch 7 → 32 not taken.
✓ Branch 29 → 9 taken 7915306 times.
✓ Branch 29 → 30 taken 387783 times.
|
8303089 | for (const auto &symbol : symbolTable.symbols | std::views::values) { |
| 273 |
1/2✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 7915306 times.
|
7915306 | if (symbol.anonymous) |
| 274 | ✗ | continue; | |
| 275 |
1/2✓ Branch 12 → 13 taken 7915306 times.
✗ Branch 12 → 32 not taken.
|
7915306 | const QualType &symbolType = symbol.getQualType(); |
| 276 |
2/4✓ Branch 13 → 14 taken 7915306 times.
✗ Branch 13 → 32 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 7915306 times.
|
7915306 | if (symbolType.is(TY_IMPORT)) |
| 277 | ✗ | continue; | |
| 278 | 7915306 | const ASTNode *declNode = symbol.declNode; | |
| 279 |
10/14✓ Branch 16 → 17 taken 7915306 times.
✗ Branch 16 → 32 not taken.
✓ Branch 17 → 18 taken 1479708 times.
✓ Branch 17 → 22 taken 6435598 times.
✓ Branch 18 → 19 taken 1479708 times.
✗ Branch 18 → 32 not taken.
✓ Branch 19 → 20 taken 1321478 times.
✓ Branch 19 → 22 taken 158230 times.
✓ Branch 20 → 21 taken 1321478 times.
✗ Branch 20 → 32 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 1321478 times.
✓ Branch 24 → 25 taken 6593828 times.
✓ Branch 24 → 26 taken 1321478 times.
|
7915306 | if (declNode->isFctOrProcDef() || declNode->isStructDef() || declNode->isUnionDef()) |
| 280 | 6593828 | continue; | |
| 281 | 1321478 | fieldCount++; | |
| 282 | } | ||
| 283 | 387783 | 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 | 4546 | std::vector<const Function *> Scope::getVirtualMethods() { | |
| 295 |
3/4✓ Branch 2 → 3 taken 2056 times.
✓ Branch 2 → 5 taken 2490 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2056 times.
|
4546 | assert(type == ScopeType::STRUCT || type == ScopeType::INTERFACE); |
| 296 | |||
| 297 | // Collect all virtual methods | ||
| 298 | 4546 | std::vector<const Function *> methods; | |
| 299 |
2/2✓ Branch 37 → 7 taken 34624 times.
✓ Branch 37 → 38 taken 4546 times.
|
39170 | for (auto &[fctId, manifestationList] : functions) { |
| 300 |
1/2✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 34624 times.
|
34624 | assert(!manifestationList.empty()); |
| 301 |
2/2✓ Branch 34 → 15 taken 50932 times.
✓ Branch 34 → 35 taken 34624 times.
|
85556 | for (auto &[mangledName, function] : manifestationList) |
| 302 |
2/2✓ Branch 27 → 28 taken 10488 times.
✓ Branch 27 → 32 taken 40444 times.
|
50932 | if (function.isVirtualMethod()) |
| 303 |
3/6✓ Branch 28 → 29 taken 10488 times.
✗ Branch 28 → 41 not taken.
✓ Branch 29 → 30 taken 10488 times.
✗ Branch 29 → 41 not taken.
✓ Branch 30 → 31 taken 10488 times.
✗ Branch 30 → 41 not taken.
|
10488 | 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 | 12680 | const auto pred = [](const Function *a, const Function *b) { return a->vtableIndex < b->vtableIndex; }; | |
| 308 |
1/2✓ Branch 38 → 39 taken 4546 times.
✗ Branch 38 → 44 not taken.
|
4546 | std::ranges::sort(methods, pred); |
| 309 | |||
| 310 | 4546 | 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 | 5109 | std::vector<Struct *> Scope::getAllStructManifestationsInDeclarationOrder() { | |
| 319 | // Retrieve all struct manifestations in this scope | ||
| 320 | 5109 | std::vector<Struct *> manifestations; | |
| 321 |
1/2✓ Branch 3 → 4 taken 5109 times.
✗ Branch 3 → 27 not taken.
|
5109 | manifestations.reserve(structs.size()); // Reserve at least the size of individual generic structs |
| 322 |
5/8✓ Branch 4 → 5 taken 5109 times.
✗ Branch 4 → 26 not taken.
✓ Branch 5 → 6 taken 5109 times.
✗ Branch 5 → 26 not taken.
✓ Branch 6 → 7 taken 5109 times.
✗ Branch 6 → 26 not taken.
✓ Branch 20 → 8 taken 4162 times.
✓ Branch 20 → 21 taken 5109 times.
|
9271 | for (auto &structManifestations : structs | std::views::values) |
| 323 |
5/8✓ Branch 9 → 10 taken 4162 times.
✗ Branch 9 → 25 not taken.
✓ Branch 10 → 11 taken 4162 times.
✗ Branch 10 → 25 not taken.
✓ Branch 11 → 12 taken 4162 times.
✗ Branch 11 → 25 not taken.
✓ Branch 17 → 13 taken 4182 times.
✓ Branch 17 → 18 taken 4162 times.
|
8344 | for (auto &manifestation : structManifestations | std::views::values) |
| 324 |
1/2✓ Branch 14 → 15 taken 4182 times.
✗ Branch 14 → 24 not taken.
|
4182 | manifestations.push_back(&manifestation); |
| 325 | |||
| 326 | // Sort manifestations by declaration code location | ||
| 327 |
2/2✓ Branch 4 → 5 taken 28 times.
✓ Branch 4 → 6 taken 2257 times.
|
4570 | auto sortLambda = [](const Struct *lhs, const Struct *rhs) { return lhs->getDeclCodeLoc() < rhs->getDeclCodeLoc(); }; |
| 328 |
1/2✓ Branch 21 → 22 taken 5109 times.
✗ Branch 21 → 27 not taken.
|
5109 | std::ranges::sort(manifestations, sortLambda); |
| 329 | 5109 | 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 | 15318 | unsigned int Scope::getLoopNestingDepth() const { // NOLINT(misc-no-recursion) | |
| 381 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 15318 times.
|
15318 | assert(!isRootScope()); |
| 382 |
2/2✓ Branch 6 → 7 taken 2940 times.
✓ Branch 6 → 8 taken 12378 times.
|
15318 | if (parent->parent == nullptr) |
| 383 | 2940 | return 0; | |
| 384 | 12378 | unsigned int loopCount = parent->getLoopNestingDepth(); | |
| 385 |
6/6✓ Branch 9 → 10 taken 11301 times.
✓ Branch 9 → 12 taken 1077 times.
✓ Branch 10 → 11 taken 8095 times.
✓ Branch 10 → 12 taken 3206 times.
✓ Branch 11 → 12 taken 392 times.
✓ Branch 11 → 13 taken 7703 times.
|
12378 | if (type == ScopeType::WHILE_BODY || type == ScopeType::FOR_BODY || type == ScopeType::FOREACH_BODY) |
| 386 | 4675 | loopCount++; | |
| 387 | 12378 | 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 | 102707 | Scope *Scope::getFunctionScope() { // NOLINT(misc-no-recursion) | |
| 396 |
4/4✓ Branch 2 → 3 taken 36396 times.
✓ Branch 2 → 4 taken 66311 times.
✓ Branch 3 → 4 taken 113 times.
✓ Branch 3 → 5 taken 36283 times.
|
102707 | if (type == ScopeType::FUNC_PROC_BODY || type == ScopeType::LAMBDA_BODY) |
| 397 | 66424 | return this; | |
| 398 |
1/2✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 36283 times.
|
36283 | assert(!isRootScope()); |
| 399 | 36283 | 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 | 292 | bool Scope::isInAsyncScope() const { // NOLINT(misc-no-recursion) | |
| 422 |
2/2✓ Branch 2 → 3 taken 22 times.
✓ Branch 2 → 4 taken 270 times.
|
292 | if (isAsyncScope) |
| 423 | 22 | return true; | |
| 424 |
3/4✓ Branch 6 → 7 taken 177 times.
✓ Branch 6 → 10 taken 93 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 177 times.
|
270 | 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 | 121760 | bool Scope::doesAllowUnsafeOperations() const { // NOLINT(misc-no-recursion) | |
| 433 |
2/2✓ Branch 2 → 3 taken 26698 times.
✓ Branch 2 → 4 taken 95062 times.
|
121760 | if (type == ScopeType::UNSAFE_BODY) |
| 434 | 26698 | return true; | |
| 435 |
4/4✓ Branch 6 → 7 taken 70965 times.
✓ Branch 6 → 10 taken 24097 times.
✓ Branch 8 → 9 taken 15539 times.
✓ Branch 8 → 10 taken 55426 times.
|
95062 | 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 | 590486 | 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 | 872697 | nlohmann::json Scope::getSymbolTableJSON() const { // NOLINT(misc-no-recursion) | |
| 453 |
1/2✓ Branch 2 → 3 taken 872697 times.
✗ Branch 2 → 42 not taken.
|
872697 | nlohmann::json result = symbolTable.toJSON(); |
| 454 | |||
| 455 | // Collect all children | ||
| 456 | 872697 | std::vector<nlohmann::json> jsonChildren; | |
| 457 |
1/2✓ Branch 4 → 5 taken 872697 times.
✗ Branch 4 → 38 not taken.
|
872697 | jsonChildren.reserve(children.size()); |
| 458 |
2/2✓ Branch 20 → 7 taken 859950 times.
✓ Branch 20 → 21 taken 872697 times.
|
1732647 | for (const auto &[name, childScope] : children) { |
| 459 |
1/2✓ Branch 11 → 12 taken 859950 times.
✗ Branch 11 → 33 not taken.
|
859950 | nlohmann::json c = childScope->getSymbolTableJSON(); |
| 460 |
2/4✓ Branch 12 → 13 taken 859950 times.
✗ Branch 12 → 30 not taken.
✓ Branch 13 → 14 taken 859950 times.
✗ Branch 13 → 28 not taken.
|
859950 | c["name"] = name; // Inject symbol table name into JSON object |
| 461 |
1/2✓ Branch 16 → 17 taken 859950 times.
✗ Branch 16 → 31 not taken.
|
859950 | jsonChildren.emplace_back(c); |
| 462 | 859950 | } | |
| 463 |
2/4✓ Branch 21 → 22 taken 872697 times.
✗ Branch 21 → 37 not taken.
✓ Branch 22 → 23 taken 872697 times.
✗ Branch 22 → 35 not taken.
|
872697 | result["children"] = jsonChildren; |
| 464 | |||
| 465 | 872697 | return result; | |
| 466 | 872697 | } | |
| 467 | |||
| 468 | } // namespace spice::compiler | ||
| 469 |