GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 93.0% 119 / 0 / 128
Functions: 92.9% 13 / 0 / 14
Branches: 63.9% 170 / 0 / 266

src/typechecker/TypeChecker.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "TypeChecker.h"
4
5 #include <unordered_set>
6
7 #include <SourceFile.h>
8 #include <ast/Attributes.h>
9 #include <global/GlobalResourceManager.h>
10 #include <symboltablebuilder/Scope.h>
11 #include <symboltablebuilder/SymbolTableBuilder.h>
12 #include <typechecker/FunctionManager.h>
13
14 namespace spice::compiler {
15
16 10326 TypeChecker::TypeChecker(GlobalResourceManager &resourceManager, SourceFile *sourceFile, TypeCheckerMode typeCheckerMode)
17
1/2
✓ Branch 4 → 5 taken 10326 times.
✗ Branch 4 → 7 not taken.
10326 : CompilerPass(resourceManager, sourceFile), typeCheckerMode(typeCheckerMode), warnings(sourceFile->compilerOutput.warnings) {
18 10326 }
19
20 /**
21 * Check whether the given struct and all of its by-value struct fields are manifested, transitively. While a circular
22 * import is still being prepared, a by-value struct field may (transitively) reference a struct that is not manifested
23 * yet; generating implicit special members for such a struct recurses through isTriviallyConstructible and would
24 * dereference a null struct lookup. A genuine infinite-size containment cycle among these structs is reported
25 * separately by the infinite-size check during struct preparation, so a containment cycle here is treated as manifested.
26 */
27 8712 static bool structFullyManifested(const Struct *spiceStruct, const ASTNode *node, std::unordered_set<const Scope *> &visited) {
28
2/2
✓ Branch 29 → 4 taken 20776 times.
✓ Branch 29 → 30 taken 8711 times.
38199 for (const QualType &fieldType : spiceStruct->fieldTypes) {
29
3/4
✓ Branch 6 → 7 taken 20776 times.
✗ Branch 6 → 33 not taken.
✓ Branch 7 → 8 taken 15040 times.
✓ Branch 7 → 9 taken 5736 times.
20776 if (!fieldType.is(TY_STRUCT))
30 15040 continue;
31
1/2
✓ Branch 9 → 10 taken 5736 times.
✗ Branch 9 → 33 not taken.
5736 const Struct *fieldStruct = fieldType.getStruct(node);
32
2/2
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 5735 times.
5736 if (fieldStruct == nullptr)
33 1 return false;
34 // Recurse into each field struct once. A containment cycle (already visited) is fine here - it is reported
35 // separately as an infinite-size error. Leaf structs never touch the set, so the common case stays allocation-free.
36
6/10
✓ Branch 12 → 13 taken 5735 times.
✗ Branch 12 → 33 not taken.
✓ Branch 13 → 14 taken 5644 times.
✓ Branch 13 → 17 taken 91 times.
✓ Branch 14 → 15 taken 5644 times.
✗ Branch 14 → 33 not taken.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 5644 times.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 5735 times.
5735 if (visited.insert(fieldStruct->scope).second && !structFullyManifested(fieldStruct, node, visited))
37 return false;
38 }
39 8711 return true;
40 }
41
42 6461 std::any TypeChecker::visitEntry(EntryNode *node) {
43 // Initialize
44 6461 currentScope = rootScope;
45
46 // Initialize AST nodes with size of 1
47 6461 const bool isPrepare = typeCheckerMode == TC_MODE_PRE;
48
2/2
✓ Branch 2 → 3 taken 2484 times.
✓ Branch 2 → 4 taken 3977 times.
6461 if (isPrepare)
49 2484 node->resizeToNumberOfManifestations(1);
50
51 // Visit children
52
2/2
✓ Branch 4 → 5 taken 6414 times.
✓ Branch 4 → 42 taken 47 times.
6461 visitChildren(node);
53
54 // Check which implicit structures we need for each struct, defined in this source file
55
2/2
✓ Branch 6 → 7 taken 2469 times.
✓ Branch 6 → 38 taken 3945 times.
6414 if (isPrepare) {
56
1/2
✓ Branch 7 → 8 taken 2469 times.
✗ Branch 7 → 49 not taken.
2469 const std::vector<const Struct *> manifestations = rootScope->getAllStructManifestationsInDeclarationOrder();
57
2/2
✓ Branch 35 → 10 taken 3068 times.
✓ Branch 35 → 36 taken 2469 times.
8006 for (const Struct *manifestation : manifestations) {
58 // Skip while a by-value struct field is (transitively) not manifested yet (circular import still in progress). A
59 // genuine infinite-size cycle among such structs is reported by the infinite-size check during preparation.
60 3068 std::unordered_set<const Scope *> visitedScopes;
61
3/4
✓ Branch 13 → 14 taken 3068 times.
✗ Branch 13 → 43 not taken.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 16 taken 3067 times.
3068 if (!structFullyManifested(manifestation, node, visitedScopes))
62 1 continue;
63 // Check if we need to create a default ctor, copy ctor, move ctor or dtor
64
1/2
✓ Branch 16 → 17 taken 3067 times.
✗ Branch 16 → 43 not taken.
3067 createDefaultCtorIfRequired(*manifestation, manifestation->scope);
65
1/2
✓ Branch 17 → 18 taken 3067 times.
✗ Branch 17 → 43 not taken.
3067 createDefaultCopyCtorIfRequired(*manifestation, manifestation->scope);
66
1/2
✓ Branch 18 → 19 taken 3067 times.
✗ Branch 18 → 43 not taken.
3067 createDefaultMoveCtorIfRequired(*manifestation, manifestation->scope);
67
1/2
✓ Branch 19 → 20 taken 3067 times.
✗ Branch 19 → 43 not taken.
3067 createDefaultDtorIfRequired(*manifestation, manifestation->scope);
68
2/2
✓ Branch 22 → 23 taken 3067 times.
✓ Branch 22 → 25 taken 1 time.
3068 }
69 2469 }
70
71
1/2
✓ Branch 38 → 39 taken 6414 times.
✗ Branch 38 → 50 not taken.
12828 return nullptr;
72 }
73
74 /**
75 * Check if the capture rules for async lambdas are enforced if the async attribute is set
76 *
77 * Only one capture with pointer type, pass-by-val is allowed, since only then we can store it in the second field of the
78 * fat pointer and can ensure, that no stack variable is referenced inside the lambda.
79 *
80 * @param node Lambda base node
81 * @param attrs Lambda attributes
82 * @return False if the rules are violated, true otherwise
83 */
84 64 bool TypeChecker::checkAsyncLambdaCaptureRules(const LambdaBaseNode *node, const LambdaAttrNode *attrs) const {
85 // If the async attribute is not set, we can return early
86
18/32
✓ Branch 2 → 3 taken 6 times.
✓ Branch 2 → 13 taken 58 times.
✓ Branch 5 → 6 taken 6 times.
✗ Branch 5 → 53 not taken.
✓ Branch 6 → 7 taken 6 times.
✗ Branch 6 → 53 not taken.
✓ Branch 7 → 8 taken 6 times.
✗ Branch 7 → 13 not taken.
✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 53 not taken.
✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 53 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 6 times.
✓ Branch 15 → 16 taken 6 times.
✓ Branch 15 → 17 taken 58 times.
✓ Branch 17 → 18 taken 6 times.
✓ Branch 17 → 20 taken 58 times.
✓ Branch 20 → 21 taken 6 times.
✓ Branch 20 → 22 taken 58 times.
✓ Branch 22 → 23 taken 6 times.
✓ Branch 22 → 25 taken 58 times.
✓ Branch 25 → 26 taken 58 times.
✓ Branch 25 → 27 taken 6 times.
✗ Branch 53 → 54 not taken.
✗ Branch 53 → 55 not taken.
✗ Branch 57 → 58 not taken.
✗ Branch 57 → 60 not taken.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 64 not taken.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 69 not taken.
88 if (!attrs || !attrs->attrLst->hasAttr(ATTR_ASYNC) || !attrs->attrLst->getAttrValueByName(ATTR_ASYNC)->boolValue)
87 58 return true; // Not violated
88
89 // If we don't have any captures, we can return early
90 6 const CaptureMap &captures = node->bodyScope->symbolTable.captures;
91
1/2
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 30 taken 6 times.
6 if (captures.empty())
92 return true; // Not violated
93
94 // Check for the capture rules
95 6 if (const Capture &capture = captures.begin()->second;
96
8/8
✓ Branch 33 → 34 taken 4 times.
✓ Branch 33 → 39 taken 2 times.
✓ Branch 36 → 37 taken 2 times.
✓ Branch 36 → 39 taken 2 times.
✓ Branch 38 → 39 taken 1 time.
✓ Branch 38 → 40 taken 1 time.
✓ Branch 41 → 42 taken 5 times.
✓ Branch 41 → 51 taken 1 time.
6 captures.size() > 1 || !capture.capturedSymbol->getQualType().isPtr() || capture.getMode() != BY_VALUE) {
97 5 const auto warningMessage =
98 "Async lambdas can only capture one pointer by value without storing captures in the caller stack frame, which can lead "
99 "to bugs due to references, outliving the validity scope of the referenced variable.";
100
2/4
✓ Branch 44 → 45 taken 5 times.
✗ Branch 44 → 73 not taken.
✓ Branch 45 → 46 taken 5 times.
✗ Branch 45 → 71 not taken.
10 const CompilerWarning warning(node->codeLoc, ASYNC_LAMBDA_CAPTURE_RULE_VIOLATION, warningMessage);
101
1/2
✓ Branch 48 → 49 taken 5 times.
✗ Branch 48 → 77 not taken.
5 currentScope->sourceFile->compilerOutput.warnings.push_back(warning);
102 5 }
103
104 6 return false; // Violated
105 }
106
107 39 Function *TypeChecker::matchCopyCtor(const QualType &thisType, const ASTNode *node) const {
108
1/2
✓ Branch 2 → 3 taken 39 times.
✗ Branch 2 → 40 not taken.
39 Scope *matchScope = thisType.getBodyScope();
109
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 39 times.
39 assert(matchScope != nullptr);
110
2/4
✓ Branch 5 → 6 taken 39 times.
✗ Branch 5 → 27 not taken.
✓ Branch 9 → 10 taken 39 times.
✗ Branch 9 → 23 not taken.
78 const ArgList args = {{thisType.toConstRef(node), false}};
111
2/4
✓ Branch 14 → 15 taken 39 times.
✗ Branch 14 → 31 not taken.
✓ Branch 15 → 16 taken 39 times.
✗ Branch 15 → 29 not taken.
156 return FunctionManager::match(matchScope, CTOR_FUNCTION_NAME, thisType, args, {}, true, node);
112 39 }
113
114 Function *TypeChecker::matchMoveCtor(const QualType &thisType, const ASTNode *node) const {
115 Scope *matchScope = thisType.getBodyScope();
116 assert(matchScope != nullptr);
117 const ArgList args = {{thisType.toNonConst().toRef(node), false}};
118 return FunctionManager::match(matchScope, CTOR_FUNCTION_NAME, thisType, args, {}, true, node);
119 }
120
121 837680 QualType TypeChecker::mapLocalTypeToImportedScopeType(const Scope *targetScope, const QualType &symbolType) const {
122 // Skip all types, except structs
123
3/4
✓ Branch 2 → 3 taken 837680 times.
✗ Branch 2 → 62 not taken.
✓ Branch 3 → 4 taken 721039 times.
✓ Branch 3 → 5 taken 116641 times.
837680 if (!symbolType.isBase(TY_STRUCT))
124 721039 return symbolType;
125
126 // If the target scope is in the current source file, we can return the symbol type as is
127 116641 SourceFile *targetSourceFile = targetScope->sourceFile;
128
2/2
✓ Branch 5 → 6 taken 24703 times.
✓ Branch 5 → 7 taken 91938 times.
116641 if (targetSourceFile == sourceFile)
129 24703 return symbolType;
130
131 // Match the scope of the symbol type against all scopes in the name registry of the target file
132
5/8
✓ Branch 7 → 8 taken 91938 times.
✗ Branch 7 → 58 not taken.
✓ Branch 8 → 9 taken 91938 times.
✗ Branch 8 → 58 not taken.
✓ Branch 9 → 10 taken 91938 times.
✗ Branch 9 → 58 not taken.
✓ Branch 41 → 11 taken 13798435 times.
✓ Branch 41 → 42 taken 8112 times.
13806547 for (const NameRegistryEntry &entry : targetSourceFile->exportedNameRegistry | std::views::values)
133
7/10
✓ Branch 12 → 13 taken 13798435 times.
✗ Branch 12 → 17 not taken.
✓ Branch 13 → 14 taken 13798435 times.
✗ Branch 13 → 58 not taken.
✓ Branch 14 → 15 taken 13798435 times.
✗ Branch 14 → 58 not taken.
✓ Branch 15 → 16 taken 1988430 times.
✓ Branch 15 → 17 taken 11810005 times.
✓ Branch 18 → 19 taken 1988430 times.
✓ Branch 18 → 39 taken 11810005 times.
13798435 if (entry.targetEntry != nullptr && entry.targetEntry->getQualType().isBase(TY_STRUCT))
134
3/4
✓ Branch 19 → 20 taken 1988430 times.
✗ Branch 19 → 57 not taken.
✓ Branch 37 → 22 taken 2777007 times.
✓ Branch 37 → 38 taken 1904604 times.
6670041 for (const Struct *manifestation : *entry.targetEntry->declNode->getStructManifestations())
135
4/6
✓ Branch 24 → 25 taken 2777007 times.
✗ Branch 24 → 56 not taken.
✓ Branch 25 → 26 taken 2777007 times.
✗ Branch 25 → 56 not taken.
✓ Branch 26 → 27 taken 83826 times.
✓ Branch 26 → 28 taken 2693181 times.
2777007 if (manifestation->scope == symbolType.getBase().getBodyScope())
136 83826 return symbolType;
137
138 // The target file does not know about the struct at all
139 // -> show it how to find the struct
140
3/6
✓ Branch 42 → 43 taken 8112 times.
✗ Branch 42 → 59 not taken.
✓ Branch 43 → 44 taken 8112 times.
✗ Branch 43 → 59 not taken.
✓ Branch 44 → 45 taken 8112 times.
✗ Branch 44 → 59 not taken.
8112 const std::string structName = symbolType.getBase().getSubType();
141
1/2
✓ Branch 45 → 46 taken 8112 times.
✗ Branch 45 → 60 not taken.
8112 const NameRegistryEntry *origRegistryEntry = sourceFile->getNameRegistryEntry(structName);
142 // If even this file does not know the struct by its unqualified name (deep transitive import), there is
143 // nothing to copy over. Skip teaching the target file; the type identity itself is unaffected, and member
144 // access falls back to the resolved body scope.
145
2/2
✓ Branch 46 → 47 taken 36 times.
✓ Branch 46 → 48 taken 8076 times.
8112 if (origRegistryEntry == nullptr)
146 36 return symbolType;
147 // Do not clobber an entry the target file already has under this name (e.g. its OWN same-named struct, like
148 // llvm's `Function` vs the model's `Function`). Teaching uses keepNewOnCollision=false, which would otherwise
149 // ERASE the target's existing entry and break resolution of its own type. The struct's QualType identity is
150 // carried by pointer regardless, so a name that is already taken does not need (re-)teaching here.
151
3/4
✓ Branch 48 → 49 taken 8076 times.
✗ Branch 48 → 60 not taken.
✓ Branch 49 → 50 taken 2807 times.
✓ Branch 49 → 51 taken 5269 times.
8076 if (targetSourceFile->exportedNameRegistry.contains(structName))
152 2807 return symbolType;
153 5269 const uint64_t targetTypeId = origRegistryEntry->typeId;
154 5269 SymbolTableEntry *targetEntry = origRegistryEntry->targetEntry;
155
1/2
✓ Branch 51 → 52 taken 5269 times.
✗ Branch 51 → 60 not taken.
5269 targetSourceFile->addNameRegistryEntry(structName, targetTypeId, targetEntry, origRegistryEntry->targetScope, false);
156
157 5269 return symbolType;
158 8112 }
159
160 23112 QualType TypeChecker::mapImportedScopeTypeToLocalType(const Scope *sourceScope, const QualType &symbolType) const {
161 // Skip all types, except structs
162
3/4
✓ Branch 2 → 3 taken 23112 times.
✗ Branch 2 → 57 not taken.
✓ Branch 3 → 4 taken 1758 times.
✓ Branch 3 → 5 taken 21354 times.
23112 if (!symbolType.isBase(TY_STRUCT))
163 1758 return symbolType;
164
165 // If the given source file is in the current one, we can return the symbol type as is
166 21354 const SourceFile *sourceSourceFile = sourceScope->sourceFile;
167
2/2
✓ Branch 5 → 6 taken 5150 times.
✓ Branch 5 → 7 taken 16204 times.
21354 if (sourceSourceFile == sourceFile)
168 5150 return symbolType;
169
170 // Match the scope of the symbol type against all scopes in the name registry of this source file
171
1/2
✓ Branch 7 → 8 taken 16204 times.
✗ Branch 7 → 57 not taken.
16204 const QualType baseType = symbolType.getBase();
172
5/8
✓ Branch 8 → 9 taken 16204 times.
✗ Branch 8 → 56 not taken.
✓ Branch 9 → 10 taken 16204 times.
✗ Branch 9 → 56 not taken.
✓ Branch 10 → 11 taken 16204 times.
✗ Branch 10 → 56 not taken.
✓ Branch 41 → 12 taken 2987796 times.
✓ Branch 41 → 42 taken 210 times.
2988006 for (const auto &entry : sourceFile->exportedNameRegistry | std::views::values)
173
7/10
✓ Branch 13 → 14 taken 2987796 times.
✗ Branch 13 → 18 not taken.
✓ Branch 14 → 15 taken 2987796 times.
✗ Branch 14 → 56 not taken.
✓ Branch 15 → 16 taken 2987796 times.
✗ Branch 15 → 56 not taken.
✓ Branch 16 → 17 taken 528406 times.
✓ Branch 16 → 18 taken 2459390 times.
✓ Branch 19 → 20 taken 528406 times.
✓ Branch 19 → 39 taken 2459390 times.
2987796 if (entry.targetEntry != nullptr && entry.targetEntry->getQualType().isBase(TY_STRUCT))
174
3/4
✓ Branch 20 → 21 taken 528406 times.
✗ Branch 20 → 55 not taken.
✓ Branch 37 → 23 taken 594576 times.
✓ Branch 37 → 38 taken 512412 times.
1635394 for (const Struct *manifestation : *entry.targetEntry->declNode->getStructManifestations())
175
3/4
✓ Branch 25 → 26 taken 594576 times.
✗ Branch 25 → 55 not taken.
✓ Branch 26 → 27 taken 15994 times.
✓ Branch 26 → 28 taken 578582 times.
594576 if (manifestation->scope == baseType.getBodyScope())
176 15994 return symbolType;
177
178 // This source file does not know about the struct at all
179 // -> show it how to find the struct
180
2/4
✓ Branch 42 → 43 taken 210 times.
✗ Branch 42 → 57 not taken.
✓ Branch 43 → 44 taken 210 times.
✗ Branch 43 → 57 not taken.
210 const NameRegistryEntry *origRegistryEntry = sourceSourceFile->getNameRegistryEntry(baseType.getSubType());
181 // If even the source file does not know the struct by its unqualified name (deep transitive import), there is
182 // nothing to copy over. Skip teaching this file; the type identity itself is unaffected, and member access
183 // falls back to the resolved body scope.
184
1/2
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 46 taken 210 times.
210 if (origRegistryEntry == nullptr)
185 return symbolType;
186 // Do not clobber an entry this file already has under this name (see mapLocalTypeToImportedScopeType): teaching
187 // with keepNewOnCollision=false would ERASE this file's own same-named struct entry. The QualType identity is
188 // carried by pointer, so an already-taken name needs no (re-)teaching here.
189
4/6
✓ Branch 46 → 47 taken 210 times.
✗ Branch 46 → 57 not taken.
✓ Branch 47 → 48 taken 210 times.
✗ Branch 47 → 57 not taken.
✓ Branch 48 → 49 taken 16 times.
✓ Branch 48 → 50 taken 194 times.
210 if (sourceFile->exportedNameRegistry.contains(baseType.getSubType()))
190 16 return symbolType;
191 194 const uint64_t typeId = origRegistryEntry->typeId;
192 194 SymbolTableEntry *targetEntry = origRegistryEntry->targetEntry;
193
2/4
✓ Branch 50 → 51 taken 194 times.
✗ Branch 50 → 57 not taken.
✓ Branch 51 → 52 taken 194 times.
✗ Branch 51 → 57 not taken.
194 sourceFile->addNameRegistryEntry(baseType.getSubType(), typeId, targetEntry, origRegistryEntry->targetScope, false);
194
195 194 return symbolType;
196 }
197
198 /**
199 * Returns the operator function list for the current manifestation and the given node
200 *
201 * @param node Node to retrieve the op fct pointer list from
202 * @return Op fct pointer list
203 */
204 5380 std::vector<const Function *> &TypeChecker::getOpFctPointers(ASTNode *node) const {
205
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 5380 times.
5380 assert(node->getOpFctPointers()->size() > manIdx);
206 5380 return node->getOpFctPointers()->at(manIdx);
207 }
208
209 /**
210 * Check if a function has been type-checked already. If not, request a revisit
211 *
212 * @param fct Function to check
213 */
214 95566 void TypeChecker::requestRevisitIfRequired(const Function *fct) {
215
4/4
✓ Branch 2 → 3 taken 95428 times.
✓ Branch 2 → 5 taken 138 times.
✓ Branch 3 → 4 taken 61150 times.
✓ Branch 3 → 5 taken 34278 times.
95566 if (fct && !fct->alreadyTypeChecked)
216 61150 fct->entry->scope->sourceFile->reVisitRequested = true;
217 95566 }
218
219 /**
220 * Check type name against well-known type names that require a runtime import. If found one, auto-import the runtime module.
221 *
222 * @param typeName Given type name
223 */
224 129479 void TypeChecker::ensureLoadedRuntimeForTypeName(const std::string &typeName) const {
225
2/2
✓ Branch 18 → 4 taken 381139 times.
✓ Branch 18 → 19 taken 119877 times.
501016 for (const auto &[wellKnownTypeName, runtimeModule] : TYPE_NAME_TO_RT_MODULE_MAPPING) {
226
8/10
✓ Branch 7 → 8 taken 381139 times.
✗ Branch 7 → 20 not taken.
✓ Branch 8 → 9 taken 19724 times.
✓ Branch 8 → 12 taken 361415 times.
✓ Branch 9 → 10 taken 19724 times.
✗ Branch 9 → 20 not taken.
✓ Branch 10 → 11 taken 9602 times.
✓ Branch 10 → 12 taken 10122 times.
✓ Branch 13 → 14 taken 9602 times.
✓ Branch 13 → 16 taken 371537 times.
381139 if (typeName == wellKnownTypeName && !sourceFile->isRT(runtimeModule)) {
227
1/2
✓ Branch 14 → 15 taken 9602 times.
✗ Branch 14 → 20 not taken.
9602 sourceFile->requestRuntimeModule(runtimeModule);
228 9602 break;
229 }
230 }
231 129479 }
232
233 /**
234 * Check type name against well-known function names that require a runtime import. If found one, auto-import the runtime module.
235 *
236 * @param functionName Given function name
237 */
238 28858 void TypeChecker::ensureLoadedRuntimeForFunctionName(const std::string &functionName) const {
239
2/2
✓ Branch 18 → 4 taken 379493 times.
✓ Branch 18 → 19 taken 25791 times.
405284 for (const auto &[wellKnownFunctionName, runtimeModule] : FCT_NAME_TO_RT_MODULE_MAPPING) {
240
8/10
✓ Branch 7 → 8 taken 379493 times.
✗ Branch 7 → 20 not taken.
✓ Branch 8 → 9 taken 3203 times.
✓ Branch 8 → 12 taken 376290 times.
✓ Branch 9 → 10 taken 3203 times.
✗ Branch 9 → 20 not taken.
✓ Branch 10 → 11 taken 3067 times.
✓ Branch 10 → 12 taken 136 times.
✓ Branch 13 → 14 taken 3067 times.
✓ Branch 13 → 16 taken 376426 times.
379493 if (functionName == wellKnownFunctionName && !sourceFile->isRT(runtimeModule)) {
241
1/2
✓ Branch 14 → 15 taken 3067 times.
✗ Branch 14 → 20 not taken.
3067 sourceFile->requestRuntimeModule(runtimeModule);
242 3067 break;
243 }
244 }
245 28858 }
246
247 /**
248 * Add a soft error to the error list
249 */
250 25 void TypeChecker::softError(const ASTNode *node, const SemanticErrorType errorType, const std::string &message) const {
251 25 resourceManager.errorManager.addSoftError(node, errorType, message);
252 25 }
253
254 20 bool TypeChecker::isCopyCtorCall(const FctCallNode *node, const QualType &thisType) const {
255
1/2
✓ Branch 2 → 3 taken 20 times.
✗ Branch 2 → 14 not taken.
20 const FctCallNode::FctCallData &data = node->data.at(manIdx);
256
2/2
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 6 taken 18 times.
20 if (data.args.size() != 2)
257 2 return false;
258
2/4
✓ Branch 7 → 8 taken 18 times.
✗ Branch 7 → 13 not taken.
✓ Branch 8 → 9 taken 18 times.
✗ Branch 8 → 13 not taken.
18 const QualType &secondArgType = data.args.back().first.removeReferenceWrapper().toNonConst();
259
1/2
✓ Branch 9 → 10 taken 18 times.
✗ Branch 9 → 14 not taken.
18 return thisType.matches(secondArgType, false, false, true);
260 }
261
262 } // namespace spice::compiler
263