GCC Code Coverage Report


Directory: ../
File: src/typechecker/TypeCheckerValues.cpp
Date: 2025-12-15 05:32:10
Coverage Exec Excl Total
Lines: 95.4% 397 3 419
Functions: 92.3% 12 0 13
Branches: 52.8% 634 8 1209

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