GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 96.8% 421 / 3 / 438
Functions: 92.3% 12 / 0 / 13
Branches: 54.7% 704 / 8 / 1294

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 <model/GenericType.h>
10 #include <symboltablebuilder/Scope.h>
11 #include <symboltablebuilder/ScopeHandle.h>
12 #include <symboltablebuilder/SymbolTableBuilder.h>
13 #include <typechecker/BuiltinFunctions.h>
14 #include <typechecker/FunctionManager.h>
15 #include <typechecker/MacroDefs.h>
16 #include <typechecker/TypeMatcher.h>
17
18 namespace spice::compiler {
19
20 172203 std::any TypeChecker::visitValue(ValueNode *node) {
21 // Function call
22
2/2
✓ Branch 2 → 3 taken 148897 times.
✓ Branch 2 → 4 taken 23306 times.
172203 if (node->fctCall)
23 148897 return visit(node->fctCall);
24
25 // Array initialization
26
2/2
✓ Branch 4 → 5 taken 670 times.
✓ Branch 4 → 6 taken 22636 times.
23306 if (node->arrayInitialization)
27 670 return visit(node->arrayInitialization);
28
29 // Struct instantiation
30
2/2
✓ Branch 6 → 7 taken 3555 times.
✓ Branch 6 → 8 taken 19081 times.
22636 if (node->structInstantiation)
31 3555 return visit(node->structInstantiation);
32
33 // Lambda function
34
2/2
✓ Branch 8 → 9 taken 109 times.
✓ Branch 8 → 10 taken 18972 times.
19081 if (node->lambdaFunc)
35 109 return visit(node->lambdaFunc);
36
37 // Lambda procedure
38
2/2
✓ Branch 10 → 11 taken 92 times.
✓ Branch 10 → 12 taken 18880 times.
18972 if (node->lambdaProc)
39 92 return visit(node->lambdaProc);
40
41 // Lambda expression
42
2/2
✓ Branch 12 → 13 taken 2 times.
✓ Branch 12 → 14 taken 18878 times.
18880 if (node->lambdaExpr)
43 2 return visit(node->lambdaExpr);
44
45 // Typed nil
46
1/2
✓ Branch 14 → 15 taken 18878 times.
✗ Branch 14 → 41 not taken.
18878 if (node->isNil) {
47
2/4
✓ Branch 15 → 16 taken 18878 times.
✗ Branch 15 → 52 not taken.
✓ Branch 16 → 17 taken 18878 times.
✗ Branch 16 → 50 not taken.
18878 const auto nilType = std::any_cast<QualType>(visit(node->nilType));
48
2/8
✓ Branch 18 → 19 taken 18878 times.
✗ Branch 18 → 62 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 24 taken 18878 times.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 53 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 53 not taken.
18878 HANDLE_UNRESOLVED_TYPE_ER(nilType)
49
2/4
✓ Branch 24 → 25 taken 18878 times.
✗ Branch 24 → 62 not taken.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 36 taken 18878 times.
18878 if (nilType.is(TY_DYN))
50 SOFT_ERROR_ER(node->nilType, UNEXPECTED_DYN_TYPE, "Nil must have an explicit type")
51
2/4
✓ Branch 36 → 37 taken 18878 times.
✗ Branch 36 → 61 not taken.
✓ Branch 37 → 38 taken 18878 times.
✗ Branch 37 → 61 not taken.
37756 return ExprResult{node->setEvaluatedSymbolType(nilType, manIdx)};
52 }
53
54 throw CompilerError(UNHANDLED_BRANCH, "Value fall-through"); // GCOV_EXCL_LINE
55 }
56
57 164284 std::any TypeChecker::visitConstant(ConstantNode *node) {
58 SuperType superType;
59
7/8
✓ Branch 2 → 3 taken 3918 times.
✓ Branch 2 → 4 taken 22646 times.
✓ Branch 2 → 5 taken 2526 times.
✓ Branch 2 → 6 taken 67586 times.
✓ Branch 2 → 7 taken 13207 times.
✓ Branch 2 → 8 taken 35060 times.
✓ Branch 2 → 9 taken 19341 times.
✗ Branch 2 → 10 not taken.
164284 switch (node->type) {
60 3918 case ConstantNode::PrimitiveValueType::TYPE_DOUBLE:
61 3918 superType = TY_DOUBLE;
62 3918 break;
63 22646 case ConstantNode::PrimitiveValueType::TYPE_INT:
64 22646 superType = TY_INT;
65 22646 break;
66 2526 case ConstantNode::PrimitiveValueType::TYPE_SHORT:
67 2526 superType = TY_SHORT;
68 2526 break;
69 67586 case ConstantNode::PrimitiveValueType::TYPE_LONG:
70 67586 superType = TY_LONG;
71 67586 break;
72 13207 case ConstantNode::PrimitiveValueType::TYPE_CHAR:
73 13207 superType = TY_CHAR;
74 13207 break;
75 35060 case ConstantNode::PrimitiveValueType::TYPE_STRING:
76 35060 superType = TY_STRING;
77 35060 break;
78 19341 case ConstantNode::PrimitiveValueType::TYPE_BOOL:
79 19341 superType = TY_BOOL;
80 19341 break;
81 default: // GCOV_EXCL_LINE
82 throw CompilerError(UNHANDLED_BRANCH, "Constant fall-through"); // GCOV_EXCL_LINE
83 }
84
3/6
✓ Branch 18 → 19 taken 164284 times.
✗ Branch 18 → 33 not taken.
✓ Branch 19 → 20 taken 164284 times.
✗ Branch 19 → 33 not taken.
✓ Branch 20 → 21 taken 164284 times.
✗ Branch 20 → 33 not taken.
328568 return ExprResult{node->setEvaluatedSymbolType(QualType(superType), manIdx)};
85 }
86
87 148897 std::any TypeChecker::visitFctCall(FctCallNode *node) {
88
1/2
✓ Branch 2 → 3 taken 148897 times.
✗ Branch 2 → 561 not taken.
148897 FctCallNode::FctCallData &data = node->data.at(manIdx);
89 148897 auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope, compTimeVal, hasCompTimeVal] = data;
90
91 // Retrieve arg types
92 148897 args.clear();
93
2/2
✓ Branch 4 → 5 taken 107633 times.
✓ Branch 4 → 36 taken 41264 times.
148897 if (node->hasArgs) {
94
1/2
✓ Branch 6 → 7 taken 107633 times.
✗ Branch 6 → 561 not taken.
107633 args.reserve(node->argLst->args.size());
95
2/2
✓ Branch 34 → 9 taken 173885 times.
✓ Branch 34 → 35 taken 107599 times.
389117 for (ExprNode *arg : node->argLst->args) {
96 // Visit argument
97
3/4
✓ Branch 11 → 12 taken 173883 times.
✓ Branch 11 → 440 taken 2 times.
✓ Branch 12 → 13 taken 173883 times.
✗ Branch 12 → 438 not taken.
173885 const auto argResult = std::any_cast<ExprResult>(visit(arg));
98
5/8
✓ Branch 14 → 15 taken 173883 times.
✗ Branch 14 → 443 not taken.
✓ Branch 15 → 16 taken 32 times.
✓ Branch 15 → 20 taken 173851 times.
✓ Branch 16 → 17 taken 32 times.
✗ Branch 16 → 441 not taken.
✓ Branch 17 → 18 taken 32 times.
✗ Branch 17 → 441 not taken.
173915 HANDLE_UNRESOLVED_TYPE_ER(argResult.type)
99
2/4
✓ Branch 20 → 21 taken 173851 times.
✗ Branch 20 → 443 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 173851 times.
173851 assert(!argResult.type.hasAnyGenericParts());
100 // Save arg type to arg types list
101
1/2
✓ Branch 24 → 25 taken 173851 times.
✗ Branch 24 → 442 not taken.
173851 args.emplace_back(argResult.type, argResult.isTemporary());
102 }
103 }
104
105 // Retrieve template types
106 148863 templateTypes.clear();
107
2/2
✓ Branch 37 → 38 taken 12486 times.
✓ Branch 37 → 81 taken 136377 times.
148863 if (node->hasTemplateTypes) {
108
2/2
✓ Branch 79 → 40 taken 14975 times.
✓ Branch 79 → 80 taken 12486 times.
39947 for (DataTypeNode *templateTypeNode : node->templateTypeLst->dataTypes) {
109
2/4
✓ Branch 42 → 43 taken 14975 times.
✗ Branch 42 → 447 not taken.
✓ Branch 43 → 44 taken 14975 times.
✗ Branch 43 → 445 not taken.
14975 auto templateType = std::any_cast<QualType>(visit(templateTypeNode));
110
2/4
✓ Branch 45 → 46 taken 14975 times.
✗ Branch 45 → 456 not taken.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 14975 times.
14975 assert(!templateType.is(TY_INVALID));
111
112 // Abort if the type is unresolved
113
2/4
✓ Branch 48 → 49 taken 14975 times.
✗ Branch 48 → 456 not taken.
✗ Branch 49 → 50 not taken.
✓ Branch 49 → 56 taken 14975 times.
14975 if (templateType.is(TY_UNRESOLVED))
114 HANDLE_UNRESOLVED_TYPE_ER(templateType)
115
116 // Check if the given type is generic
117
2/4
✓ Branch 56 → 57 taken 14975 times.
✗ Branch 56 → 456 not taken.
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 68 taken 14975 times.
14975 if (templateType.is(TY_GENERIC))
118 SOFT_ERROR_ER(templateTypeNode, EXPECTED_NON_GENERIC_TYPE, "You must specify a concrete type here")
119
120
1/2
✓ Branch 68 → 69 taken 14975 times.
✗ Branch 68 → 456 not taken.
14975 templateTypes.push_back(templateType);
121 }
122 }
123
124 // Check if this is a builtin call
125
2/2
✓ Branch 88 → 82 taken 3213472 times.
✓ Branch 88 → 89 taken 132694 times.
3346166 for (const auto &[builtinFctName, _] : BUILTIN_FUNCTIONS)
126
2/2
✓ Branch 84 → 85 taken 16169 times.
✓ Branch 84 → 87 taken 3197303 times.
3213472 if (node->fqFunctionName == builtinFctName)
127
1/2
✓ Branch 85 → 86 taken 16169 times.
✗ Branch 85 → 561 not taken.
16169 return visitBuiltinCall(node);
128
129 // Retrieve entry of the first fragment
130 132694 const std::string &firstFrag = node->functionNameFragments.front();
131
1/2
✓ Branch 90 → 91 taken 132694 times.
✗ Branch 90 → 561 not taken.
132694 SymbolTableEntry *firstFragEntry = currentScope->lookup(firstFrag);
132
2/2
✓ Branch 93 → 94 taken 90206 times.
✓ Branch 93 → 131 taken 42488 times.
132694 if (firstFragEntry) {
133 // Check if we have seen a 'this.' prefix, because the generator needs that
134
6/8
✓ Branch 94 → 95 taken 2 times.
✓ Branch 94 → 98 taken 90204 times.
✓ Branch 95 → 96 taken 2 times.
✗ Branch 95 → 468 not taken.
✓ Branch 96 → 97 taken 2 times.
✗ Branch 96 → 98 not taken.
✓ Branch 99 → 100 taken 2 times.
✓ Branch 99 → 109 taken 90204 times.
90206 if (firstFragEntry->scope->type == ScopeType::STRUCT && firstFrag != THIS_VARIABLE_NAME)
135
5/10
✓ Branch 100 → 101 taken 2 times.
✗ Branch 100 → 462 not taken.
✓ Branch 101 → 102 taken 2 times.
✗ Branch 101 → 460 not taken.
✓ Branch 102 → 103 taken 2 times.
✗ Branch 102 → 458 not taken.
✓ Branch 105 → 106 taken 2 times.
✗ Branch 105 → 464 not taken.
✓ Branch 106 → 107 taken 2 times.
✗ Branch 106 → 464 not taken.
4 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE,
136 "The symbol '" + firstFrag + "' could not be found. Missing 'this.' prefix?")
137
138 90204 firstFragEntry->used = true;
139 // Decide of which type the function call is
140
2/4
✓ Branch 109 → 110 taken 90204 times.
✗ Branch 109 → 468 not taken.
✓ Branch 110 → 111 taken 90204 times.
✗ Branch 110 → 468 not taken.
90204 const QualType &baseType = firstFragEntry->getQualType().getBase();
141
5/8
✓ Branch 111 → 112 taken 90204 times.
✗ Branch 111 → 468 not taken.
✓ Branch 112 → 113 taken 8 times.
✓ Branch 112 → 117 taken 90196 times.
✓ Branch 113 → 114 taken 8 times.
✗ Branch 113 → 465 not taken.
✓ Branch 114 → 115 taken 8 times.
✗ Branch 114 → 465 not taken.
90212 HANDLE_UNRESOLVED_TYPE_ER(baseType)
142
3/4
✓ Branch 117 → 118 taken 90196 times.
✗ Branch 117 → 466 not taken.
✓ Branch 118 → 119 taken 70541 times.
✓ Branch 118 → 122 taken 19655 times.
90196 if (baseType.isOneOf({TY_STRUCT, TY_INTERFACE})) {
143
2/2
✓ Branch 119 → 120 taken 7638 times.
✓ Branch 119 → 121 taken 62903 times.
70541 if (firstFragEntry->scope->type == ScopeType::GLOBAL)
144 7638 callType = FctCallNode::FctCallType::TYPE_CTOR;
145 else
146 62903 callType = FctCallNode::FctCallType::TYPE_METHOD;
147
7/8
✓ Branch 122 → 123 taken 19655 times.
✗ Branch 122 → 467 not taken.
✓ Branch 123 → 124 taken 19275 times.
✓ Branch 123 → 126 taken 380 times.
✓ Branch 124 → 125 taken 235 times.
✓ Branch 124 → 126 taken 19040 times.
✓ Branch 127 → 128 taken 235 times.
✓ Branch 127 → 129 taken 19420 times.
19655 } else if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && firstFragEntry->scope->type != ScopeType::GLOBAL) {
148 235 callType = FctCallNode::FctCallType::TYPE_FCT_PTR;
149 }
150 }
151
152 // Get struct name. Retrieve it from alias if required
153
1/2
✓ Branch 131 → 132 taken 132684 times.
✗ Branch 131 → 561 not taken.
132684 const auto &[structEntry, isAlias] = rootScope->symbolTable.lookupWithAliasResolution(node->fqFunctionName);
154
4/6
✓ Branch 134 → 135 taken 50 times.
✓ Branch 134 → 138 taken 132634 times.
✓ Branch 135 → 136 taken 50 times.
✗ Branch 135 → 561 not taken.
✓ Branch 136 → 137 taken 50 times.
✗ Branch 136 → 561 not taken.
132684 const std::string &fqFunctionName = isAlias ? structEntry->getQualType().getSubType() : node->fqFunctionName;
155
156 // Get the concrete template types
157
2/2
✓ Branch 139 → 140 taken 50 times.
✓ Branch 139 → 159 taken 132634 times.
132684 if (isAlias) {
158 // Retrieve concrete template types from type alias
159
3/6
✓ Branch 140 → 141 taken 50 times.
✗ Branch 140 → 561 not taken.
✓ Branch 141 → 142 taken 50 times.
✗ Branch 141 → 561 not taken.
✓ Branch 142 → 143 taken 50 times.
✗ Branch 142 → 561 not taken.
50 templateTypes = structEntry->getQualType().getTemplateTypes();
160 // Check if the aliased type specified template types and the struct instantiation does
161
3/6
✓ Branch 144 → 145 taken 50 times.
✗ Branch 144 → 147 not taken.
✗ Branch 145 → 146 not taken.
✓ Branch 145 → 147 taken 50 times.
✗ Branch 148 → 149 not taken.
✓ Branch 148 → 159 taken 50 times.
50 if (!templateTypes.empty() && node->hasTemplateTypes)
162 SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list")
163 }
164
165 // Check if this is a method call or a normal function call
166
2/2
✓ Branch 160 → 161 taken 62903 times.
✓ Branch 160 → 175 taken 69781 times.
132684 if (data.isMethodCall()) {
167 // This is a method call
168
1/2
✓ Branch 161 → 162 taken 62903 times.
✗ Branch 161 → 561 not taken.
62903 thisType = firstFragEntry->getQualType();
169
2/4
✓ Branch 162 → 163 taken 62903 times.
✗ Branch 162 → 476 not taken.
✓ Branch 163 → 164 taken 62903 times.
✗ Branch 163 → 476 not taken.
62903 Scope *structBodyScope = thisType.getBase().getBodyScope();
170
1/2
✗ Branch 164 → 165 not taken.
✓ Branch 164 → 166 taken 62903 times.
62903 assert(structBodyScope != nullptr);
171
3/4
✓ Branch 166 → 167 taken 62903 times.
✗ Branch 166 → 561 not taken.
✓ Branch 167 → 168 taken 4 times.
✓ Branch 167 → 173 taken 62899 times.
62903 if (!visitMethodCall(node, structBodyScope)) // Check if soft errors occurred
172
3/6
✓ Branch 168 → 169 taken 4 times.
✗ Branch 168 → 477 not taken.
✓ Branch 169 → 170 taken 4 times.
✗ Branch 169 → 477 not taken.
✓ Branch 170 → 171 taken 4 times.
✗ Branch 170 → 477 not taken.
8 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
173
1/2
✗ Branch 173 → 174 not taken.
✓ Branch 173 → 211 taken 62899 times.
62899 assert(calleeParentScope != nullptr);
174
2/2
✓ Branch 176 → 177 taken 235 times.
✓ Branch 176 → 190 taken 69546 times.
69781 } else if (data.isFctPtrCall()) {
175 // This is a function pointer call
176
2/4
✓ Branch 177 → 178 taken 235 times.
✗ Branch 177 → 482 not taken.
✓ Branch 178 → 179 taken 235 times.
✗ Branch 178 → 482 not taken.
235 const QualType &functionType = firstFragEntry->getQualType().getBase();
177
2/4
✓ Branch 179 → 180 taken 235 times.
✗ Branch 179 → 479 not taken.
✗ Branch 180 → 181 not taken.
✓ Branch 180 → 182 taken 235 times.
235 assert(functionType.isOneOf({TY_FUNCTION, TY_PROCEDURE}));
178
2/4
✓ Branch 182 → 183 taken 235 times.
✗ Branch 182 → 482 not taken.
✗ Branch 183 → 184 not taken.
✓ Branch 183 → 189 taken 235 times.
235 if (!visitFctPtrCall(node, functionType)) // Check if soft errors occurred
179 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
180 } else {
181 // This is an ordinary function call
182
3/4
✓ Branch 191 → 192 taken 7712 times.
✓ Branch 191 → 195 taken 61834 times.
✗ Branch 193 → 194 not taken.
✓ Branch 193 → 195 taken 7712 times.
69546 assert(data.isOrdinaryCall() || data.isCtorCall());
183
5/6
✓ Branch 195 → 196 taken 69546 times.
✗ Branch 195 → 485 not taken.
✓ Branch 196 → 197 taken 69544 times.
✓ Branch 196 → 483 taken 2 times.
✓ Branch 198 → 199 taken 8 times.
✓ Branch 198 → 204 taken 69536 times.
69548 if (!visitOrdinaryFctCall(node, fqFunctionName)) // Check if soft errors occurred
184
3/6
✓ Branch 199 → 200 taken 8 times.
✗ Branch 199 → 486 not taken.
✓ Branch 200 → 201 taken 8 times.
✗ Branch 200 → 486 not taken.
✓ Branch 201 → 202 taken 8 times.
✗ Branch 201 → 486 not taken.
16 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
185
1/2
✗ Branch 204 → 205 not taken.
✓ Branch 204 → 206 taken 69536 times.
69536 assert(calleeParentScope != nullptr);
186
187 // If the call is no ordinary call, it must be a constructor, which takes a struct as this type.
188
4/6
✓ Branch 207 → 208 taken 19809 times.
✓ Branch 207 → 211 taken 49727 times.
✓ Branch 208 → 209 taken 19809 times.
✗ Branch 208 → 561 not taken.
✗ Branch 209 → 210 not taken.
✓ Branch 209 → 211 taken 19809 times.
69536 assert(data.isOrdinaryCall() || data.thisType.is(TY_STRUCT));
189 }
190
191
2/2
✓ Branch 212 → 213 taken 132435 times.
✓ Branch 212 → 296 taken 235 times.
132670 if (!data.isFctPtrCall()) {
192 // Check if we were able to find a function
193
2/2
✓ Branch 213 → 214 taken 24 times.
✓ Branch 213 → 251 taken 132411 times.
132435 if (!callee) {
194 // Build error message
195
6/10
✓ Branch 215 → 216 taken 4 times.
✓ Branch 215 → 219 taken 20 times.
✓ Branch 218 → 221 taken 4 times.
✗ Branch 218 → 488 not taken.
✓ Branch 220 → 221 taken 20 times.
✗ Branch 220 → 488 not taken.
✓ Branch 221 → 222 taken 4 times.
✓ Branch 221 → 224 taken 20 times.
✗ Branch 488 → 489 not taken.
✗ Branch 488 → 491 not taken.
28 const std::string functionName = data.isCtorCall() ? CTOR_FUNCTION_NAME : node->functionNameFragments.back();
196 24 ParamList errArgTypes;
197
1/2
✓ Branch 225 → 226 taken 24 times.
✗ Branch 225 → 508 not taken.
24 errArgTypes.reserve(args.size());
198
5/8
✓ Branch 226 → 227 taken 24 times.
✗ Branch 226 → 494 not taken.
✓ Branch 227 → 228 taken 24 times.
✗ Branch 227 → 494 not taken.
✓ Branch 228 → 229 taken 24 times.
✗ Branch 228 → 494 not taken.
✓ Branch 234 → 230 taken 14 times.
✓ Branch 234 → 235 taken 24 times.
38 for (const auto &type : args | std::views::keys)
199
1/2
✓ Branch 231 → 232 taken 14 times.
✗ Branch 231 → 493 not taken.
14 errArgTypes.push_back({type, false});
200
2/4
✓ Branch 236 → 237 taken 24 times.
✗ Branch 236 → 495 not taken.
✓ Branch 237 → 238 taken 24 times.
✗ Branch 237 → 495 not taken.
24 const std::string signature = Function::getSignature(functionName, thisType, QualType(TY_DYN), errArgTypes, {}, false);
201 // Throw error
202
5/10
✓ Branch 239 → 240 taken 24 times.
✗ Branch 239 → 503 not taken.
✓ Branch 240 → 241 taken 24 times.
✗ Branch 240 → 501 not taken.
✓ Branch 241 → 242 taken 24 times.
✗ Branch 241 → 499 not taken.
✓ Branch 244 → 245 taken 24 times.
✗ Branch 244 → 505 not taken.
✓ Branch 245 → 246 taken 24 times.
✗ Branch 245 → 505 not taken.
24 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_FUNCTION, "Function/procedure '" + signature + "' could not be found")
203 24 }
204
205 // Check if we need to request a re-visit, because the function body was not type-checked yet
206
1/2
✓ Branch 251 → 252 taken 132411 times.
✗ Branch 251 → 561 not taken.
132411 requestRevisitIfRequired(callee);
207
208 // Get function entry from function object
209 132411 SymbolTableEntry *functionEntry = callee->entry;
210
211 // Check if the called function has sufficient visibility
212
1/2
✓ Branch 252 → 253 taken 132411 times.
✗ Branch 252 → 561 not taken.
132411 isImported = calleeParentScope->isImportedBy(rootScope);
213
8/10
✓ Branch 253 → 254 taken 54074 times.
✓ Branch 253 → 258 taken 78337 times.
✓ Branch 254 → 255 taken 54074 times.
✗ Branch 254 → 561 not taken.
✓ Branch 255 → 256 taken 54074 times.
✗ Branch 255 → 561 not taken.
✓ Branch 256 → 257 taken 4 times.
✓ Branch 256 → 258 taken 54070 times.
✓ Branch 259 → 260 taken 4 times.
✓ Branch 259 → 284 taken 132407 times.
132411 if (isImported && !functionEntry->getQualType().isPublic()) {
214
1/2
✓ Branch 260 → 261 taken 4 times.
✗ Branch 260 → 529 not taken.
4 const QualType functionEntryType = functionEntry->getQualType();
215
1/2
✓ Branch 261 → 262 taken 4 times.
✗ Branch 261 → 529 not taken.
4 const std::string signature = callee->getSignature();
216
2/4
✓ Branch 262 → 263 taken 4 times.
✗ Branch 262 → 527 not taken.
✓ Branch 263 → 264 taken 4 times.
✗ Branch 263 → 273 not taken.
4 if (functionEntryType.is(TY_FUNCTION))
217
5/10
✓ Branch 264 → 265 taken 4 times.
✗ Branch 264 → 517 not taken.
✓ Branch 265 → 266 taken 4 times.
✗ Branch 265 → 515 not taken.
✓ Branch 266 → 267 taken 4 times.
✗ Branch 266 → 513 not taken.
✓ Branch 269 → 270 taken 4 times.
✗ Branch 269 → 519 not taken.
✓ Branch 270 → 271 taken 4 times.
✗ Branch 270 → 519 not taken.
8 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Function '" + signature + "' has insufficient visibility")
218 else
219 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Procedure '" + signature + "' has insufficient visibility")
220 4 }
221
222 // Mark direct calls to err<T>(...) as an error-return-trace origin site when tracing is enabled for this file.
223 // err<T>'s own internal delegation to Result<T>'s error ctor is a distinct ctor call and is never matched here,
224 // so this only ever fires for the user's own call site, not for that nested one.
225
8/10
✓ Branch 284 → 285 taken 68 times.
✓ Branch 284 → 293 taken 132339 times.
✓ Branch 285 → 286 taken 68 times.
✗ Branch 285 → 293 not taken.
✓ Branch 286 → 287 taken 68 times.
✗ Branch 286 → 561 not taken.
✓ Branch 289 → 290 taken 38 times.
✓ Branch 289 → 293 taken 30 times.
✓ Branch 294 → 295 taken 10 times.
✓ Branch 294 → 296 taken 132397 times.
132513 if (sourceFile->errorReturnTracing && callee->bodyScope != nullptr && callee->bodyScope->sourceFile->isResultRT() &&
226
3/4
✓ Branch 290 → 291 taken 38 times.
✗ Branch 290 → 561 not taken.
✓ Branch 291 → 292 taken 10 times.
✓ Branch 291 → 293 taken 28 times.
38 callee->name == "err")
227 10 node->isErrorTraceOrigin = true;
228 }
229
230 // Generate arg infos
231
2/2
✓ Branch 296 → 297 taken 97234 times.
✓ Branch 296 → 339 taken 35408 times.
132642 if (node->hasArgs) {
232 97234 QualTypeList paramTypes;
233
2/2
✓ Branch 298 → 299 taken 183 times.
✓ Branch 298 → 305 taken 97051 times.
97234 if (data.isFctPtrCall()) {
234
2/4
✓ Branch 299 → 300 taken 183 times.
✗ Branch 299 → 531 not taken.
✓ Branch 300 → 301 taken 183 times.
✗ Branch 300 → 531 not taken.
183 const QualType &functionType = firstFragEntry->getQualType().getBase();
235
1/2
✓ Branch 301 → 302 taken 183 times.
✗ Branch 301 → 530 not taken.
183 paramTypes = functionType.getFunctionParamTypes();
236 } else {
237
1/2
✗ Branch 305 → 306 not taken.
✓ Branch 305 → 307 taken 97051 times.
97051 assert(callee != nullptr);
238
1/2
✓ Branch 307 → 308 taken 97051 times.
✗ Branch 307 → 532 not taken.
97051 paramTypes = callee->getParamTypes();
239 }
240
241 97234 node->argLst->argInfos.clear();
242
2/2
✓ Branch 332 → 313 taken 159885 times.
✓ Branch 332 → 333 taken 97234 times.
257119 for (size_t argIdx = 0; argIdx < args.size(); argIdx++) {
243
1/2
✓ Branch 313 → 314 taken 159885 times.
✗ Branch 313 → 534 not taken.
159885 const QualType &expectedType = paramTypes.at(argIdx);
244
1/2
✓ Branch 314 → 315 taken 159885 times.
✗ Branch 314 → 534 not taken.
159885 const auto &[actualType, _] = args.at(argIdx);
245
246 159885 Function *copyCtor = nullptr;
247
11/14
✓ Branch 317 → 318 taken 159885 times.
✗ Branch 317 → 534 not taken.
✓ Branch 318 → 319 taken 2502 times.
✓ Branch 318 → 324 taken 157383 times.
✓ Branch 319 → 320 taken 2502 times.
✗ Branch 319 → 534 not taken.
✓ Branch 320 → 321 taken 2494 times.
✓ Branch 320 → 324 taken 8 times.
✓ Branch 321 → 322 taken 2494 times.
✗ Branch 321 → 534 not taken.
✓ Branch 322 → 323 taken 32 times.
✓ Branch 322 → 324 taken 2462 times.
✓ Branch 325 → 326 taken 32 times.
✓ Branch 325 → 329 taken 159853 times.
159885 if (expectedType.is(TY_STRUCT) && actualType.is(TY_STRUCT) && !actualType.isTriviallyCopyable(node)) {
248
1/2
✓ Branch 326 → 327 taken 32 times.
✗ Branch 326 → 534 not taken.
32 copyCtor = matchCopyCtor(actualType, node);
249 // Insert anonymous symbol to track the dtor call of the copy
250
1/2
✓ Branch 327 → 328 taken 32 times.
✗ Branch 327 → 534 not taken.
32 ExprNode *argNode = node->argLst->args.at(argIdx);
251
1/2
✓ Branch 328 → 329 taken 32 times.
✗ Branch 328 → 534 not taken.
32 currentScope->symbolTable.insertAnonymous(actualType, argNode, SIZE_MAX);
252 }
253
254
1/2
✓ Branch 329 → 330 taken 159885 times.
✗ Branch 329 → 533 not taken.
159885 node->argLst->argInfos.push_back(ArgLstNode::ArgInfo{copyCtor});
255 }
256
1/2
✗ Branch 335 → 336 not taken.
✓ Branch 335 → 337 taken 97234 times.
97234 assert(node->argLst->argInfos.size() == node->argLst->args.size());
257 97234 }
258
259 // Retrieve return type
260
6/10
✓ Branch 340 → 341 taken 235 times.
✓ Branch 340 → 345 taken 132407 times.
✓ Branch 341 → 342 taken 235 times.
✗ Branch 341 → 537 not taken.
✓ Branch 342 → 343 taken 235 times.
✗ Branch 342 → 537 not taken.
✓ Branch 343 → 344 taken 235 times.
✗ Branch 343 → 537 not taken.
✓ Branch 345 → 346 taken 132407 times.
✗ Branch 345 → 537 not taken.
265049 const bool isFct = data.isFctPtrCall() ? firstFragEntry->getQualType().getBase().is(TY_FUNCTION) : callee->isFunction();
261 132642 QualType returnType;
262
2/2
✓ Branch 350 → 351 taken 235 times.
✓ Branch 350 → 358 taken 132407 times.
132642 if (data.isFctPtrCall()) {
263
6/10
✓ Branch 351 → 352 taken 79 times.
✓ Branch 351 → 356 taken 156 times.
✓ Branch 352 → 353 taken 79 times.
✗ Branch 352 → 538 not taken.
✓ Branch 353 → 354 taken 79 times.
✗ Branch 353 → 538 not taken.
✓ Branch 354 → 355 taken 79 times.
✗ Branch 354 → 538 not taken.
✓ Branch 356 → 357 taken 156 times.
✗ Branch 356 → 538 not taken.
235 returnType = isFct ? firstFragEntry->getQualType().getBase().getFunctionReturnType() : QualType(TY_BOOL);
264
2/2
✓ Branch 359 → 360 taken 19805 times.
✓ Branch 359 → 361 taken 112602 times.
132407 } else if (data.isCtorCall()) {
265 19805 returnType = thisType;
266
3/4
✓ Branch 361 → 362 taken 112602 times.
✗ Branch 361 → 561 not taken.
✓ Branch 364 → 365 taken 30815 times.
✓ Branch 364 → 367 taken 81787 times.
225204 } else if (callee->isProcedure()) {
267
1/2
✓ Branch 365 → 366 taken 30815 times.
✗ Branch 365 → 540 not taken.
30815 returnType = QualType(TY_DYN);
268 } else {
269 81787 returnType = callee->returnType;
270 }
271
272
1/2
✓ Branch 368 → 369 taken 132642 times.
✗ Branch 368 → 561 not taken.
132642 const QualType returnBaseType = returnType.getBase();
273
274 // Make sure this source file knows about the return type
275
3/4
✓ Branch 369 → 370 taken 132642 times.
✗ Branch 369 → 561 not taken.
✓ Branch 370 → 371 taken 40352 times.
✓ Branch 370 → 374 taken 92290 times.
132642 if (returnBaseType.is(TY_STRUCT))
276
2/4
✓ Branch 371 → 372 taken 40352 times.
✗ Branch 371 → 541 not taken.
✓ Branch 372 → 373 taken 40352 times.
✗ Branch 372 → 541 not taken.
40352 returnType = mapImportedScopeTypeToLocalType(returnBaseType.getBodyScope(), returnType);
277
278 // Add anonymous symbol to keep track of dtor call, if non-trivially destructible
279 132642 SymbolTableEntry *anonymousSymbol = nullptr;
280
8/10
✓ Branch 374 → 375 taken 132642 times.
✗ Branch 374 → 561 not taken.
✓ Branch 375 → 376 taken 31731 times.
✓ Branch 375 → 379 taken 100911 times.
✓ Branch 376 → 377 taken 31731 times.
✗ Branch 376 → 561 not taken.
✓ Branch 377 → 378 taken 19851 times.
✓ Branch 377 → 379 taken 11880 times.
✓ Branch 380 → 381 taken 19851 times.
✓ Branch 380 → 383 taken 112791 times.
132642 if (returnType.is(TY_STRUCT) && !returnType.isTriviallyDestructible(node))
281
1/2
✓ Branch 381 → 382 taken 19851 times.
✗ Branch 381 → 561 not taken.
19851 anonymousSymbol = currentScope->symbolTable.insertAnonymous(returnType, node);
282
283 // Remove public qualifier to not have public local variables
284 132642 returnType.getQualifiers().isPublic = false;
285
286 // Check if the return value gets discarded
287
7/8
✓ Branch 384 → 385 taken 81866 times.
✓ Branch 384 → 388 taken 50776 times.
✓ Branch 385 → 386 taken 81866 times.
✗ Branch 385 → 561 not taken.
✓ Branch 386 → 387 taken 9178 times.
✓ Branch 386 → 388 taken 72688 times.
✓ Branch 389 → 390 taken 9178 times.
✓ Branch 389 → 432 taken 123464 times.
132642 if (isFct && !node->hasReturnValueReceiver()) {
288 // Discarding a Result<T> is always a hard error when explicit error handling is enabled for this module,
289 // regardless of ignoreUnusedReturnValue (which only ever weakens the generic warning below).
290
8/10
✓ Branch 390 → 391 taken 6 times.
✓ Branch 390 → 395 taken 9172 times.
✓ Branch 391 → 392 taken 6 times.
✗ Branch 391 → 542 not taken.
✓ Branch 392 → 393 taken 6 times.
✗ Branch 392 → 542 not taken.
✓ Branch 393 → 394 taken 4 times.
✓ Branch 393 → 395 taken 2 times.
✓ Branch 396 → 397 taken 4 times.
✓ Branch 396 → 407 taken 9174 times.
9178 if (sourceFile->explicitErrorHandling && returnType.removeReferenceWrapper().isResultObj())
291
4/8
✓ Branch 399 → 400 taken 4 times.
✗ Branch 399 → 545 not taken.
✓ Branch 400 → 401 taken 4 times.
✗ Branch 400 → 543 not taken.
✓ Branch 403 → 404 taken 4 times.
✗ Branch 403 → 549 not taken.
✓ Branch 404 → 405 taken 4 times.
✗ Branch 404 → 549 not taken.
16 SOFT_ERROR_ER(node, DISCARDED_RESULT_VALUE,
292 "A Result<T> returned from a call must be handled: bind it to a variable, propagate it with the "
293 "'!' operator, handle it with '.unwrapOr(...)'/'.unwrapOrElse(...)', or explicitly discard it by "
294 "binding it to a variable with a name starting with '_'")
295
296 // Check if we want to ignore the discarded return value
297 9174 bool ignoreUnusedReturnValue = false;
298
2/2
✓ Branch 408 → 409 taken 9166 times.
✓ Branch 408 → 429 taken 8 times.
9174 if (!data.isFctPtrCall()) {
299
1/2
✗ Branch 409 → 410 not taken.
✓ Branch 409 → 411 taken 9166 times.
9166 assert(callee != nullptr);
300
1/2
✓ Branch 411 → 412 taken 9166 times.
✗ Branch 411 → 413 not taken.
9166 auto fctDef = dynamic_cast<const FctDefNode *>(callee->declNode);
301
12/18
✓ Branch 414 → 415 taken 2503 times.
✓ Branch 414 → 422 taken 6663 times.
✓ Branch 415 → 416 taken 554 times.
✓ Branch 415 → 422 taken 1949 times.
✓ Branch 418 → 419 taken 554 times.
✗ Branch 418 → 550 not taken.
✓ Branch 419 → 420 taken 554 times.
✗ Branch 419 → 550 not taken.
✓ Branch 420 → 421 taken 516 times.
✓ Branch 420 → 422 taken 38 times.
✓ Branch 423 → 424 taken 554 times.
✓ Branch 423 → 425 taken 8612 times.
✓ Branch 425 → 426 taken 554 times.
✓ Branch 425 → 428 taken 8612 times.
✗ Branch 550 → 551 not taken.
✗ Branch 550 → 552 not taken.
✗ Branch 554 → 555 not taken.
✗ Branch 554 → 557 not taken.
10274 ignoreUnusedReturnValue = fctDef && fctDef->attrs && fctDef->attrs->attrLst->hasAttr(ATTR_IGNORE_UNUSED_RETURN_VALUE);
302 }
303
304
2/2
✓ Branch 429 → 430 taken 8658 times.
✓ Branch 429 → 432 taken 516 times.
9174 if (!ignoreUnusedReturnValue)
305
1/2
✓ Branch 430 → 431 taken 8658 times.
✗ Branch 430 → 559 not taken.
8658 warnings.emplace_back(node->codeLoc, UNUSED_RETURN_VALUE, "The return value of the function call is unused");
306 }
307
308
2/4
✓ Branch 432 → 433 taken 132638 times.
✗ Branch 432 → 560 not taken.
✓ Branch 433 → 434 taken 132638 times.
✗ Branch 433 → 560 not taken.
265276 return ExprResult{node->setEvaluatedSymbolType(returnType, manIdx), anonymousSymbol};
309 }
310
311 69546 bool TypeChecker::visitOrdinaryFctCall(FctCallNode *node, std::string fqFunctionName) const {
312
1/2
✓ Branch 2 → 3 taken 69546 times.
✗ Branch 2 → 112 not taken.
69546 FctCallNode::FctCallData &data = node->data.at(manIdx);
313 69546 auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope, compTimeVal, hasCompTimeVal] = data;
314
315 // Check if this is a well-known ctor/fct call
316
2/2
✓ Branch 4 → 5 taken 69226 times.
✓ Branch 4 → 7 taken 320 times.
69546 if (node->functionNameFragments.size() == 1) {
317
1/2
✓ Branch 5 → 6 taken 69226 times.
✗ Branch 5 → 112 not taken.
69226 ensureLoadedRuntimeForTypeName(fqFunctionName);
318
1/2
✓ Branch 6 → 7 taken 69226 times.
✗ Branch 6 → 112 not taken.
69226 ensureLoadedRuntimeForFunctionName(fqFunctionName);
319 }
320
321 // Check if the type is generic (possible in case of ctor call)
322
1/2
✓ Branch 7 → 8 taken 69546 times.
✗ Branch 7 → 112 not taken.
69546 const QualType *genericType = rootScope->lookupGenericTypeStrict(fqFunctionName);
323
6/8
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 12 taken 69544 times.
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 112 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 12 not taken.
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 19 taken 69544 times.
69546 if (genericType && typeMapping.contains(fqFunctionName)) {
324
1/2
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 112 not taken.
2 const QualType &replacementType = typeMapping.at(fqFunctionName);
325
2/4
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 112 not taken.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 19 not taken.
2 if (replacementType.is(TY_STRUCT))
326
2/4
✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 112 not taken.
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 112 not taken.
2 fqFunctionName = replacementType.getSubType();
327 }
328
329 // Check if the exported name registry contains that function name
330
1/2
✓ Branch 19 → 20 taken 69546 times.
✗ Branch 19 → 112 not taken.
69546 const NameRegistryEntry *functionRegistryEntry = sourceFile->getNameRegistryEntry(fqFunctionName);
331
2/2
✓ Branch 20 → 21 taken 6 times.
✓ Branch 20 → 28 taken 69540 times.
69546 if (!functionRegistryEntry) {
332
2/4
✓ Branch 22 → 23 taken 6 times.
✗ Branch 22 → 92 not taken.
✓ Branch 23 → 24 taken 6 times.
✗ Branch 23 → 90 not taken.
6 const std::string msg = "Function/procedure/struct '" + node->functionNameFragments.back() + "' could not be found";
333
1/2
✓ Branch 25 → 26 taken 6 times.
✗ Branch 25 → 93 not taken.
6 SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, msg)
334 6 }
335 69540 const SymbolTableEntry *functionEntry = functionRegistryEntry->targetEntry;
336 69540 calleeParentScope = functionRegistryEntry->targetScope;
337
338 // Check if the target symbol is a struct -> this must be a constructor call
339
1/2
✓ Branch 29 → 30 taken 69540 times.
✗ Branch 29 → 112 not taken.
69540 std::string functionName = node->functionNameFragments.back();
340
7/10
✓ Branch 30 → 31 taken 69540 times.
✗ Branch 30 → 35 not taken.
✓ Branch 31 → 32 taken 69540 times.
✗ Branch 31 → 110 not taken.
✓ Branch 32 → 33 taken 69540 times.
✗ Branch 32 → 110 not taken.
✓ Branch 33 → 34 taken 19811 times.
✓ Branch 33 → 35 taken 49729 times.
✓ Branch 36 → 37 taken 19811 times.
✓ Branch 36 → 52 taken 49729 times.
69540 if (functionEntry != nullptr && functionEntry->getQualType().is(TY_STRUCT)) {
341 19811 callType = FctCallNode::FctCallType::TYPE_CTOR;
342
1/2
✓ Branch 37 → 38 taken 19811 times.
✗ Branch 37 → 110 not taken.
19811 functionName = CTOR_FUNCTION_NAME;
343
344 19811 const NameRegistryEntry *structRegistryEntry = functionRegistryEntry;
345 19811 const SymbolTableEntry *structEntry = functionEntry;
346
347 // Substantiate potentially generic this struct
348
2/4
✓ Branch 38 → 39 taken 19811 times.
✗ Branch 38 → 110 not taken.
✓ Branch 39 → 40 taken 19811 times.
✗ Branch 39 → 110 not taken.
19811 const Struct *thisStruct = structEntry->getQualType().getStruct(node, templateTypes);
349
2/2
✓ Branch 40 → 41 taken 2 times.
✓ Branch 40 → 49 taken 19809 times.
19811 if (!thisStruct) {
350
1/2
✓ Branch 41 → 42 taken 2 times.
✗ Branch 41 → 103 not taken.
2 const std::string signature = Struct::getSignature(structRegistryEntry->targetEntry->name, templateTypes);
351
2/4
✓ Branch 42 → 43 taken 2 times.
✗ Branch 42 → 98 not taken.
✓ Branch 43 → 44 taken 2 times.
✗ Branch 43 → 96 not taken.
2 const std::string errorMsg = "Could not find struct candidate for struct '" + signature + "'. Do the template types match?";
352
1/2
✓ Branch 45 → 46 taken 2 times.
✗ Branch 45 → 99 not taken.
2 SOFT_ERROR_BOOL(node, UNKNOWN_DATATYPE, errorMsg)
353 2 }
354
355 // Set the 'this' type of the function to the struct type
356
2/4
✓ Branch 49 → 50 taken 19809 times.
✗ Branch 49 → 104 not taken.
✓ Branch 50 → 51 taken 19809 times.
✗ Branch 50 → 104 not taken.
19809 thisType = structEntry->getQualType().getWithBodyScope(thisStruct->scope);
357 19809 calleeParentScope = thisStruct->scope;
358 }
359
360 // Attach the concrete template types to the 'this' type
361
7/8
✓ Branch 52 → 53 taken 69538 times.
✗ Branch 52 → 110 not taken.
✓ Branch 53 → 54 taken 19809 times.
✓ Branch 53 → 57 taken 49729 times.
✓ Branch 55 → 56 taken 4252 times.
✓ Branch 55 → 57 taken 15557 times.
✓ Branch 58 → 59 taken 4252 times.
✓ Branch 58 → 61 taken 65286 times.
69538 if (!thisType.is(TY_DYN) && !templateTypes.empty())
362
1/2
✓ Branch 59 → 60 taken 4252 times.
✗ Branch 59 → 105 not taken.
4252 thisType = thisType.getWithTemplateTypes(templateTypes);
363
364 // Map local arg types to imported types
365
5/8
✓ Branch 61 → 62 taken 69538 times.
✗ Branch 61 → 107 not taken.
✓ Branch 62 → 63 taken 69538 times.
✗ Branch 62 → 107 not taken.
✓ Branch 63 → 64 taken 69538 times.
✗ Branch 63 → 107 not taken.
✓ Branch 69 → 65 taken 117813 times.
✓ Branch 69 → 70 taken 69538 times.
187351 for (QualType &argType : args | std::views::keys)
366
1/2
✓ Branch 66 → 67 taken 117813 times.
✗ Branch 66 → 106 not taken.
117813 argType = mapLocalTypeToImportedScopeType(calleeParentScope, argType);
367
368 // Map local template types to imported types
369
2/2
✓ Branch 84 → 72 taken 9296 times.
✓ Branch 84 → 85 taken 69538 times.
148372 for (QualType &templateType : templateTypes)
370
1/2
✓ Branch 74 → 75 taken 9296 times.
✗ Branch 74 → 108 not taken.
9296 templateType = mapLocalTypeToImportedScopeType(calleeParentScope, templateType);
371
372 // Retrieve function object
373 69538 Scope *matchScope = calleeParentScope;
374
2/2
✓ Branch 85 → 86 taken 69536 times.
✓ Branch 85 → 110 taken 2 times.
69538 callee = FunctionManager::match(matchScope, functionName, data.thisType, data.args, templateTypes, false, node);
375
376 69536 return true;
377 69540 }
378
379 235 bool TypeChecker::visitFctPtrCall(const FctCallNode *node, const QualType &functionType) const {
380
1/2
✓ Branch 2 → 3 taken 235 times.
✗ Branch 2 → 75 not taken.
235 const FctCallNode::FctCallData &data = node->data.at(manIdx);
381 235 const auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope, compTimeVal, hasCompTimeVal] =
382 data;
383
384 // Check if the given argument types match the type
385
1/2
✓ Branch 3 → 4 taken 235 times.
✗ Branch 3 → 75 not taken.
235 const QualTypeList expectedArgTypes = functionType.getFunctionParamTypes();
386
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 14 taken 235 times.
235 if (args.size() != expectedArgTypes.size())
387 SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, "Expected and actual number of arguments do not match")
388
389 // Create resolver function, that always returns a nullptr
390 235 TypeMatcher::ResolverFct resolverFct = [](const std::string &) { return nullptr; };
391
392
2/2
✓ Branch 41 → 16 taken 237 times.
✓ Branch 41 → 42 taken 235 times.
472 for (size_t i = 0; i < args.size(); i++) {
393
1/2
✓ Branch 16 → 17 taken 237 times.
✗ Branch 16 → 71 not taken.
237 const QualType &actualType = args.at(i).first;
394
1/2
✓ Branch 17 → 18 taken 237 times.
✗ Branch 17 → 71 not taken.
237 const QualType &expectedType = expectedArgTypes.at(i);
395
2/4
✓ Branch 19 → 20 taken 237 times.
✗ Branch 19 → 68 not taken.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 34 taken 237 times.
237 if (TypeMapping tm; !TypeMatcher::matchRequestedToCandidateType(expectedType, actualType, tm, resolverFct, false))
396
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 237 times.
✗ Branch 36 → 39 not taken.
237 SOFT_ERROR_BOOL(node->argLst->args.at(i), REFERENCED_UNDEFINED_FUNCTION,
397 "Expected " + expectedType.getName(false) + " but got " + actualType.getName(false))
398 }
399 235 return true;
400 235 }
401
402 62903 bool TypeChecker::visitMethodCall(FctCallNode *node, Scope *structScope) const {
403 62903 FctCallNode::FctCallData &data = node->data.at(manIdx);
404 62903 auto &[callType, isImported, templateTypes, thisType, args, callee, calleeParentScope, compTimeVal, hasCompTimeVal] = data;
405
406 // Traverse through structs - the first fragment is already looked up and the last one is the method name
407
2/2
✓ Branch 43 → 4 taken 14182 times.
✓ Branch 43 → 44 taken 62899 times.
77081 for (size_t i = 1; i < node->functionNameFragments.size() - 1; i++) {
408
1/2
✓ Branch 4 → 5 taken 14182 times.
✗ Branch 4 → 104 not taken.
14182 const std::string &identifier = node->functionNameFragments.at(i);
409
410 // Retrieve field entry, also looking through composed fields
411 14182 std::vector<size_t> indexPath;
412
1/2
✓ Branch 5 → 6 taken 14182 times.
✗ Branch 5 → 102 not taken.
14182 SymbolTableEntry *fieldEntry = structScope->symbolTable.lookupInComposedFields(identifier, indexPath);
413
2/2
✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 21 taken 14180 times.
14182 if (!fieldEntry) {
414
1/2
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 92 not taken.
2 std::stringstream errorMsg;
415
1/2
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 90 not taken.
2 errorMsg << "The type '";
416
3/6
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 85 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 85 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 83 not taken.
2 errorMsg << thisType.getBase().getName(false, true);
417
3/6
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 90 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 90 not taken.
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 90 not taken.
2 errorMsg << "' does not have a member with the name '" << identifier << "'";
418
2/4
✓ Branch 16 → 17 taken 2 times.
✗ Branch 16 → 89 not taken.
✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 87 not taken.
2 SOFT_ERROR_BOOL(node, ACCESS_TO_NON_EXISTING_MEMBER, errorMsg.str())
419 2 }
420
5/8
✓ Branch 21 → 22 taken 14180 times.
✗ Branch 21 → 94 not taken.
✓ Branch 22 → 23 taken 14180 times.
✗ Branch 22 → 94 not taken.
✓ Branch 23 → 24 taken 14180 times.
✗ Branch 23 → 93 not taken.
✓ Branch 24 → 25 taken 2 times.
✓ Branch 24 → 31 taken 14178 times.
14180 if (!fieldEntry->getQualType().getBase().isOneOf({TY_STRUCT, TY_INTERFACE}))
421
3/6
✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 99 not taken.
✓ Branch 26 → 27 taken 2 times.
✗ Branch 26 → 97 not taken.
✓ Branch 27 → 28 taken 2 times.
✗ Branch 27 → 95 not taken.
2 SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS,
422 "Cannot call a method on '" + identifier + "', since it is no struct or interface")
423 14178 fieldEntry->used = true;
424
425 // Get struct type and scope
426
1/2
✓ Branch 31 → 32 taken 14178 times.
✗ Branch 31 → 102 not taken.
14178 thisType = fieldEntry->getQualType();
427
2/4
✓ Branch 32 → 33 taken 14178 times.
✗ Branch 32 → 101 not taken.
✓ Branch 33 → 34 taken 14178 times.
✗ Branch 33 → 101 not taken.
14178 structScope = thisType.getBase().getBodyScope();
428
1/2
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 36 taken 14178 times.
14178 assert(structScope != nullptr);
429
2/2
✓ Branch 38 → 39 taken 14178 times.
✓ Branch 38 → 41 taken 4 times.
14182 }
430
431
1/2
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 53 taken 62899 times.
62899 if (thisType.is(TY_INTERFACE))
432 SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS, "Cannot call a method on an interface")
433
434 // Map local arg types to imported types
435 62899 Scope *matchScope = calleeParentScope = structScope;
436
5/8
✓ Branch 53 → 54 taken 62899 times.
✗ Branch 53 → 112 not taken.
✓ Branch 54 → 55 taken 62899 times.
✗ Branch 54 → 112 not taken.
✓ Branch 55 → 56 taken 62899 times.
✗ Branch 55 → 112 not taken.
✓ Branch 61 → 57 taken 41851 times.
✓ Branch 61 → 62 taken 62899 times.
104750 for (QualType &argType : args | std::views::keys)
437
1/2
✓ Branch 58 → 59 taken 41851 times.
✗ Branch 58 → 111 not taken.
41851 argType = mapLocalTypeToImportedScopeType(calleeParentScope, argType);
438
439 // Map local template types to imported types
440
2/2
✓ Branch 76 → 64 taken 700 times.
✓ Branch 76 → 77 taken 62899 times.
126498 for (QualType &templateType : templateTypes)
441
1/2
✓ Branch 66 → 67 taken 700 times.
✗ Branch 66 → 113 not taken.
700 templateType = mapLocalTypeToImportedScopeType(calleeParentScope, templateType);
442
443 // 'this' type
444
1/2
✓ Branch 77 → 78 taken 62899 times.
✗ Branch 77 → 115 not taken.
62899 thisType = thisType.autoDeReference();
445
1/2
✓ Branch 78 → 79 taken 62899 times.
✗ Branch 78 → 116 not taken.
62899 thisType = mapLocalTypeToImportedScopeType(calleeParentScope, thisType);
446
447 // Retrieve function object
448 62899 const std::string &functionName = node->functionNameFragments.back();
449 62899 callee = FunctionManager::match(matchScope, functionName, thisType, args, templateTypes, false, node);
450
451 62899 return true;
452 }
453
454 670 std::any TypeChecker::visitArrayInitialization(ArrayInitializationNode *node) {
455
5/6
✓ Branch 2 → 3 taken 668 times.
✓ Branch 2 → 5 taken 2 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 668 times.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 18 taken 668 times.
670 if (!node->itemLst || node->itemLst->args.empty())
456
4/8
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 76 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 74 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 80 not taken.
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 80 not taken.
8 SOFT_ERROR_ER(node, ARRAY_SIZE_INVALID, "Array initializers must at least contain one value");
457 668 node->actualSize = node->itemLst->args.size();
458
459
1/2
✓ Branch 19 → 20 taken 668 times.
✗ Branch 19 → 105 not taken.
668 QualType actualItemType(TY_DYN);
460 // Check if all values have the same type
461
2/2
✓ Branch 63 → 22 taken 3630 times.
✓ Branch 63 → 64 taken 666 times.
4964 for (ExprNode *arg : node->itemLst->args) {
462
2/4
✓ Branch 24 → 25 taken 3630 times.
✗ Branch 24 → 83 not taken.
✓ Branch 25 → 26 taken 3630 times.
✗ Branch 25 → 81 not taken.
3630 const QualType itemType = std::any_cast<ExprResult>(visit(arg)).type;
463
2/8
✓ Branch 27 → 28 taken 3630 times.
✗ Branch 27 → 102 not taken.
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 33 taken 3630 times.
✗ Branch 29 → 30 not taken.
✗ Branch 29 → 85 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 85 not taken.
3630 HANDLE_UNRESOLVED_TYPE_ER(itemType)
464
3/4
✓ Branch 33 → 34 taken 3630 times.
✗ Branch 33 → 102 not taken.
✓ Branch 34 → 35 taken 668 times.
✓ Branch 34 → 36 taken 2962 times.
3630 if (actualItemType.is(TY_DYN)) // Perform type inference
465 668 actualItemType = itemType;
466
3/4
✓ Branch 36 → 37 taken 2962 times.
✗ Branch 36 → 102 not taken.
✓ Branch 37 → 38 taken 2 times.
✓ Branch 37 → 53 taken 2960 times.
2962 else if (itemType != actualItemType) // Check if types are matching
467
8/16
✓ Branch 38 → 39 taken 2 times.
✗ Branch 38 → 99 not taken.
✓ Branch 39 → 40 taken 2 times.
✗ Branch 39 → 94 not taken.
✓ Branch 40 → 41 taken 2 times.
✗ Branch 40 → 92 not taken.
✓ Branch 41 → 42 taken 2 times.
✗ Branch 41 → 90 not taken.
✓ Branch 42 → 43 taken 2 times.
✗ Branch 42 → 88 not taken.
✓ Branch 43 → 44 taken 2 times.
✗ Branch 43 → 86 not taken.
✓ Branch 49 → 50 taken 2 times.
✗ Branch 49 → 101 not taken.
✓ Branch 50 → 51 taken 2 times.
✗ Branch 50 → 101 not taken.
4 SOFT_ERROR_ER(arg, ARRAY_ITEM_TYPE_NOT_MATCHING,
468 "All provided values have to be of the same data type. You provided " + actualItemType.getName(false) +
469 " and " + itemType.getName(false))
470 }
471
2/4
✓ Branch 64 → 65 taken 666 times.
✗ Branch 64 → 105 not taken.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 666 times.
666 assert(!actualItemType.is(TY_DYN));
472
473
1/2
✓ Branch 67 → 68 taken 666 times.
✗ Branch 67 → 105 not taken.
666 const QualType arrayType = actualItemType.toArr(node, node->actualSize, true);
474
2/4
✓ Branch 68 → 69 taken 666 times.
✗ Branch 68 → 104 not taken.
✓ Branch 69 → 70 taken 666 times.
✗ Branch 69 → 104 not taken.
1332 return ExprResult{node->setEvaluatedSymbolType(arrayType, manIdx)};
475 }
476
477 3555 std::any TypeChecker::visitStructInstantiation(StructInstantiationNode *node) {
478 // Retrieve struct name
479
1/2
✓ Branch 2 → 3 taken 3555 times.
✗ Branch 2 → 307 not taken.
3555 const auto [aliasedEntry, isAlias] = rootScope->symbolTable.lookupWithAliasResolution(node->fqStructName);
480
5/8
✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 9 taken 3553 times.
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 307 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 307 not taken.
✓ Branch 10 → 11 taken 3555 times.
✗ Branch 10 → 307 not taken.
3555 std::string structName = isAlias ? aliasedEntry->getQualType().getSubType() : node->fqStructName;
481
482 // Check if the struct type is generic
483
1/2
✓ Branch 11 → 12 taken 3555 times.
✗ Branch 11 → 305 not taken.
3555 const QualType *genericType = rootScope->lookupGenericTypeStrict(structName);
484
6/8
✓ Branch 12 → 13 taken 4 times.
✓ Branch 12 → 16 taken 3551 times.
✓ Branch 13 → 14 taken 4 times.
✗ Branch 13 → 305 not taken.
✓ Branch 14 → 15 taken 4 times.
✗ Branch 14 → 16 not taken.
✓ Branch 17 → 18 taken 4 times.
✓ Branch 17 → 23 taken 3551 times.
3555 if (genericType && typeMapping.contains(structName)) {
485
1/2
✓ Branch 18 → 19 taken 4 times.
✗ Branch 18 → 305 not taken.
4 const QualType &replacementType = typeMapping.at(structName);
486
2/4
✓ Branch 19 → 20 taken 4 times.
✗ Branch 19 → 305 not taken.
✓ Branch 20 → 21 taken 4 times.
✗ Branch 20 → 23 not taken.
4 if (replacementType.is(TY_STRUCT))
487
2/4
✓ Branch 21 → 22 taken 4 times.
✗ Branch 21 → 305 not taken.
✓ Branch 22 → 23 taken 4 times.
✗ Branch 22 → 305 not taken.
4 structName = replacementType.getSubType();
488 }
489
490 // Retrieve struct
491
1/2
✓ Branch 23 → 24 taken 3555 times.
✗ Branch 23 → 305 not taken.
3555 const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(structName);
492
2/2
✓ Branch 24 → 25 taken 2 times.
✓ Branch 24 → 34 taken 3553 times.
3555 if (!registryEntry)
493
5/10
✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 234 not taken.
✓ Branch 26 → 27 taken 2 times.
✗ Branch 26 → 232 not taken.
✓ Branch 27 → 28 taken 2 times.
✗ Branch 27 → 230 not taken.
✓ Branch 30 → 31 taken 2 times.
✗ Branch 30 → 236 not taken.
✓ Branch 31 → 32 taken 2 times.
✗ Branch 31 → 236 not taken.
4 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT, "Cannot find struct '" + structName + "'")
494
2/4
✓ Branch 34 → 35 taken 3553 times.
✗ Branch 34 → 37 not taken.
✓ Branch 35 → 36 taken 3553 times.
✗ Branch 35 → 37 not taken.
3553 assert(registryEntry->targetEntry != nullptr && registryEntry->targetScope != nullptr);
495 3553 SymbolTableEntry *structEntry = registryEntry->targetEntry;
496
497 // Check visibility
498
9/12
✓ Branch 38 → 39 taken 3553 times.
✗ Branch 38 → 305 not taken.
✓ Branch 39 → 40 taken 3553 times.
✗ Branch 39 → 305 not taken.
✓ Branch 40 → 41 taken 1087 times.
✓ Branch 40 → 44 taken 2466 times.
✓ Branch 41 → 42 taken 1087 times.
✗ Branch 41 → 305 not taken.
✓ Branch 42 → 43 taken 2 times.
✓ Branch 42 → 44 taken 1085 times.
✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 55 taken 3551 times.
3553 if (!structEntry->getQualType().isPublic() && structEntry->scope->isImportedBy(currentScope))
499
5/10
✓ Branch 46 → 47 taken 2 times.
✗ Branch 46 → 241 not taken.
✓ Branch 47 → 48 taken 2 times.
✗ Branch 47 → 239 not taken.
✓ Branch 48 → 49 taken 2 times.
✗ Branch 48 → 237 not taken.
✓ Branch 51 → 52 taken 2 times.
✗ Branch 51 → 243 not taken.
✓ Branch 52 → 53 taken 2 times.
✗ Branch 52 → 243 not taken.
4 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Struct '" + structName + "' has insufficient visibility")
500
501 // Get struct type
502
1/2
✓ Branch 55 → 56 taken 3551 times.
✗ Branch 55 → 305 not taken.
3551 QualType structType = structEntry->getQualType();
503
504 // Get the concrete template types
505 3551 QualTypeList concreteTemplateTypes;
506
2/2
✓ Branch 56 → 57 taken 2 times.
✓ Branch 56 → 76 taken 3549 times.
3551 if (isAlias) {
507 // Retrieve concrete template types from type alias
508
3/6
✓ Branch 57 → 58 taken 2 times.
✗ Branch 57 → 303 not taken.
✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 303 not taken.
✓ Branch 59 → 60 taken 2 times.
✗ Branch 59 → 303 not taken.
2 concreteTemplateTypes = aliasedEntry->getQualType().getTemplateTypes();
509 // Check if the aliased type specified template types and the struct instantiation does
510
3/6
✓ Branch 61 → 62 taken 2 times.
✗ Branch 61 → 64 not taken.
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 64 taken 2 times.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 76 taken 2 times.
2 if (!concreteTemplateTypes.empty() && node->templateTypeLst)
511 SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list")
512 }
513
514
2/2
✓ Branch 76 → 77 taken 26 times.
✓ Branch 76 → 117 taken 3525 times.
3551 if (node->templateTypeLst) {
515
1/2
✓ Branch 78 → 79 taken 26 times.
✗ Branch 78 → 303 not taken.
26 concreteTemplateTypes.reserve(node->templateTypeLst->dataTypes.size());
516
2/2
✓ Branch 115 → 81 taken 34 times.
✓ Branch 115 → 116 taken 26 times.
86 for (DataTypeNode *dataType : node->templateTypeLst->dataTypes) {
517
2/4
✓ Branch 83 → 84 taken 34 times.
✗ Branch 83 → 253 not taken.
✓ Branch 84 → 85 taken 34 times.
✗ Branch 84 → 251 not taken.
34 auto concreteType = std::any_cast<QualType>(visit(dataType));
518
2/8
✓ Branch 86 → 87 taken 34 times.
✗ Branch 86 → 262 not taken.
✗ Branch 87 → 88 not taken.
✓ Branch 87 → 92 taken 34 times.
✗ Branch 88 → 89 not taken.
✗ Branch 88 → 254 not taken.
✗ Branch 89 → 90 not taken.
✗ Branch 89 → 254 not taken.
34 HANDLE_UNRESOLVED_TYPE_ER(concreteType)
519 // Check if generic type
520
2/4
✓ Branch 92 → 93 taken 34 times.
✗ Branch 92 → 262 not taken.
✗ Branch 93 → 94 not taken.
✓ Branch 93 → 104 taken 34 times.
34 if (concreteType.is(TY_GENERIC))
521 SOFT_ERROR_ER(dataType, EXPECTED_NON_GENERIC_TYPE, "Struct instantiations may only take concrete template types")
522
1/2
✓ Branch 104 → 105 taken 34 times.
✗ Branch 104 → 262 not taken.
34 concreteTemplateTypes.push_back(concreteType);
523 }
524 }
525
526 // Get the struct instance
527
2/4
✓ Branch 117 → 118 taken 3551 times.
✗ Branch 117 → 303 not taken.
✓ Branch 118 → 119 taken 3551 times.
✗ Branch 118 → 303 not taken.
3551 Struct *spiceStruct = node->instantiatedStructs.at(manIdx) = structType.getStructAndAdjustType(node, concreteTemplateTypes);
528
2/2
✓ Branch 119 → 120 taken 2 times.
✓ Branch 119 → 131 taken 3549 times.
3551 if (!spiceStruct)
529
6/12
✓ Branch 120 → 121 taken 2 times.
✗ Branch 120 → 270 not taken.
✓ Branch 121 → 122 taken 2 times.
✗ Branch 121 → 268 not taken.
✓ Branch 122 → 123 taken 2 times.
✗ Branch 122 → 266 not taken.
✓ Branch 123 → 124 taken 2 times.
✗ Branch 123 → 264 not taken.
✓ Branch 127 → 128 taken 2 times.
✗ Branch 127 → 273 not taken.
✓ Branch 128 → 129 taken 2 times.
✗ Branch 128 → 273 not taken.
4 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT,
530 "Struct '" + Struct::getSignature(structName, concreteTemplateTypes) + "' could not be found")
531
532 // Struct instantiation for an inheriting struct is forbidden, because the vtable needs to be initialized and this is done in
533 // the ctor of the struct, which is never called in case of struct instantiation
534
2/2
✓ Branch 132 → 133 taken 2 times.
✓ Branch 132 → 143 taken 3547 times.
3549 if (!spiceStruct->interfaceTypes.empty())
535
4/8
✓ Branch 135 → 136 taken 2 times.
✗ Branch 135 → 276 not taken.
✓ Branch 136 → 137 taken 2 times.
✗ Branch 136 → 274 not taken.
✓ Branch 139 → 140 taken 2 times.
✗ Branch 139 → 280 not taken.
✓ Branch 140 → 141 taken 2 times.
✗ Branch 140 → 280 not taken.
8 SOFT_ERROR_ER(node, INVALID_STRUCT_INSTANTIATION, "Struct instantiations for inheriting structs are forbidden")
536
537 // Check if the number of fields matches
538
2/2
✓ Branch 143 → 144 taken 3495 times.
✓ Branch 143 → 204 taken 52 times.
3547 if (node->fieldLst) { // Check if any fields are passed. Empty braces are also allowed
539
2/2
✓ Branch 146 → 147 taken 2 times.
✓ Branch 146 → 157 taken 3493 times.
3495 if (spiceStruct->fieldTypes.size() != node->fieldLst->args.size())
540
4/8
✓ Branch 149 → 150 taken 2 times.
✗ Branch 149 → 283 not taken.
✓ Branch 150 → 151 taken 2 times.
✗ Branch 150 → 281 not taken.
✓ Branch 153 → 154 taken 2 times.
✗ Branch 153 → 287 not taken.
✓ Branch 154 → 155 taken 2 times.
✗ Branch 154 → 287 not taken.
8 SOFT_ERROR_ER(node->fieldLst, NUMBER_OF_FIELDS_NOT_MATCHING,
541 "You've passed too less/many field values. Pass either none or all of them")
542
543 // Check if the field types are matching
544 3493 const size_t fieldCount = spiceStruct->fieldTypes.size();
545
1/2
✓ Branch 158 → 159 taken 3493 times.
✗ Branch 158 → 303 not taken.
3493 const size_t explicitFieldsStartIdx = spiceStruct->scope->getFieldCount() - fieldCount;
546 // Per-manifestation: a struct literal inside a generic function is re-type-checked once per manifestation of
547 // that function, and the struct itself may resolve to a different concrete type each time (e.g. HashEntry<K,
548 // V> inside HashTable<K, V>.upsert()), so the copy-ctor set from one manifestation must not leak into another.
549
1/2
✓ Branch 159 → 160 taken 3493 times.
✗ Branch 159 → 303 not taken.
3493 std::vector<Function *> &fieldCopyCtors = node->fieldCopyCtors.at(manIdx);
550 3493 fieldCopyCtors.clear();
551
2/2
✓ Branch 199 → 162 taken 7188 times.
✓ Branch 199 → 200 taken 3491 times.
10679 for (size_t i = 0; i < node->fieldLst->args.size(); i++) {
552 // Get actual type
553
1/2
✓ Branch 162 → 163 taken 7188 times.
✗ Branch 162 → 294 not taken.
7188 ExprNode *assignExpr = node->fieldLst->args.at(i);
554
2/4
✓ Branch 163 → 164 taken 7188 times.
✗ Branch 163 → 290 not taken.
✓ Branch 164 → 165 taken 7188 times.
✗ Branch 164 → 288 not taken.
7188 auto fieldResult = std::any_cast<ExprResult>(visit(assignExpr));
555
2/8
✓ Branch 166 → 167 taken 7188 times.
✗ Branch 166 → 294 not taken.
✗ Branch 167 → 168 not taken.
✓ Branch 167 → 172 taken 7188 times.
✗ Branch 168 → 169 not taken.
✗ Branch 168 → 291 not taken.
✗ Branch 169 → 170 not taken.
✗ Branch 169 → 291 not taken.
7188 HANDLE_UNRESOLVED_TYPE_ER(fieldResult.type)
556 // Get expected type
557
1/2
✗ Branch 172 → 173 not taken.
✓ Branch 172 → 175 taken 7188 times.
7188 SymbolTableEntry *expectedField = spiceStruct->scope->lookupField(explicitFieldsStartIdx + i);
558
1/2
✗ Branch 178 → 179 not taken.
✓ Branch 178 → 180 taken 7188 times.
7188 assert(expectedField != nullptr);
559
1/2
✓ Branch 180 → 181 taken 7188 times.
✗ Branch 180 → 294 not taken.
7188 const ExprResult expected = {expectedField->getQualType(), expectedField};
560
1/2
✓ Branch 181 → 182 taken 7188 times.
✗ Branch 181 → 294 not taken.
7188 const bool rhsIsImmediate = assignExpr->hasCompileTimeValue(manIdx);
561
562 // Capture anonymous info up front: getFieldAssignResultType may delete the anonymous entry (temp stealing
563 // in performStructAssign), turning fieldResult.entry into a dangling pointer.
564
4/4
✓ Branch 182 → 183 taken 4440 times.
✓ Branch 182 → 185 taken 2748 times.
✓ Branch 183 → 184 taken 14 times.
✓ Branch 183 → 185 taken 4426 times.
7188 const bool rhsIsAnonymous = fieldResult.entry != nullptr && fieldResult.entry->anonymous;
565
3/4
✓ Branch 186 → 187 taken 14 times.
✓ Branch 186 → 188 taken 7174 times.
✓ Branch 187 → 189 taken 14 times.
✗ Branch 187 → 294 not taken.
7188 const std::string rhsEntryName = rhsIsAnonymous ? fieldResult.entry->name : std::string();
566
567 // Check if actual type matches expected type. A non-anonymous, non-trivially-copyable rhs (e.g. a plain
568 // local variable) needs its value deep-copied into the field: the struct instantiation does not
569 // consume/move it, so the caller keeps its own copy alive and destructs it independently.
570
2/2
✓ Branch 189 → 190 taken 7186 times.
✓ Branch 189 → 292 taken 2 times.
7188 const auto [_, copyCtor] = opRuleManager.getFieldAssignResultType(assignExpr, expected, fieldResult, rhsIsImmediate, true);
571
1/2
✓ Branch 192 → 193 taken 7186 times.
✗ Branch 192 → 292 not taken.
7186 fieldCopyCtors.push_back(copyCtor);
572
573 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it.
574 // Safe to call even if performStructAssign already deleted it: map::erase by key is a no-op when absent.
575
2/2
✓ Branch 193 → 194 taken 14 times.
✓ Branch 193 → 196 taken 7172 times.
7186 if (rhsIsAnonymous) {
576
1/2
✓ Branch 194 → 195 taken 14 times.
✗ Branch 194 → 292 not taken.
14 currentScope->symbolTable.deleteAnonymous(rhsEntryName);
577 14 fieldResult.entry = nullptr;
578 }
579 7188 }
580
1/2
✗ Branch 202 → 203 not taken.
✓ Branch 202 → 216 taken 3491 times.
3491 assert(fieldCopyCtors.size() == node->fieldLst->args.size());
581 } else {
582
2/4
✓ Branch 204 → 205 taken 52 times.
✗ Branch 204 → 303 not taken.
✗ Branch 205 → 206 not taken.
✓ Branch 205 → 216 taken 52 times.
228 if (std::ranges::any_of(spiceStruct->fieldTypes, [](const QualType &fieldType) { return fieldType.isRef(); }))
583 SOFT_ERROR_ER(node, REFERENCE_WITHOUT_INITIALIZER,
584 "The struct takes at least one reference field. You need to instantiate it with all fields.")
585 }
586
587 // Update type of struct entry
588
1/2
✓ Branch 216 → 217 taken 3543 times.
✗ Branch 216 → 303 not taken.
3543 structEntry->updateType(structType, true);
589
590 // Add anonymous symbol to keep track of dtor call, if non-trivially destructible
591 3543 SymbolTableEntry *anonymousEntry = nullptr;
592
3/4
✓ Branch 217 → 218 taken 3543 times.
✗ Branch 217 → 303 not taken.
✓ Branch 218 → 219 taken 175 times.
✓ Branch 218 → 221 taken 3368 times.
3543 if (!structType.isTriviallyDestructible(node))
593
1/2
✓ Branch 219 → 220 taken 175 times.
✗ Branch 219 → 303 not taken.
175 anonymousEntry = currentScope->symbolTable.insertAnonymous(structType, node);
594
595 // Remove public qualifier to not have public local variables
596 3543 structType.getQualifiers().isPublic = false;
597
598
2/4
✓ Branch 222 → 223 taken 3543 times.
✗ Branch 222 → 302 not taken.
✓ Branch 223 → 224 taken 3543 times.
✗ Branch 223 → 302 not taken.
7086 return ExprResult{node->setEvaluatedSymbolType(structType, manIdx), anonymousEntry};
599 3557 }
600
601 109 std::any TypeChecker::visitLambdaFunc(LambdaFuncNode *node) {
602 // Check if all control paths in the lambda body return
603 109 bool returnsOnAllControlPaths = true;
604
3/4
✓ Branch 2 → 3 taken 109 times.
✗ Branch 2 → 194 not taken.
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 14 taken 107 times.
109 if (!node->returnsOnAllControlPaths(&returnsOnAllControlPaths, manIdx))
605
4/8
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 120 not taken.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 118 not taken.
✓ Branch 10 → 11 taken 2 times.
✗ Branch 10 → 124 not taken.
✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 124 not taken.
8 SOFT_ERROR_ER(node, MISSING_RETURN_STMT, "Not all control paths of this lambda function have a return statement")
606
607 // Change to function scope
608
2/4
✓ Branch 14 → 15 taken 107 times.
✗ Branch 14 → 127 not taken.
✓ Branch 15 → 16 taken 107 times.
✗ Branch 15 → 125 not taken.
107 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
609
1/2
✓ Branch 17 → 18 taken 107 times.
✗ Branch 17 → 128 not taken.
107 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
610
611 // Visit return type
612
2/4
✓ Branch 18 → 19 taken 107 times.
✗ Branch 18 → 131 not taken.
✓ Branch 19 → 20 taken 107 times.
✗ Branch 19 → 129 not taken.
107 const auto returnType = std::any_cast<QualType>(visit(node->returnType));
613
2/8
✓ Branch 21 → 22 taken 107 times.
✗ Branch 21 → 192 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 27 taken 107 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 132 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 132 not taken.
107 HANDLE_UNRESOLVED_TYPE_ER(returnType)
614
3/4
✓ Branch 27 → 28 taken 107 times.
✗ Branch 27 → 192 not taken.
✓ Branch 28 → 29 taken 2 times.
✓ Branch 28 → 39 taken 105 times.
107 if (returnType.is(TY_DYN))
615
4/8
✓ Branch 31 → 32 taken 2 times.
✗ Branch 31 → 135 not taken.
✓ Branch 32 → 33 taken 2 times.
✗ Branch 32 → 133 not taken.
✓ Branch 35 → 36 taken 2 times.
✗ Branch 35 → 139 not taken.
✓ Branch 36 → 37 taken 2 times.
✗ Branch 36 → 139 not taken.
8 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed")
616
617 // Set the type of the result variable
618
1/2
✓ Branch 41 → 42 taken 105 times.
✗ Branch 41 → 142 not taken.
315 SymbolTableEntry *resultVarEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
619
1/2
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 105 times.
105 assert(resultVarEntry != nullptr);
620
1/2
✓ Branch 49 → 50 taken 105 times.
✗ Branch 49 → 192 not taken.
105 resultVarEntry->updateType(returnType, true);
621 105 resultVarEntry->used = true;
622
623 // Visit parameters
624 105 QualTypeList paramTypes;
625 105 ParamList paramList;
626
2/2
✓ Branch 50 → 51 taken 95 times.
✓ Branch 50 → 80 taken 10 times.
105 if (node->hasParams) {
627 // Visit param list to retrieve the param names
628
2/4
✓ Branch 51 → 52 taken 95 times.
✗ Branch 51 → 148 not taken.
✓ Branch 52 → 53 taken 95 times.
✗ Branch 52 → 146 not taken.
95 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
629
2/2
✓ Branch 77 → 56 taken 125 times.
✓ Branch 77 → 78 taken 95 times.
315 for (const auto &[name, qualType, isOptional] : namedParamList) {
630
1/2
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 66 taken 125 times.
125 if (isOptional)
631 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
632
633
1/2
✓ Branch 66 → 67 taken 125 times.
✗ Branch 66 → 156 not taken.
125 paramTypes.push_back(qualType);
634
1/2
✓ Branch 67 → 68 taken 125 times.
✗ Branch 67 → 155 not taken.
125 paramList.push_back({qualType, isOptional});
635 }
636 95 }
637
638 // Visit lambda body
639
2/2
✓ Branch 80 → 81 taken 103 times.
✓ Branch 80 → 160 taken 2 times.
105 visit(node->body);
640
641 // Leave function body scope
642
1/2
✓ Branch 82 → 83 taken 103 times.
✗ Branch 82 → 188 not taken.
103 scopeHandle.leaveScopeEarly();
643
644 // Prepare type of function
645
1/2
✓ Branch 83 → 84 taken 103 times.
✗ Branch 83 → 161 not taken.
103 const QualType functionType = QualType(TY_FUNCTION)
646
1/2
✓ Branch 84 → 85 taken 103 times.
✗ Branch 84 → 161 not taken.
103 .getWithFunctionParamAndReturnTypes(returnType, paramTypes)
647
1/2
✓ Branch 86 → 87 taken 103 times.
✗ Branch 86 → 161 not taken.
103 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
648
649 // Create function object
650
2/4
✓ Branch 87 → 88 taken 103 times.
✗ Branch 87 → 165 not taken.
✓ Branch 88 → 89 taken 103 times.
✗ Branch 88 → 163 not taken.
103 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
651
5/10
✓ Branch 91 → 92 taken 103 times.
✗ Branch 91 → 174 not taken.
✓ Branch 92 → 93 taken 103 times.
✗ Branch 92 → 171 not taken.
✓ Branch 93 → 94 taken 103 times.
✗ Branch 93 → 170 not taken.
✓ Branch 94 → 95 taken 103 times.
✗ Branch 94 → 168 not taken.
✓ Branch 95 → 96 taken 103 times.
✗ Branch 95 → 166 not taken.
103 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node);
652
1/2
✓ Branch 101 → 102 taken 103 times.
✗ Branch 101 → 186 not taken.
103 node->manifestations.at(manIdx).bodyScope = bodyScope;
653
3/6
✓ Branch 102 → 103 taken 103 times.
✗ Branch 102 → 183 not taken.
✓ Branch 103 → 104 taken 103 times.
✗ Branch 103 → 181 not taken.
✓ Branch 104 → 105 taken 103 times.
✗ Branch 104 → 179 not taken.
103 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
654
655 // Check special requirements if this is an async lambda
656
1/2
✓ Branch 108 → 109 taken 103 times.
✗ Branch 108 → 186 not taken.
103 (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr);
657
658
2/4
✓ Branch 109 → 110 taken 103 times.
✗ Branch 109 → 185 not taken.
✓ Branch 110 → 111 taken 103 times.
✗ Branch 110 → 185 not taken.
103 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
659 111 }
660
661 92 std::any TypeChecker::visitLambdaProc(LambdaProcNode *node) {
662 // Mark unreachable statements
663 92 bool doSetPredecessorsUnreachable = true;
664
1/2
✓ Branch 2 → 3 taken 92 times.
✗ Branch 2 → 131 not taken.
92 node->returnsOnAllControlPaths(&doSetPredecessorsUnreachable, manIdx);
665
666 // Change to function scope
667
2/4
✓ Branch 3 → 4 taken 92 times.
✗ Branch 3 → 79 not taken.
✓ Branch 4 → 5 taken 92 times.
✗ Branch 4 → 77 not taken.
92 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
668
1/2
✓ Branch 6 → 7 taken 92 times.
✗ Branch 6 → 80 not taken.
92 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
669
670 // Visit parameters
671 92 QualTypeList paramTypes;
672 92 ParamList paramList;
673
2/2
✓ Branch 7 → 8 taken 58 times.
✓ Branch 7 → 37 taken 34 times.
92 if (node->hasParams) {
674 // Visit param list to retrieve the param names
675
2/4
✓ Branch 8 → 9 taken 58 times.
✗ Branch 8 → 83 not taken.
✓ Branch 9 → 10 taken 58 times.
✗ Branch 9 → 81 not taken.
58 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
676
2/2
✓ Branch 34 → 13 taken 78 times.
✓ Branch 34 → 35 taken 58 times.
194 for (const auto &[_, qualType, isOptional] : namedParamList) {
677
2/2
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 23 taken 76 times.
78 if (isOptional)
678
2/4
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 86 not taken.
✓ Branch 19 → 20 taken 2 times.
✗ Branch 19 → 84 not taken.
4 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
679
680
1/2
✓ Branch 23 → 24 taken 78 times.
✗ Branch 23 → 91 not taken.
78 paramTypes.push_back(qualType);
681
1/2
✓ Branch 24 → 25 taken 78 times.
✗ Branch 24 → 90 not taken.
78 paramList.push_back({qualType, isOptional});
682 }
683 58 }
684
685 // Visit lambda body
686
1/2
✓ Branch 37 → 38 taken 92 times.
✗ Branch 37 → 95 not taken.
92 visit(node->body);
687
688 // Leave function body scope
689
1/2
✓ Branch 39 → 40 taken 92 times.
✗ Branch 39 → 125 not taken.
92 scopeHandle.leaveScopeEarly();
690
691 // Prepare type of function
692
1/2
✓ Branch 40 → 41 taken 92 times.
✗ Branch 40 → 97 not taken.
92 const QualType functionType = QualType(TY_PROCEDURE)
693
2/4
✓ Branch 41 → 42 taken 92 times.
✗ Branch 41 → 96 not taken.
✓ Branch 42 → 43 taken 92 times.
✗ Branch 42 → 96 not taken.
92 .getWithFunctionParamAndReturnTypes(QualType(TY_DYN), paramTypes)
694
1/2
✓ Branch 44 → 45 taken 92 times.
✗ Branch 44 → 96 not taken.
92 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
695
696 // Create function object
697
2/4
✓ Branch 45 → 46 taken 92 times.
✗ Branch 45 → 101 not taken.
✓ Branch 46 → 47 taken 92 times.
✗ Branch 46 → 99 not taken.
92 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
698
6/12
✓ Branch 49 → 50 taken 92 times.
✗ Branch 49 → 111 not taken.
✓ Branch 50 → 51 taken 92 times.
✗ Branch 50 → 108 not taken.
✓ Branch 51 → 52 taken 92 times.
✗ Branch 51 → 107 not taken.
✓ Branch 52 → 53 taken 92 times.
✗ Branch 52 → 106 not taken.
✓ Branch 53 → 54 taken 92 times.
✗ Branch 53 → 104 not taken.
✓ Branch 54 → 55 taken 92 times.
✗ Branch 54 → 102 not taken.
92 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), QualType(TY_DYN), paramList, {}, node);
699
1/2
✓ Branch 60 → 61 taken 92 times.
✗ Branch 60 → 123 not taken.
92 node->manifestations.at(manIdx).bodyScope = bodyScope;
700
3/6
✓ Branch 61 → 62 taken 92 times.
✗ Branch 61 → 120 not taken.
✓ Branch 62 → 63 taken 92 times.
✗ Branch 62 → 118 not taken.
✓ Branch 63 → 64 taken 92 times.
✗ Branch 63 → 116 not taken.
92 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
701
702 // Check special requirements if this is an async lambda
703
1/2
✓ Branch 67 → 68 taken 92 times.
✗ Branch 67 → 123 not taken.
92 (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr);
704
705
2/4
✓ Branch 68 → 69 taken 92 times.
✗ Branch 68 → 122 not taken.
✓ Branch 69 → 70 taken 92 times.
✗ Branch 69 → 122 not taken.
184 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
706 92 }
707
708 2 std::any TypeChecker::visitLambdaExpr(LambdaExprNode *node) {
709 // Change to function scope
710
2/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 98 not taken.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 96 not taken.
2 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
711
1/2
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 99 not taken.
2 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
712
713 // Visit parameters
714 2 QualTypeList paramTypes;
715 2 ParamList paramList;
716
1/2
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 36 not taken.
2 if (node->hasParams) {
717 // Visit param list to retrieve the param names
718
2/4
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 102 not taken.
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 100 not taken.
2 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
719
2/2
✓ Branch 33 → 12 taken 4 times.
✓ Branch 33 → 34 taken 2 times.
8 for (const NamedParam &param : namedParamList) {
720
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 22 taken 4 times.
4 if (param.isOptional)
721 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
722
723
1/2
✓ Branch 22 → 23 taken 4 times.
✗ Branch 22 → 110 not taken.
4 paramTypes.push_back(param.qualType);
724
1/2
✓ Branch 23 → 24 taken 4 times.
✗ Branch 23 → 109 not taken.
4 paramList.push_back({param.qualType, param.isOptional});
725 }
726 2 }
727
728 // Visit lambda expression
729
2/4
✓ Branch 36 → 37 taken 2 times.
✗ Branch 36 → 116 not taken.
✓ Branch 37 → 38 taken 2 times.
✗ Branch 37 → 114 not taken.
2 const QualType returnType = std::any_cast<ExprResult>(visit(node->lambdaExpr)).type;
730
2/8
✓ Branch 39 → 40 taken 2 times.
✗ Branch 39 → 153 not taken.
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 45 taken 2 times.
✗ Branch 41 → 42 not taken.
✗ Branch 41 → 118 not taken.
✗ Branch 42 → 43 not taken.
✗ Branch 42 → 118 not taken.
2 HANDLE_UNRESOLVED_TYPE_ER(returnType)
731
2/4
✓ Branch 45 → 46 taken 2 times.
✗ Branch 45 → 153 not taken.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 57 taken 2 times.
2 if (returnType.is(TY_DYN))
732 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed")
733
734 // Leave function body scope
735
1/2
✓ Branch 57 → 58 taken 2 times.
✗ Branch 57 → 153 not taken.
2 scopeHandle.leaveScopeEarly();
736
737 // Prepare type of function
738
2/4
✓ Branch 58 → 59 taken 2 times.
✗ Branch 58 → 153 not taken.
✗ Branch 59 → 60 not taken.
✓ Branch 59 → 61 taken 2 times.
2 const SuperType superType = returnType.is(TY_DYN) ? TY_PROCEDURE : TY_FUNCTION;
739
1/2
✓ Branch 62 → 63 taken 2 times.
✗ Branch 62 → 126 not taken.
2 const QualType functionType = QualType(superType)
740
1/2
✓ Branch 63 → 64 taken 2 times.
✗ Branch 63 → 126 not taken.
2 .getWithFunctionParamAndReturnTypes(returnType, paramTypes)
741
1/2
✓ Branch 65 → 66 taken 2 times.
✗ Branch 65 → 126 not taken.
2 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
742
743 // Create function object
744
2/4
✓ Branch 66 → 67 taken 2 times.
✗ Branch 66 → 130 not taken.
✓ Branch 67 → 68 taken 2 times.
✗ Branch 67 → 128 not taken.
2 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
745
5/10
✓ Branch 70 → 71 taken 2 times.
✗ Branch 70 → 139 not taken.
✓ Branch 71 → 72 taken 2 times.
✗ Branch 71 → 136 not taken.
✓ Branch 72 → 73 taken 2 times.
✗ Branch 72 → 135 not taken.
✓ Branch 73 → 74 taken 2 times.
✗ Branch 73 → 133 not taken.
✓ Branch 74 → 75 taken 2 times.
✗ Branch 74 → 131 not taken.
2 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node);
746
1/2
✓ Branch 80 → 81 taken 2 times.
✗ Branch 80 → 151 not taken.
2 node->manifestations.at(manIdx).bodyScope = bodyScope;
747
3/6
✓ Branch 81 → 82 taken 2 times.
✗ Branch 81 → 148 not taken.
✓ Branch 82 → 83 taken 2 times.
✗ Branch 82 → 146 not taken.
✓ Branch 83 → 84 taken 2 times.
✗ Branch 83 → 144 not taken.
2 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
748
749
2/4
✓ Branch 87 → 88 taken 2 times.
✗ Branch 87 → 150 not taken.
✓ Branch 88 → 89 taken 2 times.
✗ Branch 88 → 150 not taken.
2 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
750 2 }
751
752 } // namespace spice::compiler
753