GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 96.5% 411 / 3 / 429
Functions: 92.3% 12 / 0 / 13
Branches: 53.8% 671 / 8 / 1256

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