GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 176 / 0 / 176
Functions: 100.0% 5 / 0 / 5
Branches: 66.1% 213 / 0 / 322

src/typechecker/TypeCheckerTopLevelDefinitionsCheck.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "TypeChecker.h"
4
5 #include <SourceFile.h>
6 #include <ast/ASTNodes.h>
7 #include <exception/SemanticError.h>
8 #include <model/Interface.h>
9 #include <model/Union.h>
10 #include <symboltablebuilder/Scope.h>
11 #include <symboltablebuilder/SymbolTableBuilder.h>
12 #include <typechecker/FunctionManager.h>
13 #include <typechecker/TypeMatcher.h>
14
15 namespace spice::compiler {
16
17 1438 std::any TypeChecker::visitMainFctDefCheck(MainFctDefNode *node) {
18 // Skip if already type-checked
19
2/2
✓ Branch 2 → 3 taken 190 times.
✓ Branch 2 → 6 taken 1248 times.
1438 if (typeCheckedMainFct)
20
1/2
✓ Branch 3 → 4 taken 190 times.
✗ Branch 3 → 13 not taken.
380 return nullptr;
21
22 1248 node->resizeToNumberOfManifestations(1);
23
24 // Change to function body scope
25 1248 currentScope = node->bodyScope;
26 // Visit statements in new scope
27
2/2
✓ Branch 7 → 8 taken 1182 times.
✓ Branch 7 → 14 taken 66 times.
1248 visit(node->body);
28 // Leave main function body scope
29 1182 currentScope = rootScope;
30
31 // Set to type-checked
32 1182 typeCheckedMainFct = true;
33
1/2
✓ Branch 9 → 10 taken 1182 times.
✗ Branch 9 → 15 not taken.
2364 return nullptr;
34 }
35
36 87205 std::any TypeChecker::visitFctDefCheck(FctDefNode *node) {
37 87205 const size_t manifestationCount = node->manifestations.size();
38 87205 node->resizeToNumberOfManifestations(manifestationCount);
39 87205 manIdx = 0; // Reset the manifestation index
40
41 // Get all manifestations for this function definition. Type-checking a body can add new manifestations of this function
42 // (e.g. a generic struct method that uses another substantiation of its own struct), which would invalidate iterators.
43 // Those are type-checked in the next run, so only visit the manifestations that exist up front, accessing them by index.
44
2/2
✓ Branch 69 → 5 taken 112954 times.
✓ Branch 69 → 70 taken 87201 times.
200155 while (manIdx < manifestationCount) {
45 112954 Function *manifestation = node->manifestations.at(manIdx);
46 // Skip non-substantiated or already checked functions
47
6/6
✓ Branch 7 → 8 taken 86875 times.
✓ Branch 7 → 9 taken 26079 times.
✓ Branch 8 → 9 taken 46984 times.
✓ Branch 8 → 10 taken 39891 times.
✓ Branch 11 → 12 taken 73063 times.
✓ Branch 11 → 13 taken 39891 times.
112954 if (!manifestation->isFullySubstantiated() || manifestation->alreadyTypeChecked) {
48 73063 manIdx++; // Increase the manifestation index
49 73063 continue;
50 }
51
52 // Change scope to concrete struct specialization scope
53
2/2
✓ Branch 13 → 14 taken 19985 times.
✓ Branch 13 → 19 taken 19906 times.
39891 if (node->isMethod) {
54
2/4
✓ Branch 14 → 15 taken 19985 times.
✗ Branch 14 → 76 not taken.
✓ Branch 15 → 16 taken 19985 times.
✗ Branch 15 → 76 not taken.
19985 const std::string &scopeName = Struct::getScopeName(node->name->structName, manifestation->thisType.getTemplateTypes());
55
1/2
✓ Branch 16 → 17 taken 19985 times.
✗ Branch 16 → 74 not taken.
19985 changeToScope(scopeName, ScopeType::STRUCT);
56 19985 }
57
58 // Change to function scope
59 39891 changeToScope(manifestation->bodyScope, ScopeType::FUNC_PROC_BODY);
60
61 // Mount type mapping for this manifestation
62
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 39891 times.
39891 assert(typeMapping.empty());
63 39891 typeMapping = manifestation->typeMapping;
64
65 // Set return type to the result variable
66
1/2
✓ Branch 26 → 27 taken 39891 times.
✗ Branch 26 → 79 not taken.
119673 SymbolTableEntry *resultVarEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
67
1/2
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 34 taken 39891 times.
39891 assert(resultVarEntry != nullptr);
68 39891 resultVarEntry->updateType(manifestation->returnType, false);
69 39891 resultVarEntry->used = true;
70
71 // Visit parameters
72 // This happens once in the type checker prepare stage. This second time is only required if we have a generic function
73
2/2
✓ Branch 35 → 36 taken 28727 times.
✓ Branch 35 → 62 taken 11164 times.
39891 if (node->hasParams) {
74
1/2
✓ Branch 36 → 37 taken 28727 times.
✗ Branch 36 → 83 not taken.
28727 visit(node->paramLst);
75 // Annotate function/procedure-typed params with lambda-capture info from the resolved manifestation type.
76 // This must happen in the TypeChecker so that the IRGenerator can treat SymbolTableEntry as immutable.
77
2/2
✓ Branch 61 → 39 taken 43634 times.
✓ Branch 61 → 62 taken 28727 times.
72361 for (size_t i = 0; i < manifestation->paramList.size(); i++) {
78
1/2
✓ Branch 39 → 40 taken 43634 times.
✗ Branch 39 → 89 not taken.
43634 const DeclStmtNode *param = node->paramLst->params.at(i);
79
2/4
✓ Branch 40 → 41 taken 43634 times.
✗ Branch 40 → 86 not taken.
✓ Branch 41 → 42 taken 43634 times.
✗ Branch 41 → 84 not taken.
43634 const QualType paramType = manifestation->getParamTypes().at(i);
80
8/10
✓ Branch 43 → 44 taken 43634 times.
✗ Branch 43 → 87 not taken.
✓ Branch 44 → 45 taken 38 times.
✓ Branch 44 → 48 taken 43596 times.
✓ Branch 45 → 46 taken 38 times.
✗ Branch 45 → 87 not taken.
✓ Branch 46 → 47 taken 8 times.
✓ Branch 46 → 48 taken 30 times.
✓ Branch 49 → 50 taken 8 times.
✓ Branch 49 → 59 taken 43626 times.
43634 if (paramType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && paramType.hasLambdaCaptures()) {
81
1/2
✓ Branch 50 → 51 taken 8 times.
✗ Branch 50 → 89 not taken.
8 SymbolTableEntry *paramSymbol = currentScope->lookupStrict(param->varName);
82
1/2
✗ Branch 53 → 54 not taken.
✓ Branch 53 → 55 taken 8 times.
8 assert(paramSymbol != nullptr);
83
3/6
✓ Branch 55 → 56 taken 8 times.
✗ Branch 55 → 88 not taken.
✓ Branch 56 → 57 taken 8 times.
✗ Branch 56 → 88 not taken.
✓ Branch 57 → 58 taken 8 times.
✗ Branch 57 → 88 not taken.
8 paramSymbol->updateType(paramSymbol->getQualType().getWithLambdaCaptures(), true);
84 }
85 }
86 }
87
88 // Visit statements in new scope
89
2/2
✓ Branch 62 → 63 taken 39887 times.
✓ Branch 62 → 90 taken 4 times.
39891 visit(node->body);
90
91 // Clear type mapping
92 39887 typeMapping.clear();
93
94 // Change to root scope
95 39887 currentScope = rootScope;
96
1/2
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 39887 times.
39887 assert(currentScope->type == ScopeType::GLOBAL);
97
98 // Do not type-check this manifestation again
99 39887 manifestation->alreadyTypeChecked = true;
100
101 39887 manIdx++; // Increase the manifestation index
102 }
103 87201 manIdx = 0; // Reset the manifestation index
104
105
1/2
✓ Branch 70 → 71 taken 87201 times.
✗ Branch 70 → 91 not taken.
174402 return nullptr;
106 }
107
108 56614 std::any TypeChecker::visitProcDefCheck(ProcDefNode *node) {
109 56614 const size_t manifestationCount = node->manifestations.size();
110 56614 node->resizeToNumberOfManifestations(manifestationCount);
111 56614 manIdx = 0; // Reset the manifestation index
112
113 // Get all manifestations for this procedure definition. Type-checking a body can add new manifestations of this procedure
114 // (e.g. a generic struct method that uses another substantiation of its own struct), which would invalidate iterators.
115 // Those are type-checked in the next run, so only visit the manifestations that exist up front, accessing them by index.
116
2/2
✓ Branch 62 → 5 taken 79192 times.
✓ Branch 62 → 63 taken 56614 times.
135806 while (manIdx < manifestationCount) {
117 79192 Function *manifestation = node->manifestations.at(manIdx);
118 // Skip non-substantiated or already checked procedures
119
6/6
✓ Branch 7 → 8 taken 52938 times.
✓ Branch 7 → 9 taken 26254 times.
✓ Branch 8 → 9 taken 27247 times.
✓ Branch 8 → 10 taken 25691 times.
✓ Branch 11 → 12 taken 53501 times.
✓ Branch 11 → 13 taken 25691 times.
79192 if (!manifestation->isFullySubstantiated() || manifestation->alreadyTypeChecked) {
120 53501 manIdx++; // Increase the manifestation index
121 53501 continue;
122 }
123
124 // Change scope to concrete struct specialization scope
125
2/2
✓ Branch 13 → 14 taken 20430 times.
✓ Branch 13 → 19 taken 5261 times.
25691 if (node->isMethod) {
126
2/4
✓ Branch 14 → 15 taken 20430 times.
✗ Branch 14 → 69 not taken.
✓ Branch 15 → 16 taken 20430 times.
✗ Branch 15 → 69 not taken.
20430 const std::string &scopeName = Struct::getScopeName(node->name->structName, manifestation->thisType.getTemplateTypes());
127
1/2
✓ Branch 16 → 17 taken 20430 times.
✗ Branch 16 → 67 not taken.
20430 changeToScope(scopeName, ScopeType::STRUCT);
128 20430 }
129
130 // Change to procedure scope
131 25691 changeToScope(manifestation->bodyScope, ScopeType::FUNC_PROC_BODY);
132
133 // Mount type mapping for this manifestation
134
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 25691 times.
25691 assert(typeMapping.empty());
135 25691 typeMapping = manifestation->typeMapping;
136
137 // Visit parameters
138 // This happens once in the type checker prepare stage. This second time is only required if we have a generic procedure
139
2/2
✓ Branch 24 → 25 taken 18256 times.
✓ Branch 24 → 51 taken 7435 times.
25691 if (node->hasParams) {
140
1/2
✓ Branch 25 → 26 taken 18256 times.
✗ Branch 25 → 70 not taken.
18256 visit(node->paramLst);
141 // Annotate function/procedure-typed params with lambda-capture info from the resolved manifestation type.
142 // This must happen in the TypeChecker so that the IRGenerator can treat SymbolTableEntry as immutable.
143
2/2
✓ Branch 50 → 28 taken 30921 times.
✓ Branch 50 → 51 taken 18256 times.
49177 for (size_t i = 0; i < manifestation->paramList.size(); i++) {
144
1/2
✓ Branch 28 → 29 taken 30921 times.
✗ Branch 28 → 76 not taken.
30921 const DeclStmtNode *param = node->paramLst->params.at(i);
145
2/4
✓ Branch 29 → 30 taken 30921 times.
✗ Branch 29 → 73 not taken.
✓ Branch 30 → 31 taken 30921 times.
✗ Branch 30 → 71 not taken.
30921 const QualType paramType = manifestation->getParamTypes().at(i);
146
8/10
✓ Branch 32 → 33 taken 30921 times.
✗ Branch 32 → 74 not taken.
✓ Branch 33 → 34 taken 170 times.
✓ Branch 33 → 37 taken 30751 times.
✓ Branch 34 → 35 taken 170 times.
✗ Branch 34 → 74 not taken.
✓ Branch 35 → 36 taken 50 times.
✓ Branch 35 → 37 taken 120 times.
✓ Branch 38 → 39 taken 50 times.
✓ Branch 38 → 48 taken 30871 times.
30921 if (paramType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && paramType.hasLambdaCaptures()) {
147
1/2
✓ Branch 39 → 40 taken 50 times.
✗ Branch 39 → 76 not taken.
50 SymbolTableEntry *paramSymbol = currentScope->lookupStrict(param->varName);
148
1/2
✗ Branch 42 → 43 not taken.
✓ Branch 42 → 44 taken 50 times.
50 assert(paramSymbol != nullptr);
149
3/6
✓ Branch 44 → 45 taken 50 times.
✗ Branch 44 → 75 not taken.
✓ Branch 45 → 46 taken 50 times.
✗ Branch 45 → 75 not taken.
✓ Branch 46 → 47 taken 50 times.
✗ Branch 46 → 75 not taken.
50 paramSymbol->updateType(paramSymbol->getQualType().getWithLambdaCaptures(), true);
150 }
151 }
152 }
153
154 // Prepare generation of special ctor preamble to store VTable, default field values, etc. if required
155
2/2
✓ Branch 51 → 52 taken 8320 times.
✓ Branch 51 → 53 taken 17371 times.
25691 if (node->isCtor)
156 8320 createCtorBodyPreamble(manifestation->bodyScope);
157
158 // Visit statements in new scope
159
1/2
✓ Branch 53 → 54 taken 25691 times.
✗ Branch 53 → 77 not taken.
25691 visit(node->body);
160
161 // Clear type mapping
162 25691 typeMapping.clear();
163
164 // Change to root scope
165 25691 currentScope = rootScope;
166
2/4
✓ Branch 56 → 57 taken 25691 times.
✗ Branch 56 → 59 not taken.
✓ Branch 57 → 58 taken 25691 times.
✗ Branch 57 → 59 not taken.
25691 assert(currentScope != nullptr && currentScope->type == ScopeType::GLOBAL);
167
168 // Do not type-check this manifestation again
169 25691 manifestation->alreadyTypeChecked = true;
170
171 25691 manIdx++; // Increase the manifestation index
172 }
173 56614 manIdx = 0; // Reset the manifestation index
174
175
1/2
✓ Branch 63 → 64 taken 56614 times.
✗ Branch 63 → 78 not taken.
113228 return nullptr;
176 }
177
178 8704 std::any TypeChecker::visitStructDefCheck(StructDefNode *node) {
179 8704 node->resizeToNumberOfManifestations(node->structManifestations.size());
180 8704 manIdx = 0; // Reset the manifestation index
181
182 // Get all manifestations for this procedure definition
183
2/2
✓ Branch 218 → 6 taken 15488 times.
✓ Branch 218 → 219 taken 8704 times.
32896 for (Struct *manifestation : node->structManifestations) {
184 // Skip non-substantiated or already checked procedures
185
3/4
✓ Branch 8 → 9 taken 15488 times.
✗ Branch 8 → 302 not taken.
✓ Branch 9 → 10 taken 3574 times.
✓ Branch 9 → 11 taken 11914 times.
15488 if (!manifestation->isFullySubstantiated()) {
186 3574 manIdx++; // Increase the manifestation index
187 3574 continue;
188 }
189
190 // Fallback for manifestations that could not be decided on when they were created, because a by-value struct field
191 // was not manifested yet at that point (circular import). By now the whole import graph is prepared, so the
192 // decision can be taken - late, but still before the struct's own default member bodies are prepared below.
193
1/2
✓ Branch 11 → 12 taken 11914 times.
✗ Branch 11 → 302 not taken.
11914 createImplicitDefaultMembers(*manifestation, node, /*withMoveCtor=*/false);
194
195 // Change to struct scope
196
1/2
✓ Branch 12 → 13 taken 11914 times.
✗ Branch 12 → 302 not taken.
11914 changeToScope(manifestation->scope, ScopeType::STRUCT);
197
198 // Mount type mapping for this manifestation, so that the body preamble helpers below can substantiate
199 // generic field types (e.g. `heap T*` on `Vector<T>`). Without this, an auto-generated body preamble that
200 // touches a still-generic field would assert in TypeMatcher::substantiateTypeWithTypeMapping.
201
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 11914 times.
11914 assert(typeMapping.empty());
202
1/2
✓ Branch 16 → 17 taken 11914 times.
✗ Branch 16 → 302 not taken.
11914 typeMapping = manifestation->typeMapping;
203
204 // Re-visit all default values. This is required, since the type of the default value might vary for different manifestations
205
2/2
✓ Branch 40 → 19 taken 30386 times.
✓ Branch 40 → 41 taken 11914 times.
54214 for (const FieldNode *field : node->fields) {
206
2/2
✓ Branch 21 → 22 taken 9351 times.
✓ Branch 21 → 31 taken 21035 times.
30386 if (field->defaultValue != nullptr) {
207
1/2
✓ Branch 22 → 23 taken 9351 times.
✗ Branch 22 → 223 not taken.
9351 visit(field->defaultValue);
208
1/2
✓ Branch 24 → 25 taken 9351 times.
✗ Branch 24 → 225 not taken.
9351 SymbolTableEntry *fieldEntry = manifestation->scope->lookupStrict(field->fieldName);
209
1/2
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 9351 times.
9351 assert(fieldEntry != nullptr);
210
1/2
✓ Branch 29 → 30 taken 9351 times.
✗ Branch 29 → 224 not taken.
9351 fieldEntry->updateState(INITIALIZED, field);
211 }
212 }
213
214 // Build struct type
215
1/2
✓ Branch 41 → 42 taken 11914 times.
✗ Branch 41 → 302 not taken.
11914 const QualType structType = manifestation->entry->getQualType();
216
217 // Check if the struct implements all methods of all attached interfaces
218 11914 size_t vtableIndex = 0;
219
2/2
✓ Branch 149 → 44 taken 2580 times.
✓ Branch 149 → 150 taken 11914 times.
26408 for (const QualType &interfaceType : manifestation->interfaceTypes) {
220
1/2
✓ Branch 46 → 47 taken 2580 times.
✗ Branch 46 → 269 not taken.
2580 const Interface *interface = interfaceType.getInterface(node);
221
1/2
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 2580 times.
2580 assert(interface != nullptr);
222
223 // Check for all methods, that it is implemented by the struct
224
2/2
✓ Branch 139 → 51 taken 6392 times.
✓ Branch 139 → 140 taken 2580 times.
11552 for (const Function *expMethod : interface->methods) {
225
1/2
✓ Branch 53 → 54 taken 6392 times.
✗ Branch 53 → 267 not taken.
6392 const std::string methodName = expMethod->name;
226
1/2
✓ Branch 54 → 55 taken 6392 times.
✗ Branch 54 → 265 not taken.
6392 QualTypeList params = expMethod->getParamTypes();
227 6392 QualType returnType = expMethod->returnType;
228
229 // Substantiate param and return types
230
1/2
✓ Branch 55 → 56 taken 6392 times.
✗ Branch 55 → 263 not taken.
6392 TypeMatcher::substantiateTypesWithTypeMapping(params, interface->typeMapping, node);
231
3/4
✓ Branch 56 → 57 taken 6392 times.
✗ Branch 56 → 263 not taken.
✓ Branch 57 → 58 taken 3732 times.
✓ Branch 57 → 59 taken 2660 times.
6392 if (returnType.hasAnyGenericParts())
232
1/2
✓ Branch 58 → 59 taken 3732 times.
✗ Branch 58 → 263 not taken.
3732 TypeMatcher::substantiateTypeWithTypeMapping(returnType, interface->typeMapping, node);
233
234 // Build args list
235 6392 ArgList args;
236
1/2
✓ Branch 60 → 61 taken 6392 times.
✗ Branch 60 → 261 not taken.
6392 args.reserve(params.size());
237
2/2
✓ Branch 75 → 63 taken 32 times.
✓ Branch 75 → 76 taken 6392 times.
12816 for (const QualType &param : params)
238
1/2
✓ Branch 65 → 66 taken 32 times.
✗ Branch 65 → 226 not taken.
32 args.emplace_back(param, nullptr);
239
240 // Search for method that has the required signature
241
1/2
✓ Branch 77 → 78 taken 6392 times.
✗ Branch 77 → 228 not taken.
6392 Function *spiceFunction = FunctionManager::match(currentScope, methodName, structType, args, {}, true, node);
242
2/2
✓ Branch 79 → 80 taken 8 times.
✓ Branch 79 → 92 taken 6384 times.
6392 if (spiceFunction == nullptr) {
243
1/2
✓ Branch 85 → 86 taken 8 times.
✗ Branch 85 → 231 not taken.
8 softError(node, INTERFACE_METHOD_NOT_IMPLEMENTED,
244
5/10
✓ Branch 80 → 81 taken 8 times.
✗ Branch 80 → 243 not taken.
✓ Branch 81 → 82 taken 8 times.
✗ Branch 81 → 239 not taken.
✓ Branch 82 → 83 taken 8 times.
✗ Branch 82 → 237 not taken.
✓ Branch 83 → 84 taken 8 times.
✗ Branch 83 → 235 not taken.
✓ Branch 84 → 85 taken 8 times.
✗ Branch 84 → 233 not taken.
16 "The struct '" + node->structName + "' does not implement method '" + expMethod->getSignature() + "'.");
245 8 continue;
246 }
247
248 // Check return type
249
5/6
✓ Branch 92 → 93 taken 6384 times.
✗ Branch 92 → 261 not taken.
✓ Branch 93 → 94 taken 1208 times.
✓ Branch 93 → 97 taken 5176 times.
✓ Branch 98 → 99 taken 4 times.
✓ Branch 98 → 111 taken 6380 times.
7592 if (spiceFunction->returnType != returnType &&
250
3/4
✓ Branch 94 → 95 taken 1208 times.
✗ Branch 94 → 261 not taken.
✓ Branch 95 → 96 taken 4 times.
✓ Branch 95 → 97 taken 1204 times.
1208 !returnType.matchesInterfaceImplementedByStruct(spiceFunction->returnType)) {
251
1/2
✓ Branch 104 → 105 taken 4 times.
✗ Branch 104 → 246 not taken.
4 softError(node, INTERFACE_METHOD_NOT_IMPLEMENTED,
252
4/8
✓ Branch 99 → 100 taken 4 times.
✗ Branch 99 → 258 not taken.
✓ Branch 100 → 101 taken 4 times.
✗ Branch 100 → 254 not taken.
✓ Branch 101 → 102 taken 4 times.
✗ Branch 101 → 252 not taken.
✓ Branch 102 → 103 taken 4 times.
✗ Branch 102 → 250 not taken.
8 "The struct '" + node->structName + "' does not implement method '" + expMethod->getSignature() +
253
1/2
✓ Branch 103 → 104 taken 4 times.
✗ Branch 103 → 248 not taken.
4 "'. The return type does not match.");
254 4 continue;
255 }
256 // Set to virtual, since it overrides the interface method
257 6380 spiceFunction->isVirtual = true;
258 6380 spiceFunction->vtableIndex = vtableIndex++;
259 // Methods, that return a struct implementing the interface method's return type, are called through a thunk
260
3/4
✓ Branch 111 → 112 taken 6380 times.
✗ Branch 111 → 261 not taken.
✓ Branch 112 → 113 taken 1204 times.
✓ Branch 112 → 114 taken 5176 times.
6380 if (spiceFunction->returnType != returnType)
261 1204 spiceFunction->virtualReturnType = returnType;
262
6/6
✓ Branch 116 → 117 taken 6380 times.
✓ Branch 116 → 118 taken 12 times.
✓ Branch 121 → 122 taken 6380 times.
✓ Branch 121 → 123 taken 12 times.
✓ Branch 126 → 127 taken 6380 times.
✓ Branch 126 → 129 taken 12 times.
19176 }
263 }
264
265 // Check default ctor body if required
266
2/4
✓ Branch 153 → 154 taken 11914 times.
✗ Branch 153 → 272 not taken.
✓ Branch 154 → 155 taken 11914 times.
✗ Branch 154 → 270 not taken.
35742 const Function *ctorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, structType, {}, true);
267
4/4
✓ Branch 158 → 159 taken 4289 times.
✓ Branch 158 → 164 taken 7625 times.
✓ Branch 159 → 160 taken 448 times.
✓ Branch 159 → 164 taken 3841 times.
11914 if (ctorFunc != nullptr && ctorFunc->implicitDefault) {
268
1/2
✓ Branch 160 → 161 taken 448 times.
✗ Branch 160 → 302 not taken.
448 createCtorBodyPreamble(ctorFunc->bodyScope);
269
2/4
✓ Branch 161 → 162 taken 448 times.
✗ Branch 161 → 302 not taken.
✗ Branch 162 → 163 not taken.
✓ Branch 162 → 164 taken 448 times.
448 assert(manifestation->areAllFieldsInitialized() == nullptr);
270 }
271
272 // Check default copy ctor body if required
273
2/4
✓ Branch 164 → 165 taken 11914 times.
✗ Branch 164 → 283 not taken.
✓ Branch 168 → 169 taken 11914 times.
✗ Branch 168 → 279 not taken.
35742 const ArgList args = {{structType.toConstRef(node), false /* always non-temporary */}};
274
2/4
✓ Branch 172 → 173 taken 11914 times.
✗ Branch 172 → 287 not taken.
✓ Branch 173 → 174 taken 11914 times.
✗ Branch 173 → 285 not taken.
11914 const Function *copyCtorFunc = FunctionManager::lookup(currentScope, CTOR_FUNCTION_NAME, structType, args, true);
275
4/4
✓ Branch 176 → 177 taken 3629 times.
✓ Branch 176 → 182 taken 8285 times.
✓ Branch 177 → 178 taken 1817 times.
✓ Branch 177 → 182 taken 1812 times.
11914 if (copyCtorFunc != nullptr && copyCtorFunc->implicitDefault) {
276
1/2
✓ Branch 178 → 179 taken 1817 times.
✗ Branch 178 → 300 not taken.
1817 createCopyCtorBodyPreamble(copyCtorFunc->bodyScope);
277
2/4
✓ Branch 179 → 180 taken 1817 times.
✗ Branch 179 → 300 not taken.
✗ Branch 180 → 181 not taken.
✓ Branch 180 → 182 taken 1817 times.
1817 assert(manifestation->areAllFieldsInitialized() == nullptr);
278 }
279
280 // Check default move ctor body if required. findMoveCtor scans the manifestations directly to avoid the
281 // constify-based false-positive that FunctionManager::lookup with a non-const ref arg can produce.
282
3/4
✓ Branch 182 → 183 taken 11914 times.
✗ Branch 182 → 300 not taken.
✓ Branch 183 → 184 taken 247 times.
✓ Branch 183 → 189 taken 11667 times.
11914 if (const Function *moveCtorFunc = FunctionManager::findMoveCtor(currentScope);
283
2/2
✓ Branch 184 → 185 taken 42 times.
✓ Branch 184 → 189 taken 205 times.
247 moveCtorFunc && moveCtorFunc->implicitDefault) {
284
1/2
✓ Branch 185 → 186 taken 42 times.
✗ Branch 185 → 300 not taken.
42 createMoveCtorBodyPreamble(moveCtorFunc->bodyScope);
285
2/4
✓ Branch 186 → 187 taken 42 times.
✗ Branch 186 → 300 not taken.
✗ Branch 187 → 188 not taken.
✓ Branch 187 → 189 taken 42 times.
42 assert(manifestation->areAllFieldsInitialized() == nullptr);
286 }
287
288 // Check default dtor body if required
289
2/4
✓ Branch 192 → 193 taken 11914 times.
✗ Branch 192 → 293 not taken.
✓ Branch 193 → 194 taken 11914 times.
✗ Branch 193 → 291 not taken.
35742 const Function *dtorFunc = FunctionManager::lookup(currentScope, DTOR_FUNCTION_NAME, structType, {}, true);
290
4/4
✓ Branch 197 → 198 taken 4373 times.
✓ Branch 197 → 200 taken 7541 times.
✓ Branch 198 → 199 taken 1709 times.
✓ Branch 198 → 200 taken 2664 times.
11914 if (dtorFunc != nullptr && dtorFunc->implicitDefault)
291
1/2
✓ Branch 199 → 200 taken 1709 times.
✗ Branch 199 → 300 not taken.
1709 createDtorBodyPreamble(dtorFunc->bodyScope, node);
292
293 // Reset field symbols to declared state for the next manifestation
294
1/2
✓ Branch 200 → 201 taken 11914 times.
✗ Branch 200 → 300 not taken.
11914 manifestation->resetFieldSymbolsToDeclared(node);
295
296 // Clear type mapping
297 11914 typeMapping.clear();
298
299 // Return to the root scope
300 11914 currentScope = rootScope;
301
2/4
✓ Branch 202 → 203 taken 11914 times.
✗ Branch 202 → 205 not taken.
✓ Branch 203 → 204 taken 11914 times.
✗ Branch 203 → 205 not taken.
11914 assert(currentScope != nullptr && currentScope->type == ScopeType::GLOBAL);
302
303 11914 manIdx++; // Increase the manifestation index
304 11914 }
305 8704 manIdx = 0; // Reset the manifestation index
306
307
1/2
✓ Branch 219 → 220 taken 8704 times.
✗ Branch 219 → 304 not taken.
17408 return nullptr;
308 }
309
310 30 std::any TypeChecker::visitUnionDefCheck(UnionDefNode *node) {
311 30 node->resizeToNumberOfManifestations(node->unionManifestations.size());
312 30 manIdx = 0; // Reset the manifestation index
313
314 // Get all manifestations for this union definition
315
2/2
✓ Branch 55 → 6 taken 30 times.
✓ Branch 55 → 56 taken 30 times.
90 for (Union *manifestation : node->unionManifestations) {
316 // Skip non-substantiated manifestations
317
3/4
✓ Branch 8 → 9 taken 30 times.
✗ Branch 8 → 63 not taken.
✓ Branch 9 → 10 taken 4 times.
✓ Branch 9 → 11 taken 26 times.
30 if (!manifestation->isFullySubstantiated()) {
318 4 manIdx++; // Increase the manifestation index
319 4 continue;
320 }
321
322 // Change to union scope
323
1/2
✓ Branch 11 → 12 taken 26 times.
✗ Branch 11 → 63 not taken.
26 changeToScope(manifestation->scope, ScopeType::UNION);
324
325 // Mount type mapping for this manifestation, so that the default value below can substantiate generic field types
326
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 26 times.
26 assert(typeMapping.empty());
327
1/2
✓ Branch 15 → 16 taken 26 times.
✗ Branch 15 → 63 not taken.
26 typeMapping = manifestation->typeMapping;
328
329 // Re-visit the default value (at most one field may have one). This is required, since the type of the default
330 // value might vary for different manifestations
331
2/2
✓ Branch 39 → 18 taken 52 times.
✓ Branch 39 → 40 taken 26 times.
104 for (const FieldNode *field : node->fields) {
332
2/2
✓ Branch 20 → 21 taken 8 times.
✓ Branch 20 → 30 taken 44 times.
52 if (field->defaultValue != nullptr) {
333
1/2
✓ Branch 21 → 22 taken 8 times.
✗ Branch 21 → 60 not taken.
8 visit(field->defaultValue);
334
1/2
✓ Branch 23 → 24 taken 8 times.
✗ Branch 23 → 62 not taken.
8 SymbolTableEntry *fieldEntry = manifestation->scope->lookupStrict(field->fieldName);
335
1/2
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 8 times.
8 assert(fieldEntry != nullptr);
336
1/2
✓ Branch 28 → 29 taken 8 times.
✗ Branch 28 → 61 not taken.
8 fieldEntry->updateState(INITIALIZED, field);
337 }
338 }
339
340 // Clear type mapping
341 26 typeMapping.clear();
342
343 // Return to the root scope
344 26 currentScope = rootScope;
345
2/4
✓ Branch 41 → 42 taken 26 times.
✗ Branch 41 → 44 not taken.
✓ Branch 42 → 43 taken 26 times.
✗ Branch 42 → 44 not taken.
26 assert(currentScope != nullptr && currentScope->type == ScopeType::GLOBAL);
346
347 26 manIdx++; // Increase the manifestation index
348 }
349 30 manIdx = 0; // Reset the manifestation index
350
351
1/2
✓ Branch 56 → 57 taken 30 times.
✗ Branch 56 → 64 not taken.
60 return nullptr;
352 }
353
354 } // namespace spice::compiler
355