GCC Code Coverage Report


Directory: ../
File: src/typechecker/TypeCheckerValues.cpp
Date: 2025-10-23 00:48:11
Coverage Exec Excl Total
Lines: 95.4% 396 3 418
Functions: 92.3% 12 0 13
Branches: 52.7% 632 8 1207

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