GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 96.1% 397 / 3 / 416
Functions: 92.3% 12 / 0 / 13
Branches: 52.8% 634 / 8 / 1208

src/typechecker/TypeCheckerValues.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 <ast/Attributes.h>
8 #include <global/GlobalResourceManager.h>
9 #include <symboltablebuilder/ScopeHandle.h>
10 #include <symboltablebuilder/SymbolTableBuilder.h>
11 #include <typechecker/MacroDefs.h>
12 #include <typechecker/TypeMatcher.h>
13
14 namespace spice::compiler {
15
16 19896 std::any TypeChecker::visitValue(ValueNode *node) {
17 // Function call
18
2/2
✓ Branch 2 → 3 taken 17677 times.
✓ Branch 2 → 4 taken 2219 times.
19896 if (node->fctCall)
19 17677 return visit(node->fctCall);
20
21 // Array initialization
22
2/2
✓ Branch 4 → 5 taken 79 times.
✓ Branch 4 → 6 taken 2140 times.
2219 if (node->arrayInitialization)
23 79 return visit(node->arrayInitialization);
24
25 // Struct instantiation
26
2/2
✓ Branch 6 → 7 taken 297 times.
✓ Branch 6 → 8 taken 1843 times.
2140 if (node->structInstantiation)
27 297 return visit(node->structInstantiation);
28
29 // Lambda function
30
2/2
✓ Branch 8 → 9 taken 16 times.
✓ Branch 8 → 10 taken 1827 times.
1843 if (node->lambdaFunc)
31 16 return visit(node->lambdaFunc);
32
33 // Lambda procedure
34
2/2
✓ Branch 10 → 11 taken 32 times.
✓ Branch 10 → 12 taken 1795 times.
1827 if (node->lambdaProc)
35 32 return visit(node->lambdaProc);
36
37 // Lambda expression
38
2/2
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 14 taken 1794 times.
1795 if (node->lambdaExpr)
39 1 return visit(node->lambdaExpr);
40
41 // Typed nil
42
1/2
✓ Branch 14 → 15 taken 1794 times.
✗ Branch 14 → 41 not taken.
1794 if (node->isNil) {
43
2/4
✓ Branch 15 → 16 taken 1794 times.
✗ Branch 15 → 52 not taken.
✓ Branch 16 → 17 taken 1794 times.
✗ Branch 16 → 50 not taken.
1794 const auto nilType = std::any_cast<QualType>(visit(node->nilType));
44
2/8
✓ Branch 18 → 19 taken 1794 times.
✗ Branch 18 → 62 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 24 taken 1794 times.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 53 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 53 not taken.
1794 HANDLE_UNRESOLVED_TYPE_ER(nilType)
45
2/4
✓ Branch 24 → 25 taken 1794 times.
✗ Branch 24 → 62 not taken.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 36 taken 1794 times.
1794 if (nilType.is(TY_DYN))
46 SOFT_ERROR_ER(node->nilType, UNEXPECTED_DYN_TYPE, "Nil must have an explicit type")
47
2/4
✓ Branch 36 → 37 taken 1794 times.
✗ Branch 36 → 61 not taken.
✓ Branch 37 → 38 taken 1794 times.
✗ Branch 37 → 61 not taken.
1794 return ExprResult{node->setEvaluatedSymbolType(nilType, manIdx)};
48 }
49
50 throw CompilerError(UNHANDLED_BRANCH, "Value fall-through"); // GCOV_EXCL_LINE
51 }
52
53 23137 std::any TypeChecker::visitConstant(ConstantNode *node) {
54 SuperType superType;
55
7/8
✓ Branch 2 → 3 taken 658 times.
✓ Branch 2 → 4 taken 4219 times.
✓ Branch 2 → 5 taken 885 times.
✓ Branch 2 → 6 taken 8498 times.
✓ Branch 2 → 7 taken 2563 times.
✓ Branch 2 → 8 taken 3152 times.
✓ Branch 2 → 9 taken 3162 times.
✗ Branch 2 → 10 not taken.
23137 switch (node->type) {
56 658 case ConstantNode::PrimitiveValueType::TYPE_DOUBLE:
57 658 superType = TY_DOUBLE;
58 658 break;
59 4219 case ConstantNode::PrimitiveValueType::TYPE_INT:
60 4219 superType = TY_INT;
61 4219 break;
62 885 case ConstantNode::PrimitiveValueType::TYPE_SHORT:
63 885 superType = TY_SHORT;
64 885 break;
65 8498 case ConstantNode::PrimitiveValueType::TYPE_LONG:
66 8498 superType = TY_LONG;
67 8498 break;
68 2563 case ConstantNode::PrimitiveValueType::TYPE_CHAR:
69 2563 superType = TY_CHAR;
70 2563 break;
71 3152 case ConstantNode::PrimitiveValueType::TYPE_STRING:
72 3152 superType = TY_STRING;
73 3152 break;
74 3162 case ConstantNode::PrimitiveValueType::TYPE_BOOL:
75 3162 superType = TY_BOOL;
76 3162 break;
77 default: // GCOV_EXCL_LINE
78 throw CompilerError(UNHANDLED_BRANCH, "Constant fall-through"); // GCOV_EXCL_LINE
79 }
80
3/6
✓ Branch 18 → 19 taken 23137 times.
✗ Branch 18 → 33 not taken.
✓ Branch 19 → 20 taken 23137 times.
✗ Branch 19 → 33 not taken.
✓ Branch 20 → 21 taken 23137 times.
✗ Branch 20 → 33 not taken.
23137 return ExprResult{node->setEvaluatedSymbolType(QualType(superType), manIdx)};
81 }
82
83 17677 std::any TypeChecker::visitFctCall(FctCallNode *node) {
84
1/2
✓ Branch 2 → 3 taken 17677 times.
✗ Branch 2 → 502 not taken.
17677 FctCallNode::FctCallData &data = node->data.at(manIdx);
85 17677 auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope] = data;
86
87 // Retrieve arg types
88 17677 args.clear();
89
2/2
✓ Branch 4 → 5 taken 13909 times.
✓ Branch 4 → 28 taken 3768 times.
17677 if (node->hasArgs) {
90
1/2
✓ Branch 6 → 7 taken 13909 times.
✗ Branch 6 → 502 not taken.
13909 args.reserve(node->argLst->args.size());
91
2/2
✓ Branch 26 → 9 taken 24277 times.
✓ Branch 26 → 27 taken 13909 times.
38186 for (AssignExprNode *arg : node->argLst->args) {
92 // Visit argument
93
2/4
✓ Branch 10 → 11 taken 24277 times.
✗ Branch 10 → 387 not taken.
✓ Branch 11 → 12 taken 24277 times.
✗ Branch 11 → 385 not taken.
24277 const auto argResult = std::any_cast<ExprResult>(visit(arg));
94
2/8
✓ Branch 13 → 14 taken 24277 times.
✗ Branch 13 → 390 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 19 taken 24277 times.
✗ Branch 15 → 16 not taken.
✗ Branch 15 → 388 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 388 not taken.
24277 HANDLE_UNRESOLVED_TYPE_ER(argResult.type)
95
2/4
✓ Branch 19 → 20 taken 24277 times.
✗ Branch 19 → 390 not taken.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 24277 times.
24277 assert(!argResult.type.hasAnyGenericParts());
96 // Save arg type to arg types list
97
1/2
✓ Branch 23 → 24 taken 24277 times.
✗ Branch 23 → 389 not taken.
24277 args.emplace_back(argResult.type, argResult.isTemporary());
98 }
99 }
100
101 // Retrieve entry of the first fragment
102 17677 const std::string &firstFrag = node->functionNameFragments.front();
103
1/2
✓ Branch 29 → 30 taken 17677 times.
✗ Branch 29 → 502 not taken.
17677 SymbolTableEntry *firstFragEntry = currentScope->lookup(firstFrag);
104
2/2
✓ Branch 32 → 33 taken 10119 times.
✓ Branch 32 → 70 taken 7558 times.
17677 if (firstFragEntry) {
105 // Check if we have seen a 'this.' prefix, because the generator needs that
106
6/8
✓ Branch 33 → 34 taken 1 time.
✓ Branch 33 → 37 taken 10118 times.
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 402 not taken.
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 37 not taken.
✓ Branch 38 → 39 taken 1 time.
✓ Branch 38 → 48 taken 10118 times.
10119 if (firstFragEntry->scope->type == ScopeType::STRUCT && firstFrag != THIS_VARIABLE_NAME)
107
5/10
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 396 not taken.
✓ Branch 40 → 41 taken 1 time.
✗ Branch 40 → 394 not taken.
✓ Branch 41 → 42 taken 1 time.
✗ Branch 41 → 392 not taken.
✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 398 not taken.
✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 398 not taken.
1 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE,
108 "The symbol '" + firstFrag + "' could not be found. Missing 'this.' prefix?")
109
110 10118 firstFragEntry->used = true;
111 // Decide of which type the function call is
112
2/4
✓ Branch 48 → 49 taken 10118 times.
✗ Branch 48 → 402 not taken.
✓ Branch 49 → 50 taken 10118 times.
✗ Branch 49 → 402 not taken.
10118 const QualType &baseType = firstFragEntry->getQualType().getBase();
113
5/8
✓ Branch 50 → 51 taken 10118 times.
✗ Branch 50 → 402 not taken.
✓ Branch 51 → 52 taken 4 times.
✓ Branch 51 → 56 taken 10114 times.
✓ Branch 52 → 53 taken 4 times.
✗ Branch 52 → 399 not taken.
✓ Branch 53 → 54 taken 4 times.
✗ Branch 53 → 399 not taken.
10118 HANDLE_UNRESOLVED_TYPE_ER(baseType)
114
3/4
✓ Branch 56 → 57 taken 10114 times.
✗ Branch 56 → 400 not taken.
✓ Branch 57 → 58 taken 7591 times.
✓ Branch 57 → 61 taken 2523 times.
10114 if (baseType.isOneOf({TY_STRUCT, TY_INTERFACE})) {
115
2/2
✓ Branch 58 → 59 taken 1123 times.
✓ Branch 58 → 60 taken 6468 times.
7591 if (firstFragEntry->scope->type == ScopeType::GLOBAL)
116 1123 callType = FctCallNode::FctCallType::TYPE_CTOR;
117 else
118 6468 callType = FctCallNode::FctCallType::TYPE_METHOD;
119
7/8
✓ Branch 61 → 62 taken 2523 times.
✗ Branch 61 → 401 not taken.
✓ Branch 62 → 63 taken 2455 times.
✓ Branch 62 → 65 taken 68 times.
✓ Branch 63 → 64 taken 48 times.
✓ Branch 63 → 65 taken 2407 times.
✓ Branch 66 → 67 taken 48 times.
✓ Branch 66 → 68 taken 2475 times.
2523 } else if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && firstFragEntry->scope->type != ScopeType::GLOBAL) {
120 48 callType = FctCallNode::FctCallType::TYPE_FCT_PTR;
121 }
122 }
123
124 // Get struct name. Retrieve it from alias if required
125
1/2
✓ Branch 70 → 71 taken 17672 times.
✗ Branch 70 → 502 not taken.
17672 const auto &[structEntry, isAlias] = rootScope->symbolTable.lookupWithAliasResolution(node->fqFunctionName);
126
4/6
✓ Branch 73 → 74 taken 1 time.
✓ Branch 73 → 77 taken 17671 times.
✓ Branch 74 → 75 taken 1 time.
✗ Branch 74 → 502 not taken.
✓ Branch 75 → 76 taken 1 time.
✗ Branch 75 → 502 not taken.
17672 const std::string &fqFunctionName = isAlias ? structEntry->getQualType().getSubType() : node->fqFunctionName;
127
128 // Get the concrete template types
129 17672 templateTypes.clear();
130
2/2
✓ Branch 79 → 80 taken 1 time.
✓ Branch 79 → 99 taken 17671 times.
17672 if (isAlias) {
131 // Retrieve concrete template types from type alias
132
3/6
✓ Branch 80 → 81 taken 1 time.
✗ Branch 80 → 502 not taken.
✓ Branch 81 → 82 taken 1 time.
✗ Branch 81 → 502 not taken.
✓ Branch 82 → 83 taken 1 time.
✗ Branch 82 → 502 not taken.
1 templateTypes = structEntry->getQualType().getTemplateTypes();
133 // Check if the aliased type specified template types and the struct instantiation does
134
3/6
✓ Branch 84 → 85 taken 1 time.
✗ Branch 84 → 87 not taken.
✗ Branch 85 → 86 not taken.
✓ Branch 85 → 87 taken 1 time.
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 99 taken 1 time.
1 if (!templateTypes.empty() && node->hasTemplateTypes)
135 SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list")
136 }
137
138 // Get concrete template types
139
2/2
✓ Branch 99 → 100 taken 1114 times.
✓ Branch 99 → 135 taken 16558 times.
17672 if (node->hasTemplateTypes) {
140
2/2
✓ Branch 133 → 102 taken 1739 times.
✓ Branch 133 → 134 taken 1114 times.
2853 for (DataTypeNode *templateTypeNode : node->templateTypeLst->dataTypes) {
141
2/4
✓ Branch 103 → 104 taken 1739 times.
✗ Branch 103 → 412 not taken.
✓ Branch 104 → 105 taken 1739 times.
✗ Branch 104 → 410 not taken.
1739 auto templateType = std::any_cast<QualType>(visit(templateTypeNode));
142
2/4
✓ Branch 106 → 107 taken 1739 times.
✗ Branch 106 → 413 not taken.
✗ Branch 107 → 108 not taken.
✓ Branch 107 → 109 taken 1739 times.
1739 assert(!templateType.isOneOf({TY_DYN, TY_INVALID}));
143
144 // Abort if the type is unresolved
145
2/4
✓ Branch 109 → 110 taken 1739 times.
✗ Branch 109 → 423 not taken.
✗ Branch 110 → 111 not taken.
✓ Branch 110 → 117 taken 1739 times.
1739 if (templateType.is(TY_UNRESOLVED))
146 HANDLE_UNRESOLVED_TYPE_ER(templateType)
147
148 // Check if the given type is generic
149
2/4
✓ Branch 117 → 118 taken 1739 times.
✗ Branch 117 → 423 not taken.
✗ Branch 118 → 119 not taken.
✓ Branch 118 → 129 taken 1739 times.
1739 if (templateType.is(TY_GENERIC))
150 SOFT_ERROR_ER(templateTypeNode, EXPECTED_NON_GENERIC_TYPE, "You must specify a concrete type here")
151
152
1/2
✓ Branch 129 → 130 taken 1739 times.
✗ Branch 129 → 423 not taken.
1739 templateTypes.push_back(templateType);
153 }
154 }
155
156 // Check if this is a method call or a normal function call
157
2/2
✓ Branch 136 → 137 taken 6468 times.
✓ Branch 136 → 151 taken 11204 times.
17672 if (data.isMethodCall()) {
158 // This is a method call
159
1/2
✓ Branch 137 → 138 taken 6468 times.
✗ Branch 137 → 502 not taken.
6468 thisType = firstFragEntry->getQualType();
160
2/4
✓ Branch 138 → 139 taken 6468 times.
✗ Branch 138 → 425 not taken.
✓ Branch 139 → 140 taken 6468 times.
✗ Branch 139 → 425 not taken.
6468 Scope *structBodyScope = thisType.getBase().getBodyScope();
161
1/2
✗ Branch 140 → 141 not taken.
✓ Branch 140 → 142 taken 6468 times.
6468 assert(structBodyScope != nullptr);
162
3/4
✓ Branch 142 → 143 taken 6468 times.
✗ Branch 142 → 502 not taken.
✓ Branch 143 → 144 taken 2 times.
✓ Branch 143 → 149 taken 6466 times.
6468 if (!visitMethodCall(node, structBodyScope)) // Check if soft errors occurred
163
3/6
✓ Branch 144 → 145 taken 2 times.
✗ Branch 144 → 426 not taken.
✓ Branch 145 → 146 taken 2 times.
✗ Branch 145 → 426 not taken.
✓ Branch 146 → 147 taken 2 times.
✗ Branch 146 → 426 not taken.
2 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
164
1/2
✗ Branch 149 → 150 not taken.
✓ Branch 149 → 187 taken 6466 times.
6466 assert(calleeParentScope != nullptr);
165
2/2
✓ Branch 152 → 153 taken 48 times.
✓ Branch 152 → 166 taken 11156 times.
11204 } else if (data.isFctPtrCall()) {
166 // This is a function pointer call
167
2/4
✓ Branch 153 → 154 taken 48 times.
✗ Branch 153 → 431 not taken.
✓ Branch 154 → 155 taken 48 times.
✗ Branch 154 → 431 not taken.
48 const QualType &functionType = firstFragEntry->getQualType().getBase();
168
2/4
✓ Branch 155 → 156 taken 48 times.
✗ Branch 155 → 428 not taken.
✗ Branch 156 → 157 not taken.
✓ Branch 156 → 158 taken 48 times.
48 assert(functionType.isOneOf({TY_FUNCTION, TY_PROCEDURE}));
169
2/4
✓ Branch 158 → 159 taken 48 times.
✗ Branch 158 → 431 not taken.
✗ Branch 159 → 160 not taken.
✓ Branch 159 → 165 taken 48 times.
48 if (!visitFctPtrCall(node, functionType)) // Check if soft errors occurred
170 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
171 } else {
172 // This is an ordinary function call
173
3/4
✓ Branch 167 → 168 taken 1128 times.
✓ Branch 167 → 171 taken 10028 times.
✗ Branch 169 → 170 not taken.
✓ Branch 169 → 171 taken 1128 times.
11156 assert(data.isOrdinaryCall() || data.isCtorCall());
174
5/6
✓ Branch 171 → 172 taken 11156 times.
✗ Branch 171 → 434 not taken.
✓ Branch 172 → 173 taken 11154 times.
✓ Branch 172 → 432 taken 2 times.
✓ Branch 174 → 175 taken 4 times.
✓ Branch 174 → 180 taken 11150 times.
11158 if (!visitOrdinaryFctCall(node, fqFunctionName)) // Check if soft errors occurred
175
3/6
✓ Branch 175 → 176 taken 4 times.
✗ Branch 175 → 435 not taken.
✓ Branch 176 → 177 taken 4 times.
✗ Branch 176 → 435 not taken.
✓ Branch 177 → 178 taken 4 times.
✗ Branch 177 → 435 not taken.
4 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
176
1/2
✗ Branch 180 → 181 not taken.
✓ Branch 180 → 182 taken 11150 times.
11150 assert(calleeParentScope != nullptr);
177
178 // If the call is no ordinary call, it must be a constructor, which takes a struct as this type.
179
4/6
✓ Branch 183 → 184 taken 2464 times.
✓ Branch 183 → 187 taken 8686 times.
✓ Branch 184 → 185 taken 2464 times.
✗ Branch 184 → 502 not taken.
✗ Branch 185 → 186 not taken.
✓ Branch 185 → 187 taken 2464 times.
11150 assert(data.isOrdinaryCall() || data.thisType.is(TY_STRUCT));
180 }
181
182
2/2
✓ Branch 188 → 189 taken 17616 times.
✓ Branch 188 → 260 taken 48 times.
17664 if (!data.isFctPtrCall()) {
183 // Check if we were able to find a function
184
2/2
✓ Branch 189 → 190 taken 12 times.
✓ Branch 189 → 227 taken 17604 times.
17616 if (!callee) {
185 // Build error message
186
6/10
✓ Branch 191 → 192 taken 2 times.
✓ Branch 191 → 195 taken 10 times.
✓ Branch 194 → 197 taken 2 times.
✗ Branch 194 → 437 not taken.
✓ Branch 196 → 197 taken 10 times.
✗ Branch 196 → 437 not taken.
✓ Branch 197 → 198 taken 2 times.
✓ Branch 197 → 200 taken 10 times.
✗ Branch 437 → 438 not taken.
✗ Branch 437 → 440 not taken.
14 const std::string functionName = data.isCtorCall() ? CTOR_FUNCTION_NAME : node->functionNameFragments.back();
187 12 ParamList errArgTypes;
188
1/2
✓ Branch 201 → 202 taken 12 times.
✗ Branch 201 → 457 not taken.
12 errArgTypes.reserve(args.size());
189
5/8
✓ Branch 202 → 203 taken 12 times.
✗ Branch 202 → 443 not taken.
✓ Branch 203 → 204 taken 12 times.
✗ Branch 203 → 443 not taken.
✓ Branch 204 → 205 taken 12 times.
✗ Branch 204 → 443 not taken.
✓ Branch 210 → 206 taken 7 times.
✓ Branch 210 → 211 taken 12 times.
19 for (const auto &type : args | std::views::keys)
190
1/2
✓ Branch 207 → 208 taken 7 times.
✗ Branch 207 → 442 not taken.
7 errArgTypes.push_back({type, false});
191
2/4
✓ Branch 212 → 213 taken 12 times.
✗ Branch 212 → 444 not taken.
✓ Branch 213 → 214 taken 12 times.
✗ Branch 213 → 444 not taken.
12 const std::string signature = Function::getSignature(functionName, thisType, QualType(TY_DYN), errArgTypes, {}, false);
192 // Throw error
193
5/10
✓ Branch 215 → 216 taken 12 times.
✗ Branch 215 → 452 not taken.
✓ Branch 216 → 217 taken 12 times.
✗ Branch 216 → 450 not taken.
✓ Branch 217 → 218 taken 12 times.
✗ Branch 217 → 448 not taken.
✓ Branch 220 → 221 taken 12 times.
✗ Branch 220 → 454 not taken.
✓ Branch 221 → 222 taken 12 times.
✗ Branch 221 → 454 not taken.
12 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_FUNCTION, "Function/procedure '" + signature + "' could not be found")
194 12 }
195
196 // Check if we need to request a re-visit, because the function body was not type-checked yet
197
1/2
✓ Branch 227 → 228 taken 17604 times.
✗ Branch 227 → 502 not taken.
17604 requestRevisitIfRequired(callee);
198
199 // Get function entry from function object
200 17604 SymbolTableEntry *functionEntry = callee->entry;
201
202 // Check if the called function has sufficient visibility
203
1/2
✓ Branch 228 → 229 taken 17604 times.
✗ Branch 228 → 502 not taken.
17604 isImported = calleeParentScope->isImportedBy(rootScope);
204
8/10
✓ Branch 229 → 230 taken 4629 times.
✓ Branch 229 → 234 taken 12975 times.
✓ Branch 230 → 231 taken 4629 times.
✗ Branch 230 → 502 not taken.
✓ Branch 231 → 232 taken 4629 times.
✗ Branch 231 → 502 not taken.
✓ Branch 232 → 233 taken 1 time.
✓ Branch 232 → 234 taken 4628 times.
✓ Branch 235 → 236 taken 1 time.
✓ Branch 235 → 260 taken 17603 times.
17604 if (isImported && !functionEntry->getQualType().isPublic()) {
205
1/2
✓ Branch 236 → 237 taken 1 time.
✗ Branch 236 → 478 not taken.
1 const QualType functionEntryType = functionEntry->getQualType();
206
1/2
✓ Branch 237 → 238 taken 1 time.
✗ Branch 237 → 478 not taken.
1 const std::string signature = callee->getSignature();
207
2/4
✓ Branch 238 → 239 taken 1 time.
✗ Branch 238 → 476 not taken.
✓ Branch 239 → 240 taken 1 time.
✗ Branch 239 → 249 not taken.
1 if (functionEntryType.is(TY_FUNCTION))
208
5/10
✓ Branch 240 → 241 taken 1 time.
✗ Branch 240 → 466 not taken.
✓ Branch 241 → 242 taken 1 time.
✗ Branch 241 → 464 not taken.
✓ Branch 242 → 243 taken 1 time.
✗ Branch 242 → 462 not taken.
✓ Branch 245 → 246 taken 1 time.
✗ Branch 245 → 468 not taken.
✓ Branch 246 → 247 taken 1 time.
✗ Branch 246 → 468 not taken.
1 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Function '" + signature + "' has insufficient visibility")
209 else
210 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Procedure '" + signature + "' has insufficient visibility")
211 1 }
212 }
213
214 // Generate arg infos
215
2/2
✓ Branch 260 → 261 taken 13897 times.
✓ Branch 260 → 303 taken 3754 times.
17651 if (node->hasArgs) {
216 13897 QualTypeList paramTypes;
217
2/2
✓ Branch 262 → 263 taken 25 times.
✓ Branch 262 → 269 taken 13872 times.
13897 if (data.isFctPtrCall()) {
218
2/4
✓ Branch 263 → 264 taken 25 times.
✗ Branch 263 → 480 not taken.
✓ Branch 264 → 265 taken 25 times.
✗ Branch 264 → 480 not taken.
25 const QualType &functionType = firstFragEntry->getQualType().getBase();
219
1/2
✓ Branch 265 → 266 taken 25 times.
✗ Branch 265 → 479 not taken.
25 paramTypes = functionType.getFunctionParamTypes();
220 } else {
221
1/2
✗ Branch 269 → 270 not taken.
✓ Branch 269 → 271 taken 13872 times.
13872 assert(callee != nullptr);
222
1/2
✓ Branch 271 → 272 taken 13872 times.
✗ Branch 271 → 481 not taken.
13872 paramTypes = callee->getParamTypes();
223 }
224
225 13897 node->argLst->argInfos.clear();
226
2/2
✓ Branch 296 → 277 taken 24262 times.
✓ Branch 296 → 297 taken 13897 times.
38159 for (size_t argIdx = 0; argIdx < args.size(); argIdx++) {
227
1/2
✓ Branch 277 → 278 taken 24262 times.
✗ Branch 277 → 483 not taken.
24262 const QualType &expectedType = paramTypes.at(argIdx);
228
1/2
✓ Branch 278 → 279 taken 24262 times.
✗ Branch 278 → 483 not taken.
24262 const auto &[actualType, _] = args.at(argIdx);
229
230 24262 Function *copyCtor = nullptr;
231
11/14
✓ Branch 281 → 282 taken 24262 times.
✗ Branch 281 → 483 not taken.
✓ Branch 282 → 283 taken 38 times.
✓ Branch 282 → 288 taken 24224 times.
✓ Branch 283 → 284 taken 38 times.
✗ Branch 283 → 483 not taken.
✓ Branch 284 → 285 taken 34 times.
✓ Branch 284 → 288 taken 4 times.
✓ Branch 285 → 286 taken 34 times.
✗ Branch 285 → 483 not taken.
✓ Branch 286 → 287 taken 14 times.
✓ Branch 286 → 288 taken 20 times.
✓ Branch 289 → 290 taken 14 times.
✓ Branch 289 → 293 taken 24248 times.
24262 if (expectedType.is(TY_STRUCT) && actualType.is(TY_STRUCT) && !actualType.isTriviallyCopyable(node)) {
232
1/2
✓ Branch 290 → 291 taken 14 times.
✗ Branch 290 → 483 not taken.
14 copyCtor = matchCopyCtor(actualType, node);
233 // Insert anonymous symbol to track the dtor call of the copy
234
1/2
✓ Branch 291 → 292 taken 14 times.
✗ Branch 291 → 483 not taken.
14 AssignExprNode *argNode = node->argLst->args.at(argIdx);
235
1/2
✓ Branch 292 → 293 taken 14 times.
✗ Branch 292 → 483 not taken.
14 currentScope->symbolTable.insertAnonymous(actualType, argNode, SIZE_MAX);
236 }
237
238
1/2
✓ Branch 293 → 294 taken 24262 times.
✗ Branch 293 → 482 not taken.
24262 node->argLst->argInfos.push_back(ArgLstNode::ArgInfo{copyCtor});
239 }
240
1/2
✗ Branch 299 → 300 not taken.
✓ Branch 299 → 301 taken 13897 times.
13897 assert(node->argLst->argInfos.size() == node->argLst->args.size());
241 13897 }
242
243 // Retrieve return type
244
6/10
✓ Branch 304 → 305 taken 48 times.
✓ Branch 304 → 309 taken 17603 times.
✓ Branch 305 → 306 taken 48 times.
✗ Branch 305 → 486 not taken.
✓ Branch 306 → 307 taken 48 times.
✗ Branch 306 → 486 not taken.
✓ Branch 307 → 308 taken 48 times.
✗ Branch 307 → 486 not taken.
✓ Branch 309 → 310 taken 17603 times.
✗ Branch 309 → 486 not taken.
35254 const bool isFct = data.isFctPtrCall() ? firstFragEntry->getQualType().getBase().is(TY_FUNCTION) : callee->isFunction();
245 17651 QualType returnType;
246
2/2
✓ Branch 314 → 315 taken 48 times.
✓ Branch 314 → 322 taken 17603 times.
17651 if (data.isFctPtrCall()) {
247
6/10
✓ Branch 315 → 316 taken 20 times.
✓ Branch 315 → 320 taken 28 times.
✓ Branch 316 → 317 taken 20 times.
✗ Branch 316 → 487 not taken.
✓ Branch 317 → 318 taken 20 times.
✗ Branch 317 → 487 not taken.
✓ Branch 318 → 319 taken 20 times.
✗ Branch 318 → 487 not taken.
✓ Branch 320 → 321 taken 28 times.
✗ Branch 320 → 487 not taken.
48 returnType = isFct ? firstFragEntry->getQualType().getBase().getFunctionReturnType() : QualType(TY_BOOL);
248
2/2
✓ Branch 323 → 324 taken 2462 times.
✓ Branch 323 → 325 taken 15141 times.
17603 } else if (data.isCtorCall()) {
249 2462 returnType = thisType;
250
3/4
✓ Branch 325 → 326 taken 15141 times.
✗ Branch 325 → 502 not taken.
✓ Branch 328 → 329 taken 4583 times.
✓ Branch 328 → 331 taken 10558 times.
30282 } else if (callee->isProcedure()) {
251
1/2
✓ Branch 329 → 330 taken 4583 times.
✗ Branch 329 → 489 not taken.
4583 returnType = QualType(TY_DYN);
252 } else {
253 10558 returnType = callee->returnType;
254 }
255
1/2
✓ Branch 332 → 333 taken 17651 times.
✗ Branch 332 → 502 not taken.
17651 const QualType returnBaseType = returnType.getBase();
256
257 // Make sure this source file knows about the return type
258
3/4
✓ Branch 333 → 334 taken 17651 times.
✗ Branch 333 → 502 not taken.
✓ Branch 334 → 335 taken 3885 times.
✓ Branch 334 → 338 taken 13766 times.
17651 if (returnBaseType.is(TY_STRUCT))
259
2/4
✓ Branch 335 → 336 taken 3885 times.
✗ Branch 335 → 490 not taken.
✓ Branch 336 → 337 taken 3885 times.
✗ Branch 336 → 490 not taken.
3885 returnType = mapImportedScopeTypeToLocalType(returnBaseType.getBodyScope(), returnType);
260
261 // Add anonymous symbol to keep track of dtor call, if non-trivially destructible
262 17651 SymbolTableEntry *anonymousSymbol = nullptr;
263
8/10
✓ Branch 338 → 339 taken 17651 times.
✗ Branch 338 → 502 not taken.
✓ Branch 339 → 340 taken 3418 times.
✓ Branch 339 → 343 taken 14233 times.
✓ Branch 340 → 341 taken 3418 times.
✗ Branch 340 → 502 not taken.
✓ Branch 341 → 342 taken 2241 times.
✓ Branch 341 → 343 taken 1177 times.
✓ Branch 344 → 345 taken 2241 times.
✓ Branch 344 → 347 taken 15410 times.
17651 if (returnType.is(TY_STRUCT) && !returnType.isTriviallyDestructible(node))
264
1/2
✓ Branch 345 → 346 taken 2241 times.
✗ Branch 345 → 502 not taken.
2241 anonymousSymbol = currentScope->symbolTable.insertAnonymous(returnType, node);
265
266 // Remove public qualifier to not have public local variables
267 17651 returnType.getQualifiers().isPublic = false;
268
269 // Check if the return value gets discarded
270
7/8
✓ Branch 348 → 349 taken 10578 times.
✓ Branch 348 → 352 taken 7073 times.
✓ Branch 349 → 350 taken 10578 times.
✗ Branch 349 → 502 not taken.
✓ Branch 350 → 351 taken 218 times.
✓ Branch 350 → 352 taken 10360 times.
✓ Branch 353 → 354 taken 218 times.
✓ Branch 353 → 379 taken 17433 times.
17651 if (isFct && !node->hasReturnValueReceiver()) {
271 // Check if we want to ignore the discarded return value
272 218 bool ignoreUnusedReturnValue = false;
273
2/2
✓ Branch 355 → 356 taken 215 times.
✓ Branch 355 → 376 taken 3 times.
218 if (!data.isFctPtrCall()) {
274
1/2
✗ Branch 356 → 357 not taken.
✓ Branch 356 → 358 taken 215 times.
215 assert(callee != nullptr);
275
1/2
✓ Branch 358 → 359 taken 215 times.
✗ Branch 358 → 360 not taken.
215 auto fctDef = dynamic_cast<const FctDefNode *>(callee->declNode);
276
12/18
✓ Branch 361 → 362 taken 102 times.
✓ Branch 361 → 369 taken 113 times.
✓ Branch 362 → 363 taken 27 times.
✓ Branch 362 → 369 taken 75 times.
✓ Branch 365 → 366 taken 27 times.
✗ Branch 365 → 491 not taken.
✓ Branch 366 → 367 taken 27 times.
✗ Branch 366 → 491 not taken.
✓ Branch 367 → 368 taken 26 times.
✓ Branch 367 → 369 taken 1 time.
✓ Branch 370 → 371 taken 27 times.
✓ Branch 370 → 372 taken 188 times.
✓ Branch 372 → 373 taken 27 times.
✓ Branch 372 → 375 taken 188 times.
✗ Branch 491 → 492 not taken.
✗ Branch 491 → 493 not taken.
✗ Branch 495 → 496 not taken.
✗ Branch 495 → 498 not taken.
269 ignoreUnusedReturnValue = fctDef && fctDef->attrs && fctDef->attrs->attrLst->hasAttr(ATTR_IGNORE_UNUSED_RETURN_VALUE);
277 }
278
279
2/2
✓ Branch 376 → 377 taken 192 times.
✓ Branch 376 → 379 taken 26 times.
218 if (!ignoreUnusedReturnValue)
280
1/2
✓ Branch 377 → 378 taken 192 times.
✗ Branch 377 → 500 not taken.
192 warnings.emplace_back(node->codeLoc, UNUSED_RETURN_VALUE, "The return value of the function call is unused");
281 }
282
283
2/4
✓ Branch 379 → 380 taken 17651 times.
✗ Branch 379 → 501 not taken.
✓ Branch 380 → 381 taken 17651 times.
✗ Branch 380 → 501 not taken.
17651 return ExprResult{node->setEvaluatedSymbolType(returnType, manIdx), anonymousSymbol};
284 }
285
286 11156 bool TypeChecker::visitOrdinaryFctCall(FctCallNode *node, std::string fqFunctionName) const {
287
1/2
✓ Branch 2 → 3 taken 11156 times.
✗ Branch 2 → 106 not taken.
11156 FctCallNode::FctCallData &data = node->data.at(manIdx);
288 11156 auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope] = data;
289
290 // Check if this is a well-known ctor/fct call
291
2/2
✓ Branch 4 → 5 taken 11094 times.
✓ Branch 4 → 7 taken 62 times.
11156 if (node->functionNameFragments.size() == 1) {
292
1/2
✓ Branch 5 → 6 taken 11094 times.
✗ Branch 5 → 106 not taken.
11094 ensureLoadedRuntimeForTypeName(fqFunctionName);
293
1/2
✓ Branch 6 → 7 taken 11094 times.
✗ Branch 6 → 106 not taken.
11094 ensureLoadedRuntimeForFunctionName(fqFunctionName);
294 }
295
296 // Check if the type is generic (possible in case of ctor call)
297
1/2
✓ Branch 7 → 8 taken 11156 times.
✗ Branch 7 → 106 not taken.
11156 const QualType *genericType = rootScope->lookupGenericTypeStrict(fqFunctionName);
298
6/8
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 12 taken 11155 times.
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 106 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 12 not taken.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 19 taken 11155 times.
11156 if (genericType && typeMapping.contains(fqFunctionName)) {
299
1/2
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 106 not taken.
1 const QualType &replacementType = typeMapping.at(fqFunctionName);
300
2/4
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 106 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 19 not taken.
1 if (replacementType.is(TY_STRUCT))
301
2/4
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 106 not taken.
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 106 not taken.
1 fqFunctionName = replacementType.getSubType();
302 }
303
304 // Check if the exported name registry contains that function name
305
1/2
✓ Branch 19 → 20 taken 11156 times.
✗ Branch 19 → 106 not taken.
11156 const NameRegistryEntry *functionRegistryEntry = sourceFile->getNameRegistryEntry(fqFunctionName);
306
2/2
✓ Branch 20 → 21 taken 3 times.
✓ Branch 20 → 29 taken 11153 times.
11156 if (!functionRegistryEntry) {
307
2/4
✓ Branch 22 → 23 taken 3 times.
✗ Branch 22 → 86 not taken.
✓ Branch 23 → 24 taken 3 times.
✗ Branch 23 → 84 not taken.
3 const std::string msg = "Function/procedure/struct '" + node->functionNameFragments.back() + "' could not be found";
308
1/2
✓ Branch 25 → 26 taken 3 times.
✗ Branch 25 → 87 not taken.
3 SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, msg)
309 3 }
310 11153 const SymbolTableEntry *functionEntry = functionRegistryEntry->targetEntry;
311 11153 calleeParentScope = functionRegistryEntry->targetScope;
312
313 // Check if the target symbol is a struct -> this must be a constructor call
314
1/2
✓ Branch 30 → 31 taken 11153 times.
✗ Branch 30 → 106 not taken.
11153 std::string functionName = node->functionNameFragments.back();
315
7/10
✓ Branch 31 → 32 taken 11153 times.
✗ Branch 31 → 36 not taken.
✓ Branch 32 → 33 taken 11153 times.
✗ Branch 32 → 104 not taken.
✓ Branch 33 → 34 taken 11153 times.
✗ Branch 33 → 104 not taken.
✓ Branch 34 → 35 taken 2465 times.
✓ Branch 34 → 36 taken 8688 times.
✓ Branch 37 → 38 taken 2465 times.
✓ Branch 37 → 54 taken 8688 times.
11153 if (functionEntry != nullptr && functionEntry->getQualType().is(TY_STRUCT)) {
316 2465 callType = FctCallNode::FctCallType::TYPE_CTOR;
317
1/2
✓ Branch 38 → 39 taken 2465 times.
✗ Branch 38 → 104 not taken.
2465 functionName = CTOR_FUNCTION_NAME;
318
319 2465 const NameRegistryEntry *structRegistryEntry = functionRegistryEntry;
320 2465 const SymbolTableEntry *structEntry = functionEntry;
321
322 // Substantiate potentially generic this struct
323
2/4
✓ Branch 39 → 40 taken 2465 times.
✗ Branch 39 → 104 not taken.
✓ Branch 40 → 41 taken 2465 times.
✗ Branch 40 → 104 not taken.
2465 const Struct *thisStruct = structEntry->getQualType().getStruct(node, templateTypes);
324
2/2
✓ Branch 41 → 42 taken 1 time.
✓ Branch 41 → 51 taken 2464 times.
2465 if (!thisStruct) {
325
1/2
✓ Branch 42 → 43 taken 1 time.
✗ Branch 42 → 97 not taken.
1 const std::string signature = Struct::getSignature(structRegistryEntry->targetEntry->name, templateTypes);
326
2/4
✓ Branch 43 → 44 taken 1 time.
✗ Branch 43 → 92 not taken.
✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 90 not taken.
1 const std::string errorMsg = "Could not find struct candidate for struct '" + signature + "'. Do the template types match?";
327
1/2
✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 93 not taken.
1 SOFT_ERROR_BOOL(node, UNKNOWN_DATATYPE, errorMsg)
328 1 }
329
330 // Set the 'this' type of the function to the struct type
331
2/4
✓ Branch 51 → 52 taken 2464 times.
✗ Branch 51 → 98 not taken.
✓ Branch 52 → 53 taken 2464 times.
✗ Branch 52 → 98 not taken.
2464 thisType = structEntry->getQualType().getWithBodyScope(thisStruct->scope);
332 2464 calleeParentScope = thisStruct->scope;
333 }
334
335 // Attach the concrete template types to the 'this' type
336
7/8
✓ Branch 54 → 55 taken 11152 times.
✗ Branch 54 → 104 not taken.
✓ Branch 55 → 56 taken 2464 times.
✓ Branch 55 → 59 taken 8688 times.
✓ Branch 57 → 58 taken 408 times.
✓ Branch 57 → 59 taken 2056 times.
✓ Branch 60 → 61 taken 408 times.
✓ Branch 60 → 63 taken 10744 times.
11152 if (!thisType.is(TY_DYN) && !templateTypes.empty())
337
1/2
✓ Branch 61 → 62 taken 408 times.
✗ Branch 61 → 99 not taken.
408 thisType = thisType.getWithTemplateTypes(templateTypes);
338
339 // Map local arg types to imported types
340
5/8
✓ Branch 63 → 64 taken 11152 times.
✗ Branch 63 → 101 not taken.
✓ Branch 64 → 65 taken 11152 times.
✗ Branch 64 → 101 not taken.
✓ Branch 65 → 66 taken 11152 times.
✗ Branch 65 → 101 not taken.
✓ Branch 71 → 67 taken 19598 times.
✓ Branch 71 → 72 taken 11152 times.
30750 for (QualType &argType : args | std::views::keys)
341
1/2
✓ Branch 68 → 69 taken 19598 times.
✗ Branch 68 → 100 not taken.
19598 argType = mapLocalTypeToImportedScopeType(calleeParentScope, argType);
342
343 // Map local template types to imported types
344
2/2
✓ Branch 78 → 74 taken 1740 times.
✓ Branch 78 → 79 taken 11152 times.
12892 for (QualType &templateType : templateTypes)
345
1/2
✓ Branch 75 → 76 taken 1740 times.
✗ Branch 75 → 102 not taken.
1740 templateType = mapLocalTypeToImportedScopeType(calleeParentScope, templateType);
346
347 // Retrieve function object
348 11152 Scope *matchScope = calleeParentScope;
349
2/2
✓ Branch 79 → 80 taken 11150 times.
✓ Branch 79 → 104 taken 2 times.
11152 callee = FunctionManager::match(matchScope, functionName, data.thisType, data.args, templateTypes, false, node);
350
351 11150 return true;
352 11153 }
353
354 48 bool TypeChecker::visitFctPtrCall(const FctCallNode *node, const QualType &functionType) const {
355
1/2
✓ Branch 2 → 3 taken 48 times.
✗ Branch 2 → 75 not taken.
48 const FctCallNode::FctCallData &data = node->data.at(manIdx);
356 48 const auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope] = data;
357
358 // Check if the given argument types match the type
359
1/2
✓ Branch 3 → 4 taken 48 times.
✗ Branch 3 → 75 not taken.
48 const QualTypeList expectedArgTypes = functionType.getFunctionParamTypes();
360
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 14 taken 48 times.
48 if (args.size() != expectedArgTypes.size())
361 SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, "Expected and actual number of arguments do not match")
362
363 // Create resolver function, that always returns a nullptr
364 48 TypeMatcher::ResolverFct resolverFct = [](const std::string &) { return nullptr; };
365
366
2/2
✓ Branch 41 → 16 taken 31 times.
✓ Branch 41 → 42 taken 48 times.
79 for (size_t i = 0; i < args.size(); i++) {
367
1/2
✓ Branch 16 → 17 taken 31 times.
✗ Branch 16 → 71 not taken.
31 const QualType &actualType = args.at(i).first;
368
1/2
✓ Branch 17 → 18 taken 31 times.
✗ Branch 17 → 71 not taken.
31 const QualType &expectedType = expectedArgTypes.at(i);
369
2/4
✓ Branch 19 → 20 taken 31 times.
✗ Branch 19 → 68 not taken.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 34 taken 31 times.
31 if (TypeMapping tm; !TypeMatcher::matchRequestedToCandidateType(expectedType, actualType, tm, resolverFct, false))
370
1/16
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 66 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 61 not taken.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 59 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 57 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 25 → 55 not taken.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 53 not taken.
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 53 not taken.
✓ Branch 36 → 37 taken 31 times.
✗ Branch 36 → 39 not taken.
31 SOFT_ERROR_BOOL(node->argLst->args.at(i), REFERENCED_UNDEFINED_FUNCTION,
371 "Expected " + expectedType.getName(false) + " but got " + actualType.getName(false))
372 }
373 48 return true;
374 48 }
375
376 6468 bool TypeChecker::visitMethodCall(FctCallNode *node, Scope *structScope) const {
377 6468 FctCallNode::FctCallData &data = node->data.at(manIdx);
378 6468 auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope] = data;
379
380 // Traverse through structs - the first fragment is already looked up and the last one is the method name
381
2/2
✓ Branch 41 → 4 taken 854 times.
✓ Branch 41 → 42 taken 6466 times.
7320 for (size_t i = 1; i < node->functionNameFragments.size() - 1; i++) {
382 854 const std::string &identifier = node->functionNameFragments.at(i);
383
384 // Retrieve field entry
385 854 SymbolTableEntry *fieldEntry = structScope->lookupStrict(identifier);
386
2/2
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 24 taken 853 times.
854 if (!fieldEntry) {
387
1/2
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 82 not taken.
1 std::stringstream errorMsg;
388
1/2
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 80 not taken.
1 errorMsg << "The type '";
389
3/6
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 75 not taken.
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 75 not taken.
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 73 not taken.
1 errorMsg << thisType.getBase().getName(false, true);
390
3/6
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 80 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 80 not taken.
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 80 not taken.
1 errorMsg << "' does not have a member with the name '" << identifier << "'";
391
2/4
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 79 not taken.
✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 77 not taken.
1 SOFT_ERROR_BOOL(node, ACCESS_TO_NON_EXISTING_MEMBER, errorMsg.str())
392 1 }
393
5/8
✓ Branch 24 → 25 taken 853 times.
✗ Branch 24 → 84 not taken.
✓ Branch 25 → 26 taken 853 times.
✗ Branch 25 → 84 not taken.
✓ Branch 26 → 27 taken 853 times.
✗ Branch 26 → 83 not taken.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 27 → 34 taken 852 times.
853 if (!fieldEntry->getQualType().getBase().isOneOf({TY_STRUCT, TY_INTERFACE}))
394
3/6
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 89 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 87 not taken.
✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 85 not taken.
1 SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS,
395 "Cannot call a method on '" + identifier + "', since it is no struct or interface")
396 852 fieldEntry->used = true;
397
398 // Get struct type and scope
399 852 thisType = fieldEntry->getQualType();
400
2/4
✓ Branch 35 → 36 taken 852 times.
✗ Branch 35 → 91 not taken.
✓ Branch 36 → 37 taken 852 times.
✗ Branch 36 → 91 not taken.
852 structScope = thisType.getBase().getBodyScope();
401
1/2
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 39 taken 852 times.
852 assert(structScope != nullptr);
402 }
403
404
1/2
✗ Branch 43 → 44 not taken.
✓ Branch 43 → 51 taken 6466 times.
6466 if (thisType.is(TY_INTERFACE))
405 SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS, "Cannot call a method on an interface")
406
407 // Map local arg types to imported types
408 6466 Scope *matchScope = calleeParentScope = structScope;
409
5/8
✓ Branch 51 → 52 taken 6466 times.
✗ Branch 51 → 99 not taken.
✓ Branch 52 → 53 taken 6466 times.
✗ Branch 52 → 99 not taken.
✓ Branch 53 → 54 taken 6466 times.
✗ Branch 53 → 99 not taken.
✓ Branch 59 → 55 taken 4642 times.
✓ Branch 59 → 60 taken 6466 times.
11108 for (QualType &argType : args | std::views::keys)
410
1/2
✓ Branch 56 → 57 taken 4642 times.
✗ Branch 56 → 98 not taken.
4642 argType = mapLocalTypeToImportedScopeType(calleeParentScope, argType);
411
412 // Map local template types to imported types
413
1/2
✗ Branch 66 → 62 not taken.
✓ Branch 66 → 67 taken 6466 times.
6466 for (QualType &templateType : templateTypes)
414 templateType = mapLocalTypeToImportedScopeType(calleeParentScope, templateType);
415
416 // 'this' type
417
1/2
✓ Branch 67 → 68 taken 6466 times.
✗ Branch 67 → 102 not taken.
6466 thisType = thisType.autoDeReference();
418
1/2
✓ Branch 68 → 69 taken 6466 times.
✗ Branch 68 → 103 not taken.
6466 thisType = mapLocalTypeToImportedScopeType(calleeParentScope, thisType);
419
420 // Retrieve function object
421 6466 const std::string &functionName = node->functionNameFragments.back();
422 6466 callee = FunctionManager::match(matchScope, functionName, thisType, args, templateTypes, false, node);
423
424 6466 return true;
425 }
426
427 79 std::any TypeChecker::visitArrayInitialization(ArrayInitializationNode *node) {
428
5/6
✓ Branch 2 → 3 taken 78 times.
✓ Branch 2 → 5 taken 1 time.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 78 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 18 taken 78 times.
79 if (!node->itemLst || node->itemLst->args.empty())
429
4/8
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 68 not taken.
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 66 not taken.
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 72 not taken.
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 72 not taken.
3 SOFT_ERROR_ER(node, ARRAY_SIZE_INVALID, "Array initializers must at least contain one value");
430 78 node->actualSize = node->itemLst->args.size();
431
432
1/2
✓ Branch 19 → 20 taken 78 times.
✗ Branch 19 → 97 not taken.
78 QualType actualItemType(TY_DYN);
433 // Check if all values have the same type
434
2/2
✓ Branch 55 → 22 taken 514 times.
✓ Branch 55 → 56 taken 77 times.
591 for (AssignExprNode *arg : node->itemLst->args) {
435
2/4
✓ Branch 23 → 24 taken 514 times.
✗ Branch 23 → 75 not taken.
✓ Branch 24 → 25 taken 514 times.
✗ Branch 24 → 73 not taken.
514 const QualType itemType = std::any_cast<ExprResult>(visit(arg)).type;
436
2/8
✓ Branch 26 → 27 taken 514 times.
✗ Branch 26 → 94 not taken.
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 32 taken 514 times.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 77 not taken.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 77 not taken.
514 HANDLE_UNRESOLVED_TYPE_ER(itemType)
437
3/4
✓ Branch 32 → 33 taken 514 times.
✗ Branch 32 → 94 not taken.
✓ Branch 33 → 34 taken 78 times.
✓ Branch 33 → 35 taken 436 times.
514 if (actualItemType.is(TY_DYN)) // Perform type inference
438 78 actualItemType = itemType;
439
3/4
✓ Branch 35 → 36 taken 436 times.
✗ Branch 35 → 94 not taken.
✓ Branch 36 → 37 taken 1 time.
✓ Branch 36 → 52 taken 435 times.
436 else if (itemType != actualItemType) // Check if types are matching
440
8/16
✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 91 not taken.
✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 86 not taken.
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 84 not taken.
✓ Branch 40 → 41 taken 1 time.
✗ Branch 40 → 82 not taken.
✓ Branch 41 → 42 taken 1 time.
✗ Branch 41 → 80 not taken.
✓ Branch 42 → 43 taken 1 time.
✗ Branch 42 → 78 not taken.
✓ Branch 48 → 49 taken 1 time.
✗ Branch 48 → 93 not taken.
✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 93 not taken.
1 SOFT_ERROR_ER(arg, ARRAY_ITEM_TYPE_NOT_MATCHING,
441 "All provided values have to be of the same data type. You provided " + actualItemType.getName(false) +
442 " and " + itemType.getName(false))
443 }
444
2/4
✓ Branch 56 → 57 taken 77 times.
✗ Branch 56 → 97 not taken.
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 59 taken 77 times.
77 assert(!actualItemType.is(TY_DYN));
445
446
1/2
✓ Branch 59 → 60 taken 77 times.
✗ Branch 59 → 97 not taken.
77 const QualType arrayType = actualItemType.toArr(node, node->actualSize, true);
447
2/4
✓ Branch 60 → 61 taken 77 times.
✗ Branch 60 → 96 not taken.
✓ Branch 61 → 62 taken 77 times.
✗ Branch 61 → 96 not taken.
77 return ExprResult{node->setEvaluatedSymbolType(arrayType, manIdx)};
448 }
449
450 297 std::any TypeChecker::visitStructInstantiation(StructInstantiationNode *node) {
451 // Retrieve struct name
452
1/2
✓ Branch 2 → 3 taken 297 times.
✗ Branch 2 → 264 not taken.
297 const auto [aliasedEntry, isAlias] = rootScope->symbolTable.lookupWithAliasResolution(node->fqStructName);
453
4/6
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 9 taken 296 times.
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 264 not taken.
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 264 not taken.
297 const std::string &structName = isAlias ? aliasedEntry->getQualType().getSubType() : node->fqStructName;
454
455 // Retrieve struct
456
1/2
✓ Branch 10 → 11 taken 297 times.
✗ Branch 10 → 264 not taken.
297 const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(structName);
457
2/2
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 21 taken 296 times.
297 if (!registryEntry)
458
5/10
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 195 not taken.
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 193 not taken.
✓ Branch 14 → 15 taken 1 time.
✗ Branch 14 → 191 not taken.
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 197 not taken.
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 197 not taken.
1 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT, "Cannot find struct '" + structName + "'")
459
2/4
✓ Branch 21 → 22 taken 296 times.
✗ Branch 21 → 24 not taken.
✓ Branch 22 → 23 taken 296 times.
✗ Branch 22 → 24 not taken.
296 assert(registryEntry->targetEntry != nullptr && registryEntry->targetScope != nullptr);
460 296 SymbolTableEntry *structEntry = registryEntry->targetEntry;
461
462 // Check visibility
463
9/12
✓ Branch 25 → 26 taken 296 times.
✗ Branch 25 → 264 not taken.
✓ Branch 26 → 27 taken 296 times.
✗ Branch 26 → 264 not taken.
✓ Branch 27 → 28 taken 63 times.
✓ Branch 27 → 31 taken 233 times.
✓ Branch 28 → 29 taken 63 times.
✗ Branch 28 → 264 not taken.
✓ Branch 29 → 30 taken 1 time.
✓ Branch 29 → 31 taken 62 times.
✓ Branch 32 → 33 taken 1 time.
✓ Branch 32 → 42 taken 295 times.
296 if (!structEntry->getQualType().isPublic() && structEntry->scope->isImportedBy(currentScope))
464
5/10
✓ Branch 33 → 34 taken 1 time.
✗ Branch 33 → 202 not taken.
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 200 not taken.
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 198 not taken.
✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 204 not taken.
✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 204 not taken.
1 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Struct '" + structName + "' has insufficient visibility")
465
466 // Get struct type
467
1/2
✓ Branch 42 → 43 taken 295 times.
✗ Branch 42 → 264 not taken.
295 QualType structType = structEntry->getQualType();
468
469 // Get the concrete template types
470 295 QualTypeList concreteTemplateTypes;
471
2/2
✓ Branch 43 → 44 taken 1 time.
✓ Branch 43 → 63 taken 294 times.
295 if (isAlias) {
472 // Retrieve concrete template types from type alias
473
3/6
✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 262 not taken.
✓ Branch 45 → 46 taken 1 time.
✗ Branch 45 → 262 not taken.
✓ Branch 46 → 47 taken 1 time.
✗ Branch 46 → 262 not taken.
1 concreteTemplateTypes = aliasedEntry->getQualType().getTemplateTypes();
474 // Check if the aliased type specified template types and the struct instantiation does
475
3/6
✓ Branch 48 → 49 taken 1 time.
✗ Branch 48 → 51 not taken.
✗ Branch 49 → 50 not taken.
✓ Branch 49 → 51 taken 1 time.
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 63 taken 1 time.
1 if (!concreteTemplateTypes.empty() && node->templateTypeLst)
476 SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list")
477 }
478
479
2/2
✓ Branch 63 → 64 taken 19 times.
✓ Branch 63 → 96 taken 276 times.
295 if (node->templateTypeLst) {
480
1/2
✓ Branch 65 → 66 taken 19 times.
✗ Branch 65 → 262 not taken.
19 concreteTemplateTypes.reserve(node->templateTypeLst->dataTypes.size());
481
2/2
✓ Branch 94 → 68 taken 31 times.
✓ Branch 94 → 95 taken 19 times.
50 for (DataTypeNode *dataType : node->templateTypeLst->dataTypes) {
482
2/4
✓ Branch 69 → 70 taken 31 times.
✗ Branch 69 → 214 not taken.
✓ Branch 70 → 71 taken 31 times.
✗ Branch 70 → 212 not taken.
31 auto concreteType = std::any_cast<QualType>(visit(dataType));
483
2/8
✓ Branch 72 → 73 taken 31 times.
✗ Branch 72 → 223 not taken.
✗ Branch 73 → 74 not taken.
✓ Branch 73 → 78 taken 31 times.
✗ Branch 74 → 75 not taken.
✗ Branch 74 → 215 not taken.
✗ Branch 75 → 76 not taken.
✗ Branch 75 → 215 not taken.
31 HANDLE_UNRESOLVED_TYPE_ER(concreteType)
484 // Check if generic type
485
2/4
✓ Branch 78 → 79 taken 31 times.
✗ Branch 78 → 223 not taken.
✗ Branch 79 → 80 not taken.
✓ Branch 79 → 90 taken 31 times.
31 if (concreteType.is(TY_GENERIC))
486 SOFT_ERROR_ER(dataType, EXPECTED_NON_GENERIC_TYPE, "Struct instantiations may only take concrete template types")
487
1/2
✓ Branch 90 → 91 taken 31 times.
✗ Branch 90 → 223 not taken.
31 concreteTemplateTypes.push_back(concreteType);
488 }
489 }
490
491 // Get the struct instance
492
2/4
✓ Branch 96 → 97 taken 295 times.
✗ Branch 96 → 262 not taken.
✓ Branch 97 → 98 taken 295 times.
✗ Branch 97 → 262 not taken.
295 Struct *spiceStruct = node->instantiatedStructs.at(manIdx) = structType.getStructAndAdjustType(node, concreteTemplateTypes);
493
1/2
✗ Branch 98 → 99 not taken.
✓ Branch 98 → 110 taken 295 times.
295 if (!spiceStruct)
494 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT,
495 "Struct '" + Struct::getSignature(structName, concreteTemplateTypes) + "' could not be found")
496
497 // Struct instantiation for an inheriting struct is forbidden, because the vtable needs to be initialized and this is done in
498 // the ctor of the struct, which is never called in case of struct instantiation
499
2/2
✓ Branch 111 → 112 taken 1 time.
✓ Branch 111 → 122 taken 294 times.
295 if (!spiceStruct->interfaceTypes.empty())
500
4/8
✓ Branch 114 → 115 taken 1 time.
✗ Branch 114 → 237 not taken.
✓ Branch 115 → 116 taken 1 time.
✗ Branch 115 → 235 not taken.
✓ Branch 118 → 119 taken 1 time.
✗ Branch 118 → 241 not taken.
✓ Branch 119 → 120 taken 1 time.
✗ Branch 119 → 241 not taken.
3 SOFT_ERROR_ER(node, INVALID_STRUCT_INSTANTIATION, "Struct instantiations for inheriting structs are forbidden")
501
502 // Check if the number of fields matches
503
2/2
✓ Branch 122 → 123 taken 279 times.
✓ Branch 122 → 166 taken 15 times.
294 if (node->fieldLst) { // Check if any fields are passed. Empty braces are also allowed
504
2/2
✓ Branch 125 → 126 taken 1 time.
✓ Branch 125 → 136 taken 278 times.
279 if (spiceStruct->fieldTypes.size() != node->fieldLst->args.size())
505
4/8
✓ Branch 128 → 129 taken 1 time.
✗ Branch 128 → 244 not taken.
✓ Branch 129 → 130 taken 1 time.
✗ Branch 129 → 242 not taken.
✓ Branch 132 → 133 taken 1 time.
✗ Branch 132 → 248 not taken.
✓ Branch 133 → 134 taken 1 time.
✗ Branch 133 → 248 not taken.
3 SOFT_ERROR_ER(node->fieldLst, NUMBER_OF_FIELDS_NOT_MATCHING,
506 "You've passed too less/many field values. Pass either none or all of them")
507
508 // Check if the field types are matching
509 278 const size_t fieldCount = spiceStruct->fieldTypes.size();
510
1/2
✓ Branch 137 → 138 taken 278 times.
✗ Branch 137 → 262 not taken.
278 const size_t explicitFieldsStartIdx = spiceStruct->scope->getFieldCount() - fieldCount;
511
2/2
✓ Branch 165 → 139 taken 413 times.
✓ Branch 165 → 178 taken 277 times.
690 for (size_t i = 0; i < node->fieldLst->args.size(); i++) {
512 // Get actual type
513
1/2
✓ Branch 139 → 140 taken 413 times.
✗ Branch 139 → 253 not taken.
413 AssignExprNode *assignExpr = node->fieldLst->args.at(i);
514
2/4
✓ Branch 140 → 141 taken 413 times.
✗ Branch 140 → 251 not taken.
✓ Branch 141 → 142 taken 413 times.
✗ Branch 141 → 249 not taken.
413 auto fieldResult = std::any_cast<ExprResult>(visit(assignExpr));
515
2/8
✓ Branch 143 → 144 taken 413 times.
✗ Branch 143 → 253 not taken.
✗ Branch 144 → 145 not taken.
✓ Branch 144 → 149 taken 413 times.
✗ Branch 145 → 146 not taken.
✗ Branch 145 → 252 not taken.
✗ Branch 146 → 147 not taken.
✗ Branch 146 → 252 not taken.
413 HANDLE_UNRESOLVED_TYPE_ER(fieldResult.type)
516 // Get expected type
517
1/2
✗ Branch 149 → 150 not taken.
✓ Branch 149 → 151 taken 413 times.
413 SymbolTableEntry *expectedField = spiceStruct->scope->lookupField(explicitFieldsStartIdx + i);
518
1/2
✗ Branch 154 → 155 not taken.
✓ Branch 154 → 156 taken 413 times.
413 assert(expectedField != nullptr);
519
1/2
✓ Branch 156 → 157 taken 413 times.
✗ Branch 156 → 253 not taken.
413 const ExprResult expected = {expectedField->getQualType(), expectedField};
520
1/2
✓ Branch 157 → 158 taken 413 times.
✗ Branch 157 → 253 not taken.
413 const bool rhsIsImmediate = assignExpr->hasCompileTimeValue();
521
522 // Check if actual type matches expected type
523
2/2
✓ Branch 158 → 159 taken 412 times.
✓ Branch 158 → 253 taken 1 time.
413 (void)opRuleManager.getFieldAssignResultType(assignExpr, expected, fieldResult, rhsIsImmediate, true);
524
525 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it
526
4/4
✓ Branch 159 → 160 taken 111 times.
✓ Branch 159 → 163 taken 301 times.
✓ Branch 160 → 161 taken 3 times.
✓ Branch 160 → 163 taken 108 times.
412 if (fieldResult.entry != nullptr && fieldResult.entry->anonymous) {
527
1/2
✓ Branch 161 → 162 taken 3 times.
✗ Branch 161 → 253 not taken.
3 currentScope->symbolTable.deleteAnonymous(fieldResult.entry->name);
528 3 fieldResult.entry = nullptr;
529 }
530 }
531 } else {
532
2/4
✓ Branch 166 → 167 taken 15 times.
✗ Branch 166 → 262 not taken.
✗ Branch 167 → 168 not taken.
✓ Branch 167 → 178 taken 15 times.
60 if (std::ranges::any_of(spiceStruct->fieldTypes, [](const QualType &fieldType) { return fieldType.isRef(); }))
533 SOFT_ERROR_ER(node, REFERENCE_WITHOUT_INITIALIZER,
534 "The struct takes at least one reference field. You need to instantiate it with all fields.")
535 }
536
537 // Update type of struct entry
538
1/2
✓ Branch 178 → 179 taken 292 times.
✗ Branch 178 → 262 not taken.
292 structEntry->updateType(structType, true);
539
540 // Add anonymous symbol to keep track of dtor call, if non-trivially destructible
541 292 SymbolTableEntry *anonymousEntry = nullptr;
542
3/4
✓ Branch 179 → 180 taken 292 times.
✗ Branch 179 → 262 not taken.
✓ Branch 180 → 181 taken 29 times.
✓ Branch 180 → 183 taken 263 times.
292 if (!structType.isTriviallyDestructible(node))
543
1/2
✓ Branch 181 → 182 taken 29 times.
✗ Branch 181 → 262 not taken.
29 anonymousEntry = currentScope->symbolTable.insertAnonymous(structType, node);
544
545 // Remove public qualifier to not have public local variables
546 292 structType.getQualifiers().isPublic = false;
547
548
2/4
✓ Branch 184 → 185 taken 292 times.
✗ Branch 184 → 261 not taken.
✓ Branch 185 → 186 taken 292 times.
✗ Branch 185 → 261 not taken.
292 return ExprResult{node->setEvaluatedSymbolType(structType, manIdx), anonymousEntry};
549 295 }
550
551 16 std::any TypeChecker::visitLambdaFunc(LambdaFuncNode *node) {
552 // Check if all control paths in the lambda body return
553 16 bool returnsOnAllControlPaths = true;
554
3/4
✓ Branch 2 → 3 taken 16 times.
✗ Branch 2 → 186 not taken.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 14 taken 15 times.
16 if (!node->returnsOnAllControlPaths(&returnsOnAllControlPaths))
555
4/8
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 112 not taken.
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 110 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 116 not taken.
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 116 not taken.
3 SOFT_ERROR_ER(node, MISSING_RETURN_STMT, "Not all control paths of this lambda function have a return statement")
556
557 // Change to function scope
558
2/4
✓ Branch 14 → 15 taken 15 times.
✗ Branch 14 → 119 not taken.
✓ Branch 15 → 16 taken 15 times.
✗ Branch 15 → 117 not taken.
15 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
559
1/2
✓ Branch 17 → 18 taken 15 times.
✗ Branch 17 → 120 not taken.
15 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
560
561 // Visit return type
562
2/4
✓ Branch 18 → 19 taken 15 times.
✗ Branch 18 → 123 not taken.
✓ Branch 19 → 20 taken 15 times.
✗ Branch 19 → 121 not taken.
15 const auto returnType = std::any_cast<QualType>(visit(node->returnType));
563
2/8
✓ Branch 21 → 22 taken 15 times.
✗ Branch 21 → 184 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 27 taken 15 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 124 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 124 not taken.
15 HANDLE_UNRESOLVED_TYPE_ER(returnType)
564
3/4
✓ Branch 27 → 28 taken 15 times.
✗ Branch 27 → 184 not taken.
✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 39 taken 14 times.
15 if (returnType.is(TY_DYN))
565
4/8
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 127 not taken.
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 125 not taken.
✓ Branch 35 → 36 taken 1 time.
✗ Branch 35 → 131 not taken.
✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 131 not taken.
3 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed")
566
567 // Set the type of the result variable
568
1/2
✓ Branch 41 → 42 taken 14 times.
✗ Branch 41 → 134 not taken.
42 SymbolTableEntry *resultVarEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
569
1/2
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 14 times.
14 assert(resultVarEntry != nullptr);
570
1/2
✓ Branch 49 → 50 taken 14 times.
✗ Branch 49 → 184 not taken.
14 resultVarEntry->updateType(returnType, true);
571 14 resultVarEntry->used = true;
572
573 // Visit parameters
574 14 QualTypeList paramTypes;
575 14 ParamList paramList;
576
2/2
✓ Branch 50 → 51 taken 10 times.
✓ Branch 50 → 72 taken 4 times.
14 if (node->hasParams) {
577 // Visit param list to retrieve the param names
578
2/4
✓ Branch 51 → 52 taken 10 times.
✗ Branch 51 → 140 not taken.
✓ Branch 52 → 53 taken 10 times.
✗ Branch 52 → 138 not taken.
10 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
579
2/2
✓ Branch 69 → 56 taken 18 times.
✓ Branch 69 → 70 taken 10 times.
28 for (const auto &[name, qualType, isOptional] : namedParamList) {
580
1/2
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 65 taken 18 times.
18 if (isOptional)
581 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
582
583
1/2
✓ Branch 65 → 66 taken 18 times.
✗ Branch 65 → 148 not taken.
18 paramTypes.push_back(qualType);
584
1/2
✓ Branch 66 → 67 taken 18 times.
✗ Branch 66 → 147 not taken.
18 paramList.push_back({qualType, isOptional});
585 }
586 10 }
587
588 // Visit lambda body
589
2/2
✓ Branch 72 → 73 taken 13 times.
✓ Branch 72 → 152 taken 1 time.
14 visit(node->body);
590
591 // Leave function body scope
592
1/2
✓ Branch 74 → 75 taken 13 times.
✗ Branch 74 → 180 not taken.
13 scopeHandle.leaveScopeEarly();
593
594 // Prepare type of function
595
1/2
✓ Branch 75 → 76 taken 13 times.
✗ Branch 75 → 153 not taken.
13 const QualType functionType = QualType(TY_FUNCTION)
596
1/2
✓ Branch 76 → 77 taken 13 times.
✗ Branch 76 → 153 not taken.
13 .getWithFunctionParamAndReturnTypes(returnType, paramTypes)
597
1/2
✓ Branch 78 → 79 taken 13 times.
✗ Branch 78 → 153 not taken.
13 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
598
599 // Create function object
600
2/4
✓ Branch 79 → 80 taken 13 times.
✗ Branch 79 → 157 not taken.
✓ Branch 80 → 81 taken 13 times.
✗ Branch 80 → 155 not taken.
13 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
601
4/8
✓ Branch 83 → 84 taken 13 times.
✗ Branch 83 → 166 not taken.
✓ Branch 84 → 85 taken 13 times.
✗ Branch 84 → 163 not taken.
✓ Branch 85 → 86 taken 13 times.
✗ Branch 85 → 162 not taken.
✓ Branch 87 → 88 taken 13 times.
✗ Branch 87 → 158 not taken.
13 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node);
602
1/2
✓ Branch 93 → 94 taken 13 times.
✗ Branch 93 → 178 not taken.
13 node->manifestations.at(manIdx).bodyScope = bodyScope;
603
3/6
✓ Branch 94 → 95 taken 13 times.
✗ Branch 94 → 175 not taken.
✓ Branch 95 → 96 taken 13 times.
✗ Branch 95 → 173 not taken.
✓ Branch 96 → 97 taken 13 times.
✗ Branch 96 → 171 not taken.
13 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
604
605 // Check special requirements if this is an async lambda
606
1/2
✓ Branch 100 → 101 taken 13 times.
✗ Branch 100 → 178 not taken.
13 (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr);
607
608
2/4
✓ Branch 101 → 102 taken 13 times.
✗ Branch 101 → 177 not taken.
✓ Branch 102 → 103 taken 13 times.
✗ Branch 102 → 177 not taken.
13 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
609 17 }
610
611 32 std::any TypeChecker::visitLambdaProc(LambdaProcNode *node) {
612 // Mark unreachable statements
613 32 bool doSetPredecessorsUnreachable = true;
614
1/2
✓ Branch 2 → 3 taken 32 times.
✗ Branch 2 → 123 not taken.
32 node->returnsOnAllControlPaths(&doSetPredecessorsUnreachable);
615
616 // Change to function scope
617
2/4
✓ Branch 3 → 4 taken 32 times.
✗ Branch 3 → 71 not taken.
✓ Branch 4 → 5 taken 32 times.
✗ Branch 4 → 69 not taken.
32 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
618
1/2
✓ Branch 6 → 7 taken 32 times.
✗ Branch 6 → 72 not taken.
32 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
619
620 // Visit parameters
621 32 QualTypeList paramTypes;
622 32 ParamList paramList;
623
2/2
✓ Branch 7 → 8 taken 11 times.
✓ Branch 7 → 29 taken 21 times.
32 if (node->hasParams) {
624 // Visit param list to retrieve the param names
625
2/4
✓ Branch 8 → 9 taken 11 times.
✗ Branch 8 → 75 not taken.
✓ Branch 9 → 10 taken 11 times.
✗ Branch 9 → 73 not taken.
11 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
626
2/2
✓ Branch 26 → 13 taken 19 times.
✓ Branch 26 → 27 taken 11 times.
30 for (const auto &[_, qualType, isOptional] : namedParamList) {
627
2/2
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 22 taken 18 times.
19 if (isOptional)
628
2/4
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 78 not taken.
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 76 not taken.
2 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
629
630
1/2
✓ Branch 22 → 23 taken 19 times.
✗ Branch 22 → 83 not taken.
19 paramTypes.push_back(qualType);
631
1/2
✓ Branch 23 → 24 taken 19 times.
✗ Branch 23 → 82 not taken.
19 paramList.push_back({qualType, isOptional});
632 }
633 11 }
634
635 // Visit lambda body
636
1/2
✓ Branch 29 → 30 taken 32 times.
✗ Branch 29 → 87 not taken.
32 visit(node->body);
637
638 // Leave function body scope
639
1/2
✓ Branch 31 → 32 taken 32 times.
✗ Branch 31 → 117 not taken.
32 scopeHandle.leaveScopeEarly();
640
641 // Prepare type of function
642
1/2
✓ Branch 32 → 33 taken 32 times.
✗ Branch 32 → 89 not taken.
32 const QualType functionType = QualType(TY_PROCEDURE)
643
2/4
✓ Branch 33 → 34 taken 32 times.
✗ Branch 33 → 88 not taken.
✓ Branch 34 → 35 taken 32 times.
✗ Branch 34 → 88 not taken.
32 .getWithFunctionParamAndReturnTypes(QualType(TY_DYN), paramTypes)
644
1/2
✓ Branch 36 → 37 taken 32 times.
✗ Branch 36 → 88 not taken.
32 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
645
646 // Create function object
647
2/4
✓ Branch 37 → 38 taken 32 times.
✗ Branch 37 → 93 not taken.
✓ Branch 38 → 39 taken 32 times.
✗ Branch 38 → 91 not taken.
32 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
648
5/10
✓ Branch 41 → 42 taken 32 times.
✗ Branch 41 → 103 not taken.
✓ Branch 42 → 43 taken 32 times.
✗ Branch 42 → 100 not taken.
✓ Branch 43 → 44 taken 32 times.
✗ Branch 43 → 99 not taken.
✓ Branch 44 → 45 taken 32 times.
✗ Branch 44 → 98 not taken.
✓ Branch 46 → 47 taken 32 times.
✗ Branch 46 → 94 not taken.
32 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), QualType(TY_DYN), paramList, {}, node);
649
1/2
✓ Branch 52 → 53 taken 32 times.
✗ Branch 52 → 115 not taken.
32 node->manifestations.at(manIdx).bodyScope = bodyScope;
650
3/6
✓ Branch 53 → 54 taken 32 times.
✗ Branch 53 → 112 not taken.
✓ Branch 54 → 55 taken 32 times.
✗ Branch 54 → 110 not taken.
✓ Branch 55 → 56 taken 32 times.
✗ Branch 55 → 108 not taken.
32 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
651
652 // Check special requirements if this is an async lambda
653
1/2
✓ Branch 59 → 60 taken 32 times.
✗ Branch 59 → 115 not taken.
32 (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr);
654
655
2/4
✓ Branch 60 → 61 taken 32 times.
✗ Branch 60 → 114 not taken.
✓ Branch 61 → 62 taken 32 times.
✗ Branch 61 → 114 not taken.
64 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
656 32 }
657
658 1 std::any TypeChecker::visitLambdaExpr(LambdaExprNode *node) {
659 // Change to function scope
660
2/4
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 90 not taken.
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 88 not taken.
1 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
661
1/2
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 91 not taken.
1 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
662
663 // Visit parameters
664 1 QualTypeList paramTypes;
665 1 ParamList paramList;
666
1/2
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 28 not taken.
1 if (node->hasParams) {
667 // Visit param list to retrieve the param names
668
2/4
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 94 not taken.
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 92 not taken.
1 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
669
2/2
✓ Branch 25 → 12 taken 2 times.
✓ Branch 25 → 26 taken 1 time.
3 for (const NamedParam &param : namedParamList) {
670
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 21 taken 2 times.
2 if (param.isOptional)
671 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
672
673
1/2
✓ Branch 21 → 22 taken 2 times.
✗ Branch 21 → 102 not taken.
2 paramTypes.push_back(param.qualType);
674
1/2
✓ Branch 22 → 23 taken 2 times.
✗ Branch 22 → 101 not taken.
2 paramList.push_back({param.qualType, param.isOptional});
675 }
676 1 }
677
678 // Visit lambda expression
679
2/4
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 108 not taken.
✓ Branch 29 → 30 taken 1 time.
✗ Branch 29 → 106 not taken.
1 const QualType returnType = std::any_cast<ExprResult>(visit(node->lambdaExpr)).type;
680
2/8
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 145 not taken.
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 37 taken 1 time.
✗ Branch 33 → 34 not taken.
✗ Branch 33 → 110 not taken.
✗ Branch 34 → 35 not taken.
✗ Branch 34 → 110 not taken.
1 HANDLE_UNRESOLVED_TYPE_ER(returnType)
681
2/4
✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 145 not taken.
✗ Branch 38 → 39 not taken.
✓ Branch 38 → 49 taken 1 time.
1 if (returnType.is(TY_DYN))
682 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed")
683
684 // Leave function body scope
685
1/2
✓ Branch 49 → 50 taken 1 time.
✗ Branch 49 → 145 not taken.
1 scopeHandle.leaveScopeEarly();
686
687 // Prepare type of function
688
2/4
✓ Branch 50 → 51 taken 1 time.
✗ Branch 50 → 145 not taken.
✗ Branch 51 → 52 not taken.
✓ Branch 51 → 53 taken 1 time.
1 const SuperType superType = returnType.is(TY_DYN) ? TY_PROCEDURE : TY_FUNCTION;
689
1/2
✓ Branch 54 → 55 taken 1 time.
✗ Branch 54 → 118 not taken.
1 const QualType functionType = QualType(superType)
690
1/2
✓ Branch 55 → 56 taken 1 time.
✗ Branch 55 → 118 not taken.
1 .getWithFunctionParamAndReturnTypes(returnType, paramTypes)
691
1/2
✓ Branch 57 → 58 taken 1 time.
✗ Branch 57 → 118 not taken.
1 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
692
693 // Create function object
694
2/4
✓ Branch 58 → 59 taken 1 time.
✗ Branch 58 → 122 not taken.
✓ Branch 59 → 60 taken 1 time.
✗ Branch 59 → 120 not taken.
1 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
695
4/8
✓ Branch 62 → 63 taken 1 time.
✗ Branch 62 → 131 not taken.
✓ Branch 63 → 64 taken 1 time.
✗ Branch 63 → 128 not taken.
✓ Branch 64 → 65 taken 1 time.
✗ Branch 64 → 127 not taken.
✓ Branch 66 → 67 taken 1 time.
✗ Branch 66 → 123 not taken.
1 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node);
696
1/2
✓ Branch 72 → 73 taken 1 time.
✗ Branch 72 → 143 not taken.
1 node->manifestations.at(manIdx).bodyScope = bodyScope;
697
3/6
✓ Branch 73 → 74 taken 1 time.
✗ Branch 73 → 140 not taken.
✓ Branch 74 → 75 taken 1 time.
✗ Branch 74 → 138 not taken.
✓ Branch 75 → 76 taken 1 time.
✗ Branch 75 → 136 not taken.
1 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
698
699
2/4
✓ Branch 79 → 80 taken 1 time.
✗ Branch 79 → 142 not taken.
✓ Branch 80 → 81 taken 1 time.
✗ Branch 80 → 142 not taken.
1 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
700 1 }
701
702 } // namespace spice::compiler
703