GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 96.4% 406 / 3 / 424
Functions: 92.3% 12 / 0 / 13
Branches: 53.6% 661 / 8 / 1242

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