GCC Code Coverage Report


Directory: ../
File: src/typechecker/TypeChecker.cpp
Date: 2024-12-24 01:17:15
Exec Total Coverage
Lines: 1504 1578 95.3%
Functions: 81 82 98.8%
Branches: 2462 4675 52.7%

Line Branch Exec Source
1 // Copyright (c) 2021-2024 ChilliBits. All rights reserved.
2
3 #include "TypeChecker.h"
4
5 #include <SourceFile.h>
6 #include <ast/ASTBuilder.h>
7 #include <ast/Attributes.h>
8 #include <global/GlobalResourceManager.h>
9 #include <symboltablebuilder/ScopeHandle.h>
10 #include <symboltablebuilder/SymbolTableBuilder.h>
11 #include <typechecker/MacroDefs.h>
12 #include <typechecker/TypeMatcher.h>
13
14 namespace spice::compiler {
15
16 4327 TypeChecker::TypeChecker(GlobalResourceManager &resourceManager, SourceFile *sourceFile, TypeCheckerMode typeCheckerMode)
17
1/2
✓ Branch 3 taken 4327 times.
✗ Branch 4 not taken.
4327 : CompilerPass(resourceManager, sourceFile), typeCheckerMode(typeCheckerMode), warnings(sourceFile->compilerOutput.warnings) {
18 4327 }
19
20 4536 std::any TypeChecker::visitEntry(EntryNode *node) {
21 // Initialize
22 4536 currentScope = rootScope;
23
24 // Initialize AST nodes with size of 1
25 4536 const bool isPrepare = typeCheckerMode == TC_MODE_PRE;
26
2/2
✓ Branch 0 taken 868 times.
✓ Branch 1 taken 3668 times.
4536 if (isPrepare)
27 868 node->resizeToNumberOfManifestations(1);
28
29 // Visit children
30
2/2
✓ Branch 1 taken 4492 times.
✓ Branch 2 taken 44 times.
4536 visitChildren(node);
31
32 // Check which implicit structures we need for each struct, defined in this source file
33
2/2
✓ Branch 0 taken 854 times.
✓ Branch 1 taken 3638 times.
4492 if (isPrepare) {
34
1/2
✓ Branch 1 taken 854 times.
✗ Branch 2 not taken.
854 const std::vector<const Struct *> manifestations = rootScope->getAllStructManifestationsInDeclarationOrder();
35
2/2
✓ Branch 5 taken 539 times.
✓ Branch 6 taken 854 times.
1393 for (const Struct *manifestation : manifestations) {
36 // Check if we need to create a default ctor, copy ctor or dtor
37
1/2
✓ Branch 1 taken 539 times.
✗ Branch 2 not taken.
539 createDefaultCtorIfRequired(*manifestation, manifestation->scope);
38
1/2
✓ Branch 1 taken 539 times.
✗ Branch 2 not taken.
539 createDefaultCopyCtorIfRequired(*manifestation, manifestation->scope);
39
1/2
✓ Branch 1 taken 539 times.
✗ Branch 2 not taken.
539 createDefaultDtorIfRequired(*manifestation, manifestation->scope);
40 }
41 854 }
42
43
1/2
✓ Branch 1 taken 4492 times.
✗ Branch 2 not taken.
4492 return nullptr;
44 }
45
46 723 std::any TypeChecker::visitMainFctDef(MainFctDefNode *node) {
47
2/2
✓ Branch 0 taken 343 times.
✓ Branch 1 taken 380 times.
723 if (typeCheckerMode == TC_MODE_PRE)
48 343 return visitMainFctDefPrepare(node);
49 else
50 380 return visitMainFctDefCheck(node);
51 }
52
53 31717 std::any TypeChecker::visitFctDef(FctDefNode *node) {
54
2/2
✓ Branch 0 taken 4247 times.
✓ Branch 1 taken 27470 times.
31717 if (typeCheckerMode == TC_MODE_PRE)
55 4247 return visitFctDefPrepare(node);
56 else
57 27470 return visitFctDefCheck(node);
58 }
59
60 21261 std::any TypeChecker::visitProcDef(ProcDefNode *node) {
61
2/2
✓ Branch 0 taken 2701 times.
✓ Branch 1 taken 18560 times.
21261 if (typeCheckerMode == TC_MODE_PRE)
62 2701 return visitProcDefPrepare(node);
63 else
64 18560 return visitProcDefCheck(node);
65 }
66
67 3583 std::any TypeChecker::visitStructDef(StructDefNode *node) {
68
2/2
✓ Branch 0 taken 544 times.
✓ Branch 1 taken 3039 times.
3583 if (typeCheckerMode == TC_MODE_PRE)
69 544 return visitStructDefPrepare(node);
70 else
71 3039 return visitStructDefCheck(node);
72 }
73
74 416 std::any TypeChecker::visitInterfaceDef(InterfaceDefNode *node) {
75
2/2
✓ Branch 0 taken 74 times.
✓ Branch 1 taken 342 times.
416 if (typeCheckerMode == TC_MODE_PRE)
76 74 return visitInterfaceDefPrepare(node);
77
1/2
✓ Branch 1 taken 342 times.
✗ Branch 2 not taken.
342 return nullptr;
78 }
79
80 121 std::any TypeChecker::visitEnumDef(EnumDefNode *node) {
81
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 83 times.
121 if (typeCheckerMode == TC_MODE_PRE)
82 38 return visitEnumDefPrepare(node);
83
1/2
✓ Branch 1 taken 83 times.
✗ Branch 2 not taken.
83 return nullptr;
84 }
85
86 5544 std::any TypeChecker::visitGenericTypeDef(GenericTypeDefNode *node) {
87
2/2
✓ Branch 0 taken 722 times.
✓ Branch 1 taken 4822 times.
5544 if (typeCheckerMode == TC_MODE_PRE)
88 722 return visitGenericTypeDefPrepare(node);
89
1/2
✓ Branch 1 taken 4822 times.
✗ Branch 2 not taken.
4822 return nullptr;
90 }
91
92 112 std::any TypeChecker::visitAliasDef(AliasDefNode *node) {
93
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 82 times.
112 if (typeCheckerMode == TC_MODE_PRE)
94 30 return visitAliasDefPrepare(node);
95
1/2
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
82 return nullptr;
96 }
97
98 4635 std::any TypeChecker::visitGlobalVarDef(GlobalVarDefNode *node) {
99
2/2
✓ Branch 0 taken 734 times.
✓ Branch 1 taken 3901 times.
4635 if (typeCheckerMode == TC_MODE_PRE)
100 734 return visitGlobalVarDefPrepare(node);
101
1/2
✓ Branch 1 taken 3901 times.
✗ Branch 2 not taken.
3901 return nullptr;
102 }
103
104 4461 std::any TypeChecker::visitExtDecl(ExtDeclNode *node) {
105
2/2
✓ Branch 0 taken 701 times.
✓ Branch 1 taken 3760 times.
4461 if (typeCheckerMode == TC_MODE_PRE)
106 701 return visitExtDeclPrepare(node);
107
1/2
✓ Branch 1 taken 3760 times.
✗ Branch 2 not taken.
3760 return nullptr;
108 }
109
110 1419 std::any TypeChecker::visitImportDef(ImportDefNode *node) {
111
2/2
✓ Branch 0 taken 361 times.
✓ Branch 1 taken 1058 times.
1419 if (typeCheckerMode == TC_MODE_PRE)
112 361 return visitImportDefPrepare(node);
113
1/2
✓ Branch 1 taken 1058 times.
✗ Branch 2 not taken.
1058 return nullptr;
114 }
115
116 1661 std::any TypeChecker::visitUnsafeBlock(UnsafeBlockNode *node) {
117 // Change to unsafe block body scope
118
2/4
✓ Branch 1 taken 1661 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1661 times.
✗ Branch 5 not taken.
1661 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::UNSAFE_BODY);
119
120 // Visit body
121
1/2
✓ Branch 1 taken 1661 times.
✗ Branch 2 not taken.
1661 visit(node->body);
122
123
1/2
✓ Branch 1 taken 1661 times.
✗ Branch 2 not taken.
3322 return nullptr;
124 1661 }
125
126 1049 std::any TypeChecker::visitForLoop(ForLoopNode *node) {
127 // Change to for body scope
128
2/4
✓ Branch 1 taken 1049 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1049 times.
✗ Branch 5 not taken.
1049 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::FOR_BODY);
129
130 // Visit loop variable declaration
131
1/2
✓ Branch 1 taken 1049 times.
✗ Branch 2 not taken.
1049 visit(node->initDecl);
132
133 // Visit condition
134
2/4
✓ Branch 1 taken 1049 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1049 times.
✗ Branch 5 not taken.
1049 const QualType conditionType = std::any_cast<ExprResult>(visit(node->condAssign)).type;
135
2/6
✓ Branch 1 taken 1049 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1049 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
1049 HANDLE_UNRESOLVED_TYPE_PTR(conditionType)
136 // Check if condition evaluates to bool
137
3/4
✓ Branch 1 taken 1049 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1048 times.
1049 if (!conditionType.is(TY_BOOL))
138
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node->condAssign, CONDITION_MUST_BE_BOOL, "For loop condition must be of type bool")
139
140 // Visit incrementer
141
1/2
✓ Branch 1 taken 1048 times.
✗ Branch 2 not taken.
1048 visit(node->incAssign);
142
143 // Visit body
144
1/2
✓ Branch 1 taken 1048 times.
✗ Branch 2 not taken.
1048 visit(node->body);
145
146
1/2
✓ Branch 1 taken 1048 times.
✗ Branch 2 not taken.
1048 return nullptr;
147 1049 }
148
149 91 std::any TypeChecker::visitForeachLoop(ForeachLoopNode *node) {
150 // Visit iterator assignment
151 91 AssignExprNode *iteratorNode = node->iteratorAssign;
152
2/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 91 times.
✗ Branch 5 not taken.
91 QualType iteratorOrIterableType = std::any_cast<ExprResult>(visit(iteratorNode)).type;
153
2/6
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
91 HANDLE_UNRESOLVED_TYPE_PTR(iteratorOrIterableType)
154
1/2
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
91 iteratorOrIterableType = iteratorOrIterableType.removeReferenceWrapper();
155
156 // Retrieve iterator type
157 91 QualType iteratorType = iteratorOrIterableType;
158
159
3/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 72 times.
✓ Branch 4 taken 19 times.
91 if (iteratorOrIterableType.isIterable(node)) {
160 72 const QualType &iterableType = iteratorOrIterableType;
161
3/4
✓ Branch 1 taken 72 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 64 times.
72 if (iteratorOrIterableType.isArray()) { // Array
162
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
16 const NameRegistryEntry *nameRegistryEntry = sourceFile->getNameRegistryEntry(ARRAY_ITERATOR_NAME);
163
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
8 if (!nameRegistryEntry) {
164
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 softError(node, UNKNOWN_DATATYPE, "Forgot to import \"std/iterator/array-iterator\"?");
165
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return nullptr;
166 }
167 7 nameRegistryEntry->targetEntry->used = nameRegistryEntry->importEntry->used = true;
168 7 Scope *matchScope = nameRegistryEntry->targetScope->parent;
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 assert(matchScope->type == ScopeType::GLOBAL);
170
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 QualType unsignedLongType(TY_LONG);
171
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 unsignedLongType.makeUnsigned(true);
172
1/2
✓ Branch 3 taken 7 times.
✗ Branch 4 not taken.
14 const ArgList argTypes = {Arg(iterableType, false), Arg(unsignedLongType, false)};
173
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 const QualType thisType(TY_DYN);
174
2/4
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
21 node->getIteratorFct = FunctionManager::match(this, matchScope, "iterate", thisType, argTypes, {}, true, iteratorNode);
175 7 } else { // Struct, implementing Iterator interface
176
1/2
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
64 Scope *matchScope = iterableType.getBodyScope();
177
2/4
✓ Branch 3 taken 64 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 64 times.
✗ Branch 7 not taken.
192 node->getIteratorFct = FunctionManager::match(this, matchScope, "getIterator", iterableType, {}, {}, true, iteratorNode);
178 }
179
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 70 times.
71 if (node->getIteratorFct == nullptr)
180
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
3 throw SemanticError(iteratorNode, INVALID_ITERATOR, "No getIterator() function found for the given iterable type");
181
182 70 iteratorType = QualType(node->getIteratorFct->returnType);
183 // Create anonymous entry for the iterator
184
1/2
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
70 currentScope->symbolTable.insertAnonymous(iteratorType, iteratorNode);
185 }
186
187 // Change to foreach body scope
188
2/4
✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 89 times.
✗ Branch 5 not taken.
89 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::FOREACH_BODY);
189
190 // Check iterator type
191
3/4
✓ Branch 1 taken 89 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 88 times.
89 if (!iteratorType.isIterator(node)) {
192 const std::string errMsg =
193 "Can only iterate over arrays or data structures, inheriting from IIterator or IIterable. You provided " +
194
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 iteratorType.getName(false);
195
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 softError(node->iteratorAssign, OPERATOR_WRONG_DATA_TYPE, errMsg);
196
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return nullptr;
197 1 }
198
1/2
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
88 const QualTypeList &iteratorTemplateTypes = iteratorType.getTemplateTypes();
199
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 87 times.
88 if (iteratorTemplateTypes.empty())
200
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node->iteratorAssign, INVALID_ITERATOR,
201 "Iterator has no generic arguments so that the item type could not be inferred")
202
203 87 const bool hasIdx = node->idxVarDecl;
204
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 81 times.
87 if (hasIdx) {
205 // Visit index declaration or assignment
206
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 auto indexType = std::any_cast<QualType>(visit(node->idxVarDecl));
207
2/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
6 HANDLE_UNRESOLVED_TYPE_PTR(indexType)
208 // Check if index type is int
209
3/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 5 times.
6 if (!indexType.is(TY_LONG))
210
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(node->idxVarDecl, FOREACH_IDX_NOT_LONG,
211 "Index in foreach loop must be of type long. You provided " + indexType.getName(false))
212 }
213
214 // Retrieve .get(), .getIdx(), .isValid() and .next() functions
215
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
86 Scope *matchScope = iteratorType.getBodyScope();
216 86 QualType iteratorItemType;
217
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 81 times.
86 if (hasIdx) {
218
2/4
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
15 node->getIdxFct = FunctionManager::match(this, matchScope, "getIdx", iteratorType, {}, {}, false, node);
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 assert(node->getIdxFct != nullptr);
220
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 iteratorItemType = node->getIdxFct->returnType.getTemplateTypes().back();
221 } else {
222
2/4
✓ Branch 3 taken 81 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 81 times.
✗ Branch 7 not taken.
243 node->getFct = FunctionManager::match(this, matchScope, "get", iteratorType, {}, {}, false, node);
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 assert(node->getFct != nullptr);
224 81 iteratorItemType = node->getFct->returnType;
225 }
226
2/4
✓ Branch 3 taken 86 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 86 times.
✗ Branch 7 not taken.
258 node->isValidFct = FunctionManager::match(this, matchScope, "isValid", iteratorType, {}, {}, false, node);
227
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 assert(node->isValidFct != nullptr);
228
2/4
✓ Branch 3 taken 86 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 86 times.
✗ Branch 7 not taken.
258 node->nextFct = FunctionManager::match(this, matchScope, "next", iteratorType, {}, {}, false, node);
229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 assert(node->nextFct != nullptr);
230
231 // Retrieve item variable entry
232
1/2
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
86 SymbolTableEntry *itemVarSymbol = currentScope->lookupStrict(node->itemVarDecl->varName);
233
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
86 assert(itemVarSymbol != nullptr);
234
235 // Check type of the item
236
2/4
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 5 not taken.
86 auto itemType = std::any_cast<QualType>(visit(node->itemVarDecl));
237
2/6
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
86 HANDLE_UNRESOLVED_TYPE_PTR(itemType)
238
3/4
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 82 times.
86 if (itemType.is(TY_DYN)) { // Perform type inference
239 // Update evaluated symbol type of the declaration data type
240
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 node->itemVarDecl->dataType->setEvaluatedSymbolType(iteratorItemType, manIdx);
241 // Update item type
242 4 itemType = iteratorItemType;
243 } else {
244 // Check item type
245 82 const ExprResult itemResult = {itemType, itemVarSymbol};
246 82 const ExprResult iteratorItemResult = {iteratorItemType, nullptr /* always a temporary */};
247
2/2
✓ Branch 1 taken 81 times.
✓ Branch 2 taken 1 times.
82 (void)opRuleManager.getAssignResultType(node->itemVarDecl, itemResult, iteratorItemResult, true, false, ERROR_FOREACH_ITEM);
248 }
249
250 // Update type of item
251
1/2
✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
85 itemVarSymbol->updateType(itemType, true);
252
253 // Visit body
254
1/2
✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
85 visit(node->body);
255
256
1/2
✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
85 return nullptr;
257 89 }
258
259 468 std::any TypeChecker::visitWhileLoop(WhileLoopNode *node) {
260 // Change to while body scope
261
2/4
✓ Branch 1 taken 468 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 468 times.
✗ Branch 5 not taken.
468 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::WHILE_BODY);
262
263 // Visit condition
264
3/4
✓ Branch 1 taken 467 times.
✓ Branch 2 taken 1 times.
✓ Branch 4 taken 467 times.
✗ Branch 5 not taken.
468 const QualType conditionType = std::any_cast<ExprResult>(visit(node->condition)).type;
265
2/6
✓ Branch 1 taken 467 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 467 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
467 HANDLE_UNRESOLVED_TYPE_PTR(conditionType)
266 // Check if condition evaluates to bool
267
3/4
✓ Branch 1 taken 467 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 466 times.
467 if (!conditionType.is(TY_BOOL))
268
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node->condition, CONDITION_MUST_BE_BOOL, "While loop condition must be of type bool")
269
270 // Visit body
271
1/2
✓ Branch 1 taken 466 times.
✗ Branch 2 not taken.
466 visit(node->body);
272
273
1/2
✓ Branch 1 taken 466 times.
✗ Branch 2 not taken.
466 return nullptr;
274 468 }
275
276 9 std::any TypeChecker::visitDoWhileLoop(DoWhileLoopNode *node) {
277 // Change to while body scope
278
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
9 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::WHILE_BODY);
279
280 // Visit body
281
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 visit(node->body);
282
283 // Visit condition
284
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
9 const QualType conditionType = std::any_cast<ExprResult>(visit(node->condition)).type;
285
2/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
9 HANDLE_UNRESOLVED_TYPE_PTR(conditionType)
286 // Check if condition evaluates to bool
287
3/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 8 times.
9 if (!conditionType.is(TY_BOOL))
288
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node->condition, CONDITION_MUST_BE_BOOL, "Do-While loop condition must be of type bool")
289
290
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 return nullptr;
291 9 }
292
293 3030 std::any TypeChecker::visitIfStmt(IfStmtNode *node) {
294 // Change to then body scope
295
2/4
✓ Branch 1 taken 3030 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3030 times.
✗ Branch 5 not taken.
3030 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::IF_ELSE_BODY);
296
297 // Visit condition
298
3/4
✓ Branch 1 taken 3028 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 3028 times.
✗ Branch 5 not taken.
3030 const QualType conditionType = std::any_cast<ExprResult>(visit(node->condition)).type;
299
4/6
✓ Branch 1 taken 3028 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3027 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
3028 HANDLE_UNRESOLVED_TYPE_PTR(conditionType)
300 // Check if condition evaluates to bool
301
3/4
✓ Branch 1 taken 3027 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3025 times.
3027 if (!conditionType.is(TY_BOOL))
302
5/10
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
6 SOFT_ERROR_ER(node->condition, CONDITION_MUST_BE_BOOL, "If condition must be of type bool")
303
304 // Warning for bool assignment
305
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3024 times.
3025 if (node->condition->op == AssignExprNode::OP_ASSIGN)
306
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 sourceFile->compilerOutput.warnings.emplace_back(node->condition->codeLoc, BOOL_ASSIGN_AS_CONDITION,
307 "If you want to compare the values, use '=='");
308
309 // Visit body
310
1/2
✓ Branch 1 taken 3025 times.
✗ Branch 2 not taken.
3025 visit(node->thenBody);
311
312 // Leave then body scope
313
1/2
✓ Branch 1 taken 3025 times.
✗ Branch 2 not taken.
3025 scopeHandle.leaveScopeEarly();
314
315 // Visit else statement if existing
316
2/2
✓ Branch 0 taken 141 times.
✓ Branch 1 taken 2884 times.
3025 if (node->elseStmt)
317
1/2
✓ Branch 1 taken 141 times.
✗ Branch 2 not taken.
141 visit(node->elseStmt);
318
319
1/2
✓ Branch 1 taken 3025 times.
✗ Branch 2 not taken.
3025 return nullptr;
320 3030 }
321
322 141 std::any TypeChecker::visitElseStmt(ElseStmtNode *node) {
323 // Visit if statement in the case of an else if branch
324
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 99 times.
141 if (node->isElseIf) {
325
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 visit(node->ifStmt);
326
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 return nullptr;
327 }
328
329 // Change to else body scope
330
2/4
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 99 times.
✗ Branch 5 not taken.
99 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::IF_ELSE_BODY);
331
332 // Visit body
333
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 visit(node->body);
334
335
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 return nullptr;
336 99 }
337
338 8 std::any TypeChecker::visitSwitchStmt(SwitchStmtNode *node) {
339 // Check expression type
340
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 const QualType exprType = std::any_cast<ExprResult>(visit(node->assignExpr)).type;
341
2/6
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8 HANDLE_UNRESOLVED_TYPE_PTR(exprType)
342
3/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 7 times.
8 if (!exprType.isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_CHAR, TY_BOOL}))
343
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node->assignExpr, SWITCH_EXPR_MUST_BE_PRIMITIVE,
344 "Switch expression must be of int, short, long, byte, char or bool type")
345
346 // Visit children
347
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 visitChildren(node);
348
349 // Check if case constant types match switch expression type
350
2/2
✓ Branch 5 taken 28 times.
✓ Branch 6 taken 5 times.
33 for (const CaseBranchNode *caseBranchNode : node->caseBranches)
351
2/2
✓ Branch 5 taken 28 times.
✓ Branch 6 taken 26 times.
54 for (CaseConstantNode *constantNode : caseBranchNode->caseConstants) {
352
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 const QualType constantType = std::any_cast<ExprResult>(visit(constantNode)).type;
353
3/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 26 times.
28 if (!constantType.matches(exprType, false, true, true))
354
5/10
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
6 SOFT_ERROR_ER(constantNode, SWITCH_CASE_TYPE_MISMATCH, "Case value type does not match the switch expression type")
355 }
356
357
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 return nullptr;
358 }
359
360 28 std::any TypeChecker::visitCaseBranch(CaseBranchNode *node) {
361 // Change to case body scope
362
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::CASE_BODY);
363
364 // Visit constant list
365
2/2
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 28 times.
56 for (CaseConstantNode *constant : node->caseConstants)
366
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 visit(constant);
367
368 // Visit body
369
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 visit(node->body);
370
371
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
56 return nullptr;
372 28 }
373
374 3 std::any TypeChecker::visitDefaultBranch(DefaultBranchNode *node) {
375 // Change to default body scope
376
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::DEFAULT_BODY);
377
378 // Visit body
379
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 visit(node->body);
380
381
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 return nullptr;
382 3 }
383
384 13 std::any TypeChecker::visitAnonymousBlockStmt(AnonymousBlockStmtNode *node) {
385 // Change to anonymous scope body scope
386
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 ScopeHandle scopeHandle(this, node->getScopeId(), ScopeType::ANONYMOUS_BLOCK_BODY);
387
388 // Visit body
389
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 visit(node->body);
390
391
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
26 return nullptr;
392 13 }
393
394 13253 std::any TypeChecker::visitStmtLst(StmtLstNode *node) {
395 // Visit nodes in this scope
396
2/2
✓ Branch 5 taken 26430 times.
✓ Branch 6 taken 13222 times.
39652 for (ASTNode *stmt : node->children) {
397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26430 times.
26430 if (!stmt)
398 continue;
399 // Print warning if statement is unreachable
400
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 26425 times.
26430 if (stmt->unreachable) {
401
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 warnings.emplace_back(stmt->codeLoc, UNREACHABLE_CODE, "This statement is unreachable");
402 5 continue;
403 }
404 // Visit the statement
405
2/2
✓ Branch 1 taken 26394 times.
✓ Branch 2 taken 31 times.
26425 visit(stmt);
406 }
407
408 // Do cleanup of this scope, e.g. dtor calls for struct instances
409 13222 doScopeCleanup(node);
410
411
1/2
✓ Branch 1 taken 13222 times.
✗ Branch 2 not taken.
13222 return nullptr;
412 }
413
414 9504 std::any TypeChecker::visitParamLst(ParamLstNode *node) {
415 9504 NamedParamList namedParams;
416 9504 bool metOptional = false;
417
418
2/2
✓ Branch 5 taken 15064 times.
✓ Branch 6 taken 9504 times.
24568 for (DeclStmtNode *param : node->params) {
419 // Visit param
420
2/4
✓ Branch 1 taken 15064 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15064 times.
✗ Branch 5 not taken.
15064 const auto paramType = std::any_cast<QualType>(visit(param));
421
3/4
✓ Branch 1 taken 15064 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 15062 times.
15064 if (paramType.is(TY_UNRESOLVED))
422 11 continue;
423
424 // Check if the type could be inferred. Dyn without a default value is forbidden
425
3/4
✓ Branch 1 taken 15062 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 15059 times.
15062 if (paramType.is(TY_DYN)) {
426
3/6
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
3 softError(node, FCT_PARAM_IS_TYPE_DYN, "Type of parameter '" + param->varName + "' is invalid");
427 3 continue;
428 }
429
430 // Ensure that no optional param comes after a mandatory param
431
2/2
✓ Branch 0 taken 1859 times.
✓ Branch 1 taken 13200 times.
15059 if (param->hasAssignment) {
432 1859 metOptional = true;
433
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13194 times.
13200 } else if (metOptional) {
434
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 softError(param, INVALID_PARAM_ORDER, "Mandatory parameters must go before any optional parameters");
435 6 continue;
436 }
437
438 // Add parameter to named param list
439
1/2
✓ Branch 2 taken 15053 times.
✗ Branch 3 not taken.
15053 namedParams.push_back({param->varName.c_str(), paramType, metOptional});
440 }
441
442
1/2
✓ Branch 1 taken 9504 times.
✗ Branch 2 not taken.
19008 return namedParams;
443 9504 }
444
445 1182 std::any TypeChecker::visitField(FieldNode *node) {
446
2/4
✓ Branch 1 taken 1182 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1182 times.
✗ Branch 5 not taken.
1182 auto fieldType = std::any_cast<QualType>(visit(node->dataType));
447
5/8
✓ Branch 1 taken 1182 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1181 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
1182 HANDLE_UNRESOLVED_TYPE_QT(fieldType)
448
449
2/2
✓ Branch 0 taken 151 times.
✓ Branch 1 taken 1030 times.
1181 if (TernaryExprNode *defaultValueNode = node->defaultValue) {
450
2/4
✓ Branch 1 taken 151 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 151 times.
✗ Branch 5 not taken.
151 const QualType defaultValueType = std::any_cast<ExprResult>(visit(defaultValueNode)).type;
451
2/8
✓ Branch 1 taken 151 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 151 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
151 HANDLE_UNRESOLVED_TYPE_QT(defaultValueType)
452
3/4
✓ Branch 1 taken 151 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 150 times.
151 if (!fieldType.matches(defaultValueType, false, true, true))
453
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
3 SOFT_ERROR_QT(node, FIELD_TYPE_NOT_MATCHING, "Type of the default values does not match the field type")
454 }
455
456
1/2
✓ Branch 1 taken 1180 times.
✗ Branch 2 not taken.
1180 return fieldType;
457 }
458
459 172 std::any TypeChecker::visitSignature(SignatureNode *node) {
460 172 const bool isFunction = node->signatureType == SignatureNode::TYPE_FUNCTION;
461
462 // Retrieve function template types
463 172 std::vector<GenericType> usedGenericTypes;
464
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 81 times.
172 if (node->hasTemplateTypes) {
465
2/2
✓ Branch 5 taken 91 times.
✓ Branch 6 taken 90 times.
181 for (DataTypeNode *dataType : node->templateTypeLst->dataTypes) {
466 // Visit template type
467
2/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 91 times.
✗ Branch 5 not taken.
91 auto templateType = std::any_cast<QualType>(visit(dataType));
468
2/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 91 times.
91 if (templateType.is(TY_UNRESOLVED))
469 return static_cast<std::vector<Function *> *>(nullptr);
470 // Check if it is a generic type
471
3/4
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 90 times.
91 if (!templateType.is(TY_GENERIC)) {
472
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 softError(dataType, EXPECTED_GENERIC_TYPE, "A template list can only contain generic types");
473
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return static_cast<std::vector<Function *> *>(nullptr);
474 }
475 // Convert generic symbol type to generic type
476
2/4
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 90 times.
✗ Branch 5 not taken.
90 const GenericType *genericType = rootScope->lookupGenericType(templateType.getSubType());
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 assert(genericType != nullptr);
478
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
90 usedGenericTypes.push_back(*genericType);
479 }
480 }
481
482 // Visit return type
483
1/2
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
171 QualType returnType(TY_DYN);
484
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 39 times.
171 if (isFunction) {
485
2/4
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 132 times.
✗ Branch 5 not taken.
132 returnType = std::any_cast<QualType>(visit(node->returnType));
486
2/4
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 132 times.
132 if (returnType.is(TY_UNRESOLVED))
487 return static_cast<std::vector<Function *> *>(nullptr);
488
489
3/4
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 131 times.
132 if (!returnType.isCoveredByGenericTypeList(usedGenericTypes))
490
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 softError(node->returnType, GENERIC_TYPE_NOT_IN_TEMPLATE,
491 "Generic return type not included in the template type list of the function");
492 }
493
494 // Visit params
495 171 QualTypeList paramTypes;
496 171 ParamList paramList;
497
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 159 times.
171 if (node->hasParams) {
498
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 paramList.reserve(node->paramTypeLst->dataTypes.size());
499
2/2
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 12 times.
26 for (DataTypeNode *param : node->paramTypeLst->dataTypes) {
500
2/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 14 times.
✗ Branch 5 not taken.
14 auto paramType = std::any_cast<QualType>(visit(param));
501
2/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 14 times.
14 if (paramType.is(TY_UNRESOLVED))
502 return static_cast<std::vector<Function *> *>(nullptr);
503
504 // Check if the type is present in the template for generic types
505
3/4
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 12 times.
14 if (!paramType.isCoveredByGenericTypeList(usedGenericTypes)) {
506
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 softError(node->paramTypeLst, GENERIC_TYPE_NOT_IN_TEMPLATE,
507 "Generic param type not included in the template type list of the function");
508 2 continue;
509 }
510
511
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 paramTypes.push_back(paramType);
512
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 paramList.push_back({paramType, false});
513 }
514 }
515
516 // Build signature object
517
4/8
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 171 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 171 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 171 times.
✗ Branch 11 not taken.
171 const Function signature(node->methodName, nullptr, QualType(TY_DYN), returnType, paramList, usedGenericTypes, node);
518
519 // Add signature to current scope
520
1/2
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
171 Function *manifestation = FunctionManager::insert(currentScope, signature, &node->signatureManifestations);
521 171 manifestation->entry = node->entry;
522 171 manifestation->used = true;
523
524 // Prepare signature type
525
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 39 times.
171 const SuperType superType = isFunction ? TY_FUNCTION : TY_PROCEDURE;
526
2/4
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 171 times.
✗ Branch 5 not taken.
171 QualType signatureType = QualType(superType).getWithFunctionParamAndReturnTypes(returnType, paramTypes);
527 171 signatureType.setSpecifiers(node->signatureSpecifiers);
528
529 // Set entry to signature type
530
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 assert(node->entry != nullptr);
531
1/2
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
171 node->entry->updateType(signatureType, false);
532 171 node->entry->used = true;
533
534
1/2
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
171 return &node->signatureManifestations;
535 172 }
536
537 20795 std::any TypeChecker::visitDeclStmt(DeclStmtNode *node) {
538 // Retrieve entry of the lhs variable
539
1/2
✓ Branch 1 taken 20795 times.
✗ Branch 2 not taken.
20795 SymbolTableEntry *localVarEntry = currentScope->lookupStrict(node->varName);
540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20795 times.
20795 assert(localVarEntry != nullptr);
541
542 20795 QualType localVarType;
543
2/2
✓ Branch 0 taken 7384 times.
✓ Branch 1 taken 13411 times.
20795 if (node->hasAssignment) {
544 // Visit the right side
545
3/4
✓ Branch 1 taken 7379 times.
✓ Branch 2 taken 5 times.
✓ Branch 4 taken 7379 times.
✗ Branch 5 not taken.
7384 auto rhs = std::any_cast<ExprResult>(visit(node->assignExpr));
546 7379 auto [rhsTy, rhsEntry] = rhs;
547
548 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it
549
4/4
✓ Branch 0 taken 1617 times.
✓ Branch 1 taken 5762 times.
✓ Branch 2 taken 803 times.
✓ Branch 3 taken 814 times.
7379 if (rhsEntry != nullptr && rhsEntry->anonymous) {
550
1/2
✓ Branch 1 taken 803 times.
✗ Branch 2 not taken.
803 currentScope->symbolTable.deleteAnonymous(rhsEntry->name);
551 803 rhs.entry = rhsEntry = nullptr;
552 }
553
554 // Visit data type
555
3/4
✓ Branch 1 taken 7376 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 7376 times.
✗ Branch 5 not taken.
7379 localVarType = std::any_cast<QualType>(visit(node->dataType));
556
557 // Infer the type left to right if the right side is an empty array initialization
558
3/4
✓ Branch 1 taken 7376 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 7374 times.
7376 if (rhsTy.isArrayOf(TY_DYN))
559 2 rhsTy = QualType(localVarType);
560
561 // Check if type has to be inferred or both types are fixed
562
8/10
✓ Branch 1 taken 7376 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7372 times.
✓ Branch 4 taken 4 times.
✓ Branch 6 taken 7372 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7353 times.
✓ Branch 9 taken 19 times.
✓ Branch 10 taken 7353 times.
✓ Branch 11 taken 23 times.
7376 if (!localVarType.is(TY_UNRESOLVED) && !rhsTy.is(TY_UNRESOLVED)) {
563 7353 const ExprResult lhsResult = {localVarType, localVarEntry};
564
2/2
✓ Branch 1 taken 7343 times.
✓ Branch 2 taken 10 times.
7353 localVarType = opRuleManager.getAssignResultType(node, lhsResult, rhs, true);
565
566 // Call copy ctor if required
567
9/10
✓ Branch 1 taken 7343 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 836 times.
✓ Branch 4 taken 6507 times.
✓ Branch 5 taken 832 times.
✓ Branch 6 taken 4 times.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 829 times.
✓ Branch 10 taken 3 times.
✓ Branch 11 taken 7340 times.
7343 if (localVarType.is(TY_STRUCT) && !node->isFctParam && !rhs.isTemporary()) {
568
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 Scope *matchScope = localVarType.getBodyScope();
569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(matchScope != nullptr);
570 // Check if we have a no-args ctor to call
571 3 const QualType &thisType = localVarType;
572
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
6 const ArgList args = {{thisType.toConstRef(node), false}};
573
2/4
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
9 node->calledCopyCtor = FunctionManager::match(this, matchScope, CTOR_FUNCTION_NAME, thisType, args, {}, true, node);
574 3 }
575
576 // If this is a struct type, check if the type is known. If not, error out
577
8/14
✓ Branch 1 taken 7343 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 968 times.
✓ Branch 4 taken 6375 times.
✓ Branch 6 taken 968 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 968 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 968 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 968 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 7343 times.
7343 if (localVarType.isBase(TY_STRUCT) && !sourceFile->getNameRegistryEntry(localVarType.getBase().getSubType())) {
578 const std::string structName = localVarType.getBase().getSubType();
579 softError(node->dataType, UNKNOWN_DATATYPE, "Unknown struct type '" + structName + "'. Forgot to import?");
580 localVarType = QualType(TY_UNRESOLVED);
581 }
582 } else {
583
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 localVarType = QualType(TY_UNRESOLVED);
584 }
585 } else {
586 // Visit data type
587
2/4
✓ Branch 1 taken 13411 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13411 times.
✗ Branch 5 not taken.
13411 localVarType = std::any_cast<QualType>(visit(node->dataType));
588
589 // References with no initialization are illegal
590
9/10
✓ Branch 1 taken 13411 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4644 times.
✓ Branch 4 taken 8767 times.
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 4590 times.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 53 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 13410 times.
13411 if (localVarType.isRef() && !node->isFctParam && !node->isForEachItem)
591
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 softError(node, REFERENCE_WITHOUT_INITIALIZER, "References must always be initialized directly");
592
593 // If this is a struct, check for the default ctor
594
9/10
✓ Branch 1 taken 13411 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 332 times.
✓ Branch 4 taken 13079 times.
✓ Branch 5 taken 57 times.
✓ Branch 6 taken 275 times.
✓ Branch 7 taken 49 times.
✓ Branch 8 taken 8 times.
✓ Branch 9 taken 49 times.
✓ Branch 10 taken 13362 times.
13411 if (localVarType.is(TY_STRUCT) && !node->isFctParam && !node->isForEachItem) {
595
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 Scope *matchScope = localVarType.getBodyScope();
596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 assert(matchScope != nullptr);
597 // Check if we are required to call a ctor
598
2/4
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
49 auto structDeclNode = spice_pointer_cast<StructDefNode *>(localVarType.getStruct(node)->declNode);
599
5/6
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 48 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 17 times.
✓ Branch 6 taken 31 times.
49 node->isCtorCallRequired = matchScope->hasRefFields() || structDeclNode->emitVTable;
600 // Check if we have a no-args ctor to call
601
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 const std::string &structName = localVarType.getSubType();
602 49 const QualType &thisType = localVarType;
603
2/4
✓ Branch 3 taken 49 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 49 times.
✗ Branch 7 not taken.
147 node->calledInitCtor = FunctionManager::match(this, matchScope, CTOR_FUNCTION_NAME, thisType, {}, {}, false, node);
604
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 12 times.
49 if (!node->calledInitCtor && node->isCtorCallRequired)
605
5/10
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
2 SOFT_ERROR_QT(node, MISSING_NO_ARGS_CTOR, "Struct '" + structName + "' misses a no-args constructor")
606 }
607 }
608
609 // Update the type of the variable
610
1/2
✓ Branch 1 taken 20775 times.
✗ Branch 2 not taken.
20775 localVarEntry->updateType(localVarType, true);
611
1/2
✓ Branch 1 taken 20775 times.
✗ Branch 2 not taken.
20775 node->entries.at(manIdx) = localVarEntry;
612
613 // Update the state of the variable
614
1/2
✓ Branch 1 taken 20775 times.
✗ Branch 2 not taken.
20775 localVarEntry->updateState(INITIALIZED, node, true);
615
616
2/4
✓ Branch 1 taken 20775 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 20775 times.
✗ Branch 5 not taken.
20775 return node->setEvaluatedSymbolType(localVarType, manIdx);
617 }
618
619 56 std::any TypeChecker::visitCaseConstant(CaseConstantNode *node) {
620 // If we have a normal constant, we can take the symbol type from there
621
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 20 times.
56 if (node->constant)
622
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 return visit(node->constant);
623
624 // Check if a local or global variable can be found by searching for the name
625
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
20 if (node->identifierFragments.size() == 1)
626 4 node->enumItemEntry = currentScope->lookup(node->identifierFragments.back());
627
628 // If no local or global was found, search in the name registry
629
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
20 if (!node->enumItemEntry) {
630
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(node->fqIdentifier);
631
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!registryEntry)
632 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE, "The variable '" + node->fqIdentifier + "' could not be found")
633 9 node->enumItemEntry = registryEntry->targetEntry;
634 }
635
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 assert(node->enumItemEntry != nullptr);
636
637 // Check for the correct type
638
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (node->enumItemEntry->scope->type != ScopeType::ENUM)
639
5/10
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
6 SOFT_ERROR_ER(node, CASE_CONSTANT_NOT_ENUM, "Case constants must be of type enum")
640
641
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 const QualType varType = node->enumItemEntry->getQualType();
642
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
18 assert(varType.is(TY_INT));
643
2/4
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
18 return ExprResult{node->setEvaluatedSymbolType(varType, manIdx)};
644 }
645
646 5860 std::any TypeChecker::visitReturnStmt(ReturnStmtNode *node) {
647 // Retrieve return variable entry
648
1/2
✓ Branch 1 taken 5860 times.
✗ Branch 2 not taken.
17580 SymbolTableEntry *returnVar = currentScope->lookup(RETURN_VARIABLE_NAME);
649 5860 const bool isFunction = returnVar != nullptr;
650
4/6
✓ Branch 0 taken 5816 times.
✓ Branch 1 taken 44 times.
✓ Branch 3 taken 5816 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 44 times.
✗ Branch 7 not taken.
5860 const QualType returnType = isFunction ? returnVar->getQualType() : QualType(TY_DYN);
651
652 // Check if procedure with return value
653
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 5816 times.
5860 if (!isFunction) {
654
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 42 times.
44 if (node->hasReturnValue)
655
5/10
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
6 SOFT_ERROR_ER(node->assignExpr, RETURN_WITH_VALUE_IN_PROCEDURE, "Return with value in procedure is not allowed")
656
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 return nullptr;
657 }
658
659
7/8
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 5810 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 5814 times.
5816 if (!node->hasReturnValue && !returnVar->getLifecycle().isInitialized())
660
4/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
6 SOFT_ERROR_QT(node, RETURN_WITHOUT_VALUE_RESULT, "Return without value, but result variable is not initialized yet")
661
662
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5810 times.
5814 if (!node->hasReturnValue)
663
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 return nullptr;
664
665 // Visit right side
666
2/4
✓ Branch 1 taken 5810 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5810 times.
✗ Branch 5 not taken.
5810 auto rhs = std::any_cast<ExprResult>(visit(node->assignExpr));
667
2/8
✓ Branch 1 taken 5810 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5810 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
5810 HANDLE_UNRESOLVED_TYPE_QT(rhs.type)
668
669 // Check if types match
670 5810 const ExprResult returnResult = {returnType, returnVar};
671
2/2
✓ Branch 1 taken 5808 times.
✓ Branch 2 taken 2 times.
5810 (void)opRuleManager.getAssignResultType(node->assignExpr, returnResult, rhs, false, true, ERROR_MSG_RETURN);
672
673 // Manage dtor call
674
2/2
✓ Branch 0 taken 1575 times.
✓ Branch 1 taken 4233 times.
5808 if (rhs.entry != nullptr) {
675
2/2
✓ Branch 0 taken 622 times.
✓ Branch 1 taken 953 times.
1575 if (rhs.entry->anonymous) {
676 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it
677
1/2
✓ Branch 1 taken 622 times.
✗ Branch 2 not taken.
622 currentScope->symbolTable.deleteAnonymous(rhs.entry->name);
678 622 rhs.entry = nullptr;
679 } else {
680 // Otherwise omit the destructor call, because the caller destructs the value
681 953 rhs.entry->omitDtorCall = true;
682 }
683 }
684
685
2/4
✓ Branch 1 taken 5808 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5808 times.
✗ Branch 5 not taken.
5808 return node->setEvaluatedSymbolType(returnType, manIdx);
686 }
687
688 101 std::any TypeChecker::visitBreakStmt(BreakStmtNode *node) {
689 // Check if the stated number is valid
690
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 100 times.
101 if (node->breakTimes < 1)
691
5/10
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1 SOFT_ERROR_ER(node, INVALID_BREAK_NUMBER, "Break count must be >= 1, you provided " + std::to_string(node->breakTimes))
692
693 // Check if we can break this often
694 100 const unsigned int maxBreaks = currentScope->getLoopNestingDepth();
695
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 99 times.
100 if (static_cast<unsigned int>(node->breakTimes) > maxBreaks)
696
6/12
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
1 SOFT_ERROR_ER(node, INVALID_BREAK_NUMBER, "We can only break " + std::to_string(maxBreaks) + " time(s) here")
697
698
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 return nullptr;
699 }
700
701 335 std::any TypeChecker::visitContinueStmt(ContinueStmtNode *node) {
702 // Check if the stated number is valid
703
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 334 times.
335 if (node->continueTimes < 1)
704
5/10
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
1 SOFT_ERROR_ER(node, INVALID_CONTINUE_NUMBER,
705 "Continue count must be >= 1, you provided " + std::to_string(node->continueTimes))
706
707 // Check if we can continue this often
708 334 const unsigned int maxContinues = currentScope->getLoopNestingDepth();
709
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 333 times.
334 if (static_cast<unsigned int>(node->continueTimes) > maxContinues)
710
6/12
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 1 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 1 times.
✗ Branch 21 not taken.
1 SOFT_ERROR_ER(node, INVALID_CONTINUE_NUMBER, "We can only continue " + std::to_string(maxContinues) + " time(s) here")
711
712
1/2
✓ Branch 1 taken 333 times.
✗ Branch 2 not taken.
333 return nullptr;
713 }
714
715 6 std::any TypeChecker::visitFallthroughStmt(FallthroughStmtNode *node) {
716 // Check if we can do a fallthrough here
717
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (!currentScope->isInCaseBranch())
718
5/10
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
6 SOFT_ERROR_ER(node, FALLTHROUGH_NOT_ALLOWED, "Fallthrough is only allowed in case branches")
719
720
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 return nullptr;
721 }
722
723 657 std::any TypeChecker::visitAssertStmt(AssertStmtNode *node) {
724 // Visit condition
725
2/4
✓ Branch 1 taken 657 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 657 times.
✗ Branch 5 not taken.
657 const QualType conditionType = std::any_cast<ExprResult>(visit(node->assignExpr)).type;
726
2/10
✓ Branch 1 taken 657 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 657 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
657 HANDLE_UNRESOLVED_TYPE_ER(conditionType)
727
728 // Check if condition evaluates to bool
729
3/4
✓ Branch 1 taken 657 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 656 times.
657 if (!conditionType.is(TY_BOOL))
730
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node->assignExpr, ASSERTION_CONDITION_BOOL, "The asserted condition must be of type bool")
731
732
1/2
✓ Branch 1 taken 656 times.
✗ Branch 2 not taken.
656 return nullptr;
733 }
734
735 1184 std::any TypeChecker::visitBuiltinCall(BuiltinCallNode *node) {
736
2/2
✓ Branch 0 taken 651 times.
✓ Branch 1 taken 533 times.
1184 if (node->printfCall)
737 651 return visitPrintfCall(node->printfCall);
738
2/2
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 414 times.
533 if (node->sizeofCall)
739 119 return visitSizeofCall(node->sizeofCall);
740
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 403 times.
414 if (node->alignofCall)
741 11 return visitAlignofCall(node->alignofCall);
742
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 367 times.
403 if (node->lenCall)
743 36 return visitLenCall(node->lenCall);
744
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 1 times.
367 if (node->panicCall)
745 366 return visitPanicCall(node->panicCall);
746
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (node->sysCall)
747 1 return visitSysCall(node->sysCall);
748 assert_fail("Unknown builtin call");
749 return nullptr;
750 }
751
752 651 std::any TypeChecker::visitPrintfCall(PrintfCallNode *node) {
753 // Check if assignment types match placeholder types
754 651 size_t placeholderCount = 0;
755 651 size_t index = node->templatedString.find_first_of('%');
756
5/6
✓ Branch 0 taken 550 times.
✓ Branch 1 taken 629 times.
✓ Branch 3 taken 550 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 550 times.
✓ Branch 6 taken 629 times.
1179 while (index != std::string::npos && index != node->templatedString.size() - 1) {
757 // Check if there is another assignExpr
758
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 549 times.
550 if (node->args.size() <= placeholderCount)
759
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains more placeholders than arguments")
760
761 // Get next assignment
762
1/2
✓ Branch 1 taken 549 times.
✗ Branch 2 not taken.
549 AssignExprNode *assignment = node->args.at(placeholderCount);
763 // Visit assignment
764
2/4
✓ Branch 1 taken 549 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 549 times.
✗ Branch 5 not taken.
549 QualType argType = std::any_cast<ExprResult>(visit(assignment)).type;
765
6/10
✓ Branch 1 taken 549 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 534 times.
✓ Branch 6 taken 15 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 15 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 15 times.
✗ Branch 13 not taken.
549 HANDLE_UNRESOLVED_TYPE_ER(argType)
766
1/2
✓ Branch 1 taken 534 times.
✗ Branch 2 not taken.
534 argType = argType.removeReferenceWrapper();
767
768
6/8
✓ Branch 1 taken 534 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 292 times.
✓ Branch 5 taken 34 times.
✓ Branch 6 taken 188 times.
✓ Branch 7 taken 5 times.
✗ Branch 8 not taken.
534 switch (node->templatedString.at(index + 1)) {
769 15 case 'c': {
770
3/4
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 14 times.
15 if (!argType.is(TY_CHAR))
771
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, "The placeholder string expects char, but got " + argType.getName(false))
772 14 placeholderCount++;
773 14 break;
774 }
775 292 case 'd':
776 case 'i':
777 case 'l':
778 case 'o':
779 case 'u':
780 case 'x':
781 case 'X': {
782
3/4
✓ Branch 1 taken 292 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 290 times.
292 if (!argType.isOneOf({TY_INT, TY_SHORT, TY_LONG, TY_BYTE, TY_BOOL}))
783
6/12
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
2 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR,
784 "The placeholder string expects int, short, long, byte or bool, but got " + argType.getName(false))
785 290 placeholderCount++;
786 290 break;
787 }
788 34 case 'a':
789 case 'A':
790 case 'f':
791 case 'F':
792 case 'e':
793 case 'E':
794 case 'g':
795 case 'G': {
796
3/4
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 33 times.
34 if (!argType.is(TY_DOUBLE))
797
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR, "The placeholder string expects double, but got " + argType.getName(false))
798 33 placeholderCount++;
799 33 break;
800 }
801 188 case 's': {
802
13/18
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
✓ Branch 4 taken 159 times.
✓ Branch 6 taken 29 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 27 times.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 1 times.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 20 taken 1 times.
✓ Branch 21 taken 187 times.
188 if (!argType.is(TY_STRING) && !argType.isStringObj() && !argType.isPtrTo(TY_CHAR) && !argType.isArrayOf(TY_CHAR))
803
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR,
804 "The placeholder string expects string, String, char* or char[], but got " + argType.getName(false))
805 187 placeholderCount++;
806 187 break;
807 }
808 5 case 'p': {
809
9/14
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 4 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✓ Branch 16 taken 4 times.
5 if (!argType.isPtr() && !argType.isArray() && !argType.is(TY_STRING))
810
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(assignment, PRINTF_TYPE_ERROR,
811 "The placeholder string expects pointer, array or string, but got " + argType.getName(false))
812 4 placeholderCount++;
813 4 break;
814 }
815 default:
816 SOFT_ERROR_ER(node, PRINTF_TYPE_ERROR, "The placeholder string contains an invalid placeholder")
817 }
818 528 index = node->templatedString.find_first_of('%', index + 2); // We can also skip the following char
819 }
820
821 // Check if the number of placeholders matches the number of args
822
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 628 times.
629 if (placeholderCount < node->args.size())
823
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node, PRINTF_ARG_COUNT_ERROR, "The placeholder string contains less placeholders than arguments")
824
825
3/6
✓ Branch 1 taken 628 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 628 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 628 times.
✗ Branch 8 not taken.
628 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_INT), manIdx)};
826 }
827
828 119 std::any TypeChecker::visitSizeofCall(SizeofCallNode *node) {
829
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 17 times.
119 if (node->isType) { // Size of type
830
1/2
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
102 visit(node->dataType);
831 } else { // Size of value
832
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 visit(node->assignExpr);
833 }
834
835
3/6
✓ Branch 1 taken 119 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 119 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 119 times.
✗ Branch 8 not taken.
119 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)};
836 }
837
838 11 std::any TypeChecker::visitAlignofCall(AlignofCallNode *node) {
839
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (node->isType) { // Align of type
840
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 visit(node->dataType);
841 } else { // Align of value
842
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 visit(node->assignExpr);
843 }
844
845
3/6
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 11 times.
✗ Branch 8 not taken.
11 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)};
846 }
847
848 36 std::any TypeChecker::visitLenCall(LenCallNode *node) {
849
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
36 QualType argType = std::any_cast<ExprResult>(visit(node->assignExpr)).type;
850
2/10
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
36 HANDLE_UNRESOLVED_TYPE_ER(argType)
851
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 argType = argType.removeReferenceWrapper();
852
853 // Check if arg is of type array
854
8/10
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 12 times.
✓ Branch 6 taken 24 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 23 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 35 times.
36 if (!argType.isArray() && !argType.is(TY_STRING))
855
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node->assignExpr, EXPECTED_ARRAY_TYPE, "The len builtin can only work on arrays or strings")
856
857 // If we want to use the len builtin on a string, we need to import the string runtime module
858
7/10
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23 times.
✓ Branch 4 taken 12 times.
✓ Branch 6 taken 23 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 23 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 23 times.
✓ Branch 11 taken 12 times.
58 if (argType.is(TY_STRING) && !sourceFile->isStringRT())
859
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 sourceFile->requestRuntimeModule(STRING_RT);
860
861
3/6
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 35 times.
✗ Branch 8 not taken.
35 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)};
862 }
863
864 366 std::any TypeChecker::visitPanicCall(PanicCallNode *node) {
865
2/4
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 366 times.
✗ Branch 5 not taken.
366 QualType argType = std::any_cast<ExprResult>(visit(node->assignExpr)).type;
866
2/10
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 366 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
366 HANDLE_UNRESOLVED_TYPE_ER(argType)
867
1/2
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
366 argType = argType.removeReferenceWrapper();
868
869 // Check if arg is of type array
870
2/4
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 366 times.
366 if (!argType.isErrorObj())
871 SOFT_ERROR_ER(node->assignExpr, EXPECTED_ERROR_TYPE, "The panic builtin can only work with errors")
872
873
3/6
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 366 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 366 times.
✗ Branch 8 not taken.
366 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_DYN), manIdx)};
874 }
875
876 1 std::any TypeChecker::visitSysCall(SysCallNode *node) {
877 // Check if the syscall number if of type short
878
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
1 const QualType sysCallNumberType = std::any_cast<ExprResult>(visit(node->args.front())).type;
879
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (!sysCallNumberType.is(TY_SHORT))
880 SOFT_ERROR_ER(node->args.front(), INVALID_SYSCALL_NUMBER_TYPE, "Syscall number must be of type short")
881
882 // Check if the syscall number is out of range
883 // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/
884
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (node->hasCompileTimeValue()) {
885 const unsigned short sysCallNumber = node->getCompileTimeValue().shortValue;
886 if (sysCallNumber < 0 || sysCallNumber > 439)
887 SOFT_ERROR_ER(node, SYSCALL_NUMBER_OUT_OF_RANGE, "Only syscall numbers between 0 and 439 are supported")
888 }
889
890 // Check if too many syscall args are given
891 // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/
892
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (node->args.size() > 6)
893 SOFT_ERROR_ER(node->args.front(), TOO_MANY_SYSCALL_ARGS, "There are no syscalls that support more than 6 arguments")
894
895 // Visit children
896
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 for (size_t i = 1; i < node->args.size(); i++)
897
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 visit(node->args.at(i));
898
899
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx)};
900 }
901
902 48605 std::any TypeChecker::visitAssignExpr(AssignExprNode *node) {
903 // Check if ternary
904
2/2
✓ Branch 0 taken 43821 times.
✓ Branch 1 taken 4784 times.
48605 if (node->ternaryExpr) {
905
3/4
✓ Branch 1 taken 43806 times.
✓ Branch 2 taken 15 times.
✓ Branch 4 taken 43806 times.
✗ Branch 5 not taken.
43821 auto result = std::any_cast<ExprResult>(visit(node->ternaryExpr));
906
1/2
✓ Branch 1 taken 43806 times.
✗ Branch 2 not taken.
43806 node->setEvaluatedSymbolType(result.type, manIdx);
907
1/2
✓ Branch 1 taken 43806 times.
✗ Branch 2 not taken.
43806 return result;
908 }
909
910 // Check if assignment
911
1/2
✓ Branch 0 taken 4784 times.
✗ Branch 1 not taken.
4784 if (node->op != AssignExprNode::OP_NONE) {
912 // Visit the right side first
913
2/4
✓ Branch 1 taken 4784 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4784 times.
✗ Branch 5 not taken.
4784 auto rhs = std::any_cast<ExprResult>(visit(node->rhs));
914 4784 auto [rhsType, rhsEntry] = rhs;
915
6/10
✓ Branch 1 taken 4784 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 4783 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
4784 HANDLE_UNRESOLVED_TYPE_ER(rhsType)
916 // Then visit the left side
917
2/4
✓ Branch 1 taken 4783 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4783 times.
✗ Branch 5 not taken.
4783 auto lhs = std::any_cast<ExprResult>(visit(node->lhs));
918 4783 auto [lhsType, lhsVar] = lhs;
919
6/10
✓ Branch 1 taken 4783 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 4782 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
4783 HANDLE_UNRESOLVED_TYPE_ER(lhsType)
920
921 // Take a look at the operator
922
2/2
✓ Branch 0 taken 4251 times.
✓ Branch 1 taken 531 times.
4782 if (node->op == AssignExprNode::OP_ASSIGN) {
923
6/8
✓ Branch 1 taken 4251 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3481 times.
✓ Branch 4 taken 770 times.
✓ Branch 7 taken 3481 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1179 times.
✓ Branch 10 taken 2302 times.
4251 const bool isDecl = lhs.entry->isField() && !lhs.entry->getLifecycle().isInitialized();
924
2/2
✓ Branch 1 taken 4249 times.
✓ Branch 2 taken 2 times.
4251 rhsType = opRuleManager.getAssignResultType(node, lhs, rhs, isDecl);
925
926 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it
927
4/4
✓ Branch 0 taken 2048 times.
✓ Branch 1 taken 2201 times.
✓ Branch 2 taken 125 times.
✓ Branch 3 taken 1923 times.
4249 if (rhsEntry != nullptr && rhsEntry->anonymous) {
928
1/2
✓ Branch 1 taken 125 times.
✗ Branch 2 not taken.
125 currentScope->symbolTable.deleteAnonymous(rhsEntry->name);
929 125 rhsEntry = nullptr;
930 }
931
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 318 times.
531 } else if (node->op == AssignExprNode::OP_PLUS_EQUAL) {
932
1/2
✓ Branch 1 taken 213 times.
✗ Branch 2 not taken.
213 rhsType = opRuleManager.getPlusEqualResultType(node, lhs, rhs, 0).type;
933
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 291 times.
318 } else if (node->op == AssignExprNode::OP_MINUS_EQUAL) {
934
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 rhsType = opRuleManager.getMinusEqualResultType(node, lhs, rhs, 0).type;
935
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 276 times.
291 } else if (node->op == AssignExprNode::OP_MUL_EQUAL) {
936
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 rhsType = opRuleManager.getMulEqualResultType(node, lhs, rhs, 0).type;
937
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 241 times.
276 } else if (node->op == AssignExprNode::OP_DIV_EQUAL) {
938
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 rhsType = opRuleManager.getDivEqualResultType(node, lhs, rhs, 0).type;
939
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 236 times.
241 } else if (node->op == AssignExprNode::OP_REM_EQUAL) {
940
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 rhsType = OpRuleManager::getRemEqualResultType(node, lhs, rhs);
941
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 235 times.
236 } else if (node->op == AssignExprNode::OP_SHL_EQUAL) {
942
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 rhsType = OpRuleManager::getSHLEqualResultType(node, lhs, rhs);
943
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 233 times.
235 } else if (node->op == AssignExprNode::OP_SHR_EQUAL) {
944
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 rhsType = OpRuleManager::getSHREqualResultType(node, lhs, rhs);
945
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 232 times.
233 } else if (node->op == AssignExprNode::OP_AND_EQUAL) {
946
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 rhsType = OpRuleManager::getAndEqualResultType(node, lhs, rhs);
947
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 231 times.
232 } else if (node->op == AssignExprNode::OP_OR_EQUAL) {
948
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 rhsType = OpRuleManager::getOrEqualResultType(node, lhs, rhs);
949
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 } else if (node->op == AssignExprNode::OP_XOR_EQUAL) {
950
1/2
✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
231 rhsType = OpRuleManager::getXorEqualResultType(node, lhs, rhs);
951 }
952
953
1/2
✓ Branch 0 taken 4780 times.
✗ Branch 1 not taken.
4780 if (lhsVar) { // Variable is involved on the left side
954 // Perform type inference
955
3/4
✓ Branch 1 taken 4780 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 4779 times.
4780 if (lhsType.is(TY_DYN))
956
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 lhsVar->updateType(rhsType, false);
957
958 // In case the lhs variable is captured, notify the capture about the write access
959
3/4
✓ Branch 1 taken 4780 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 4777 times.
4780 if (Capture *lhsCapture = currentScope->symbolTable.lookupCapture(lhsVar->name); lhsCapture)
960
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 lhsCapture->setAccessType(READ_WRITE);
961
962 // Update the state of the variable
963
1/2
✓ Branch 1 taken 4780 times.
✗ Branch 2 not taken.
4780 lhsVar->updateState(INITIALIZED, node, false);
964 }
965
966
2/4
✓ Branch 1 taken 4780 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4780 times.
✗ Branch 5 not taken.
4780 return ExprResult{node->setEvaluatedSymbolType(rhsType, manIdx)};
967 }
968
969 throw CompilerError(UNHANDLED_BRANCH, "AssignExpr fall-through"); // GCOV_EXCL_LINE
970 }
971
972 44653 std::any TypeChecker::visitTernaryExpr(TernaryExprNode *node) {
973 // Check if there is a ternary operator applied
974
2/2
✓ Branch 0 taken 44370 times.
✓ Branch 1 taken 283 times.
44653 if (!node->falseExpr)
975
2/2
✓ Branch 1 taken 44355 times.
✓ Branch 2 taken 15 times.
44370 return visit(node->condition);
976
977 // Visit condition
978
2/4
✓ Branch 1 taken 283 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 283 times.
✗ Branch 5 not taken.
283 const QualType conditionType = std::any_cast<ExprResult>(visit(node->condition)).type;
979
2/10
✓ Branch 1 taken 283 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 283 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
283 HANDLE_UNRESOLVED_TYPE_ER(conditionType)
980
6/10
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 282 times.
✓ Branch 3 taken 282 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 282 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 282 times.
✓ Branch 9 taken 1 times.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
283 const QualType trueType = node->isShortened ? conditionType : std::any_cast<ExprResult>(visit(node->trueExpr)).type;
981
2/10
✓ Branch 1 taken 283 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 283 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
283 HANDLE_UNRESOLVED_TYPE_ER(trueType)
982
2/4
✓ Branch 1 taken 283 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 283 times.
✗ Branch 5 not taken.
283 const QualType falseType = std::any_cast<ExprResult>(visit(node->falseExpr)).type;
983
2/10
✓ Branch 1 taken 283 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 283 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
283 HANDLE_UNRESOLVED_TYPE_ER(falseType)
984
985 // Check if the condition evaluates to bool
986
3/4
✓ Branch 1 taken 283 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 282 times.
283 if (!conditionType.is(TY_BOOL))
987
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node->condition, OPERATOR_WRONG_DATA_TYPE, "Condition operand in ternary must be a bool")
988
989 // Check if trueType and falseType are matching
990
1/2
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
282 const QualType trueTypeModified = trueType.removeReferenceWrapper();
991
1/2
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
282 const QualType falseTypeModified = falseType.removeReferenceWrapper();
992
3/4
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 281 times.
282 if (!trueTypeModified.matches(falseTypeModified, false, true, false))
993
9/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
1 SOFT_ERROR_ER(node, OPERATOR_WRONG_DATA_TYPE,
994 "True and false operands in ternary must be of same data type. Got " + trueType.getName(true) + " and " +
995 falseType.getName(true))
996
997
2/4
✓ Branch 1 taken 281 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 281 times.
✗ Branch 5 not taken.
281 return ExprResult{node->setEvaluatedSymbolType(trueType, manIdx)};
998 }
999
1000 45218 std::any TypeChecker::visitLogicalOrExpr(LogicalOrExprNode *node) {
1001 // Check if a logical or operator is applied
1002
2/2
✓ Branch 1 taken 44957 times.
✓ Branch 2 taken 261 times.
45218 if (node->children.size() == 1)
1003
2/2
✓ Branch 2 taken 44943 times.
✓ Branch 3 taken 14 times.
44957 return visit(node->operands.front());
1004
1005 // Visit leftmost operand
1006
2/4
✓ Branch 2 taken 261 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 261 times.
✗ Branch 6 not taken.
261 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands[0]));
1007
2/10
✓ Branch 1 taken 261 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 261 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
261 HANDLE_UNRESOLVED_TYPE_ER(currentOperand.type)
1008 // Loop through all remaining operands
1009
2/2
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 260 times.
548 for (size_t i = 1; i < node->operands.size(); i++) {
1010
2/4
✓ Branch 2 taken 288 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
288 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands[i]));
1011
2/10
✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 288 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
288 HANDLE_UNRESOLVED_TYPE_ER(rhsOperand.type)
1012
2/2
✓ Branch 1 taken 287 times.
✓ Branch 2 taken 1 times.
288 currentOperand = {OpRuleManager::getLogicalOrResultType(node, currentOperand, rhsOperand)};
1013 }
1014
1015
1/2
✓ Branch 1 taken 260 times.
✗ Branch 2 not taken.
260 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1016
1/2
✓ Branch 1 taken 260 times.
✗ Branch 2 not taken.
260 return currentOperand;
1017 }
1018
1019 45506 std::any TypeChecker::visitLogicalAndExpr(LogicalAndExprNode *node) {
1020 // Check if a logical and operator is applied
1021
2/2
✓ Branch 1 taken 45448 times.
✓ Branch 2 taken 58 times.
45506 if (node->children.size() == 1)
1022
2/2
✓ Branch 2 taken 45434 times.
✓ Branch 3 taken 14 times.
45448 return visit(node->operands.front());
1023
1024 // Visit leftmost operand
1025
2/4
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 58 times.
✗ Branch 6 not taken.
58 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands[0]));
1026
2/10
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 58 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
58 HANDLE_UNRESOLVED_TYPE_ER(currentOperand.type)
1027 // Loop through all remaining operands
1028
2/2
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 58 times.
123 for (size_t i = 1; i < node->operands.size(); i++) {
1029
2/4
✓ Branch 2 taken 65 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 65 times.
✗ Branch 6 not taken.
65 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands[i]));
1030
2/10
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 65 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
65 HANDLE_UNRESOLVED_TYPE_ER(rhsOperand.type)
1031
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 currentOperand = {OpRuleManager::getLogicalAndResultType(node, currentOperand, rhsOperand)};
1032 }
1033
1034
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1035
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 return currentOperand;
1036 }
1037
1038 45571 std::any TypeChecker::visitBitwiseOrExpr(BitwiseOrExprNode *node) {
1039 // Check if a bitwise or operator is applied
1040
2/2
✓ Branch 1 taken 45538 times.
✓ Branch 2 taken 33 times.
45571 if (node->children.size() == 1)
1041
2/2
✓ Branch 2 taken 45525 times.
✓ Branch 3 taken 13 times.
45538 return visit(node->operands.front());
1042
1043 // Visit leftmost operand
1044
2/4
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 33 times.
✗ Branch 6 not taken.
33 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands[0]));
1045
2/10
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
33 HANDLE_UNRESOLVED_TYPE_ER(currentOperand.type)
1046 // Loop through all remaining operands
1047
2/2
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 32 times.
68 for (size_t i = 1; i < node->operands.size(); i++) {
1048
2/4
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
36 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands[i]));
1049
2/10
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
36 HANDLE_UNRESOLVED_TYPE_ER(rhsOperand.type)
1050
2/2
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 1 times.
36 currentOperand = {OpRuleManager::getBitwiseOrResultType(node, currentOperand, rhsOperand)};
1051 }
1052
1053
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1054
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 return currentOperand;
1055 }
1056
1057 45607 std::any TypeChecker::visitBitwiseXorExpr(BitwiseXorExprNode *node) {
1058 // Check if a bitwise xor operator is applied
1059
2/2
✓ Branch 1 taken 45603 times.
✓ Branch 2 taken 4 times.
45607 if (node->children.size() == 1)
1060
2/2
✓ Branch 2 taken 45590 times.
✓ Branch 3 taken 13 times.
45603 return visit(node->operands.front());
1061
1062 // Visit leftmost operand
1063
2/4
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands[0]));
1064
2/10
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
4 HANDLE_UNRESOLVED_TYPE_ER(currentOperand.type)
1065 // Loop through all remaining operands
1066
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 4 times.
11 for (size_t i = 1; i < node->operands.size(); i++) {
1067
2/4
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
7 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands[i]));
1068
2/10
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
7 HANDLE_UNRESOLVED_TYPE_ER(rhsOperand.type)
1069
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 currentOperand = {OpRuleManager::getBitwiseXorResultType(node, currentOperand, rhsOperand)};
1070 }
1071
1072
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1073
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 return currentOperand;
1074 }
1075
1076 45614 std::any TypeChecker::visitBitwiseAndExpr(BitwiseAndExprNode *node) {
1077 // Check if a bitwise and operator is applied
1078
2/2
✓ Branch 1 taken 45584 times.
✓ Branch 2 taken 30 times.
45614 if (node->children.size() == 1)
1079
2/2
✓ Branch 2 taken 45571 times.
✓ Branch 3 taken 13 times.
45584 return visit(node->operands.front());
1080
1081 // Visit leftmost operand
1082
2/4
✓ Branch 2 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
30 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands[0]));
1083
2/10
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 30 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
30 HANDLE_UNRESOLVED_TYPE_ER(currentOperand.type)
1084 // Loop through all remaining operands
1085
2/2
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 30 times.
63 for (size_t i = 1; i < node->operands.size(); i++) {
1086
2/4
✓ Branch 2 taken 33 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 33 times.
✗ Branch 6 not taken.
33 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands[i]));
1087
2/10
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
33 HANDLE_UNRESOLVED_TYPE_ER(rhsOperand.type)
1088
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 currentOperand = {OpRuleManager::getBitwiseAndResultType(node, currentOperand, rhsOperand)};
1089 }
1090
1091
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1092
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 return currentOperand;
1093 }
1094
1095 45647 std::any TypeChecker::visitEqualityExpr(EqualityExprNode *node) {
1096 // Check if at least one equality operator is applied
1097
2/2
✓ Branch 1 taken 41953 times.
✓ Branch 2 taken 3694 times.
45647 if (node->children.size() == 1)
1098
2/2
✓ Branch 2 taken 41941 times.
✓ Branch 3 taken 12 times.
41953 return visit(node->operands.front());
1099
1100 // Visit right side first, then left side
1101
2/4
✓ Branch 2 taken 3694 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3694 times.
✗ Branch 6 not taken.
3694 auto rhs = std::any_cast<ExprResult>(visit(node->operands[1]));
1102
2/10
✓ Branch 1 taken 3694 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3694 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
3694 HANDLE_UNRESOLVED_TYPE_ER(rhs.type)
1103
2/4
✓ Branch 2 taken 3694 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3694 times.
✗ Branch 6 not taken.
3694 auto lhs = std::any_cast<ExprResult>(visit(node->operands[0]));
1104
2/10
✓ Branch 1 taken 3694 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3694 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
3694 HANDLE_UNRESOLVED_TYPE_ER(lhs.type)
1105
1106 // Check if we need the string runtime to perform a string comparison
1107
10/14
✓ Branch 1 taken 3694 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 118 times.
✓ Branch 4 taken 3576 times.
✓ Branch 6 taken 118 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 117 times.
✓ Branch 9 taken 1 times.
✓ Branch 11 taken 117 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 117 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 117 times.
✓ Branch 16 taken 3577 times.
3811 if (lhs.type.is(TY_STRING) && rhs.type.is(TY_STRING) && !sourceFile->isStringRT())
1108
1/2
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
117 sourceFile->requestRuntimeModule(STRING_RT);
1109
1110 // Check operator
1111 3694 ExprResult result;
1112
2/2
✓ Branch 0 taken 2379 times.
✓ Branch 1 taken 1315 times.
3694 if (node->op == EqualityExprNode::OP_EQUAL) // Operator was equal
1113
2/2
✓ Branch 1 taken 2378 times.
✓ Branch 2 taken 1 times.
2379 result = opRuleManager.getEqualResultType(node, lhs, rhs, 0);
1114
1/2
✓ Branch 0 taken 1315 times.
✗ Branch 1 not taken.
1315 else if (node->op == EqualityExprNode::OP_NOT_EQUAL) // Operator was not equal
1115
1/2
✓ Branch 1 taken 1315 times.
✗ Branch 2 not taken.
1315 result = opRuleManager.getNotEqualResultType(node, lhs, rhs, 0);
1116 else
1117 throw CompilerError(UNHANDLED_BRANCH, "EqualityExpr fall-through"); // GCOV_EXCL_LINE
1118
1119
1/2
✓ Branch 1 taken 3693 times.
✗ Branch 2 not taken.
3693 node->setEvaluatedSymbolType(result.type, manIdx);
1120
1/2
✓ Branch 1 taken 3693 times.
✗ Branch 2 not taken.
3693 return result;
1121 }
1122
1123 49341 std::any TypeChecker::visitRelationalExpr(RelationalExprNode *node) {
1124 // Check if a relational operator is applied
1125
2/2
✓ Branch 1 taken 46791 times.
✓ Branch 2 taken 2550 times.
49341 if (node->children.size() == 1)
1126
2/2
✓ Branch 2 taken 46780 times.
✓ Branch 3 taken 11 times.
46791 return visit(node->operands.front());
1127
1128 // Visit right side first, then left side
1129
2/4
✓ Branch 2 taken 2550 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2550 times.
✗ Branch 6 not taken.
2550 auto rhs = std::any_cast<ExprResult>(visit(node->operands[1]));
1130
6/10
✓ Branch 1 taken 2550 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2549 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
2550 HANDLE_UNRESOLVED_TYPE_ER(rhs.type)
1131
2/4
✓ Branch 2 taken 2549 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2549 times.
✗ Branch 6 not taken.
2549 auto lhs = std::any_cast<ExprResult>(visit(node->operands[0]));
1132
2/10
✓ Branch 1 taken 2549 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2549 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
2549 HANDLE_UNRESOLVED_TYPE_ER(lhs.type)
1133
1134 // Check operator
1135 2549 QualType resultType;
1136
2/2
✓ Branch 0 taken 1476 times.
✓ Branch 1 taken 1073 times.
2549 if (node->op == RelationalExprNode::OP_LESS) // Operator was less
1137
1/2
✓ Branch 1 taken 1476 times.
✗ Branch 2 not taken.
1476 resultType = OpRuleManager::getLessResultType(node, lhs, rhs);
1138
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 827 times.
1073 else if (node->op == RelationalExprNode::OP_GREATER) // Operator was greater
1139
2/2
✓ Branch 1 taken 245 times.
✓ Branch 2 taken 1 times.
246 resultType = OpRuleManager::getGreaterResultType(node, lhs, rhs);
1140
2/2
✓ Branch 0 taken 263 times.
✓ Branch 1 taken 564 times.
827 else if (node->op == RelationalExprNode::OP_LESS_EQUAL) // Operator was less equal
1141
1/2
✓ Branch 1 taken 263 times.
✗ Branch 2 not taken.
263 resultType = OpRuleManager::getLessEqualResultType(node, lhs, rhs);
1142
1/2
✓ Branch 0 taken 564 times.
✗ Branch 1 not taken.
564 else if (node->op == RelationalExprNode::OP_GREATER_EQUAL) // Operator was greater equal
1143
1/2
✓ Branch 1 taken 564 times.
✗ Branch 2 not taken.
564 resultType = OpRuleManager::getGreaterEqualResultType(node, lhs, rhs);
1144 else
1145 throw CompilerError(UNHANDLED_BRANCH, "RelationalExpr fall-through"); // GCOV_EXCL_LINE
1146
1147
2/4
✓ Branch 1 taken 2548 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2548 times.
✗ Branch 5 not taken.
2548 return ExprResult{node->setEvaluatedSymbolType(resultType, manIdx)};
1148 }
1149
1150 51890 std::any TypeChecker::visitShiftExpr(ShiftExprNode *node) {
1151 // Check if at least one shift operator is applied
1152
2/2
✓ Branch 1 taken 51873 times.
✓ Branch 2 taken 17 times.
51890 if (node->children.size() == 1)
1153
2/2
✓ Branch 2 taken 51862 times.
✓ Branch 3 taken 11 times.
51873 return visit(node->operands.front());
1154
1155 // Visit right side first, then left
1156
2/4
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
17 auto rhs = std::any_cast<ExprResult>(visit(node->operands[1]));
1157
2/10
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
17 HANDLE_UNRESOLVED_TYPE_ER(rhs.type)
1158
2/4
✓ Branch 2 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
17 auto lhs = std::any_cast<ExprResult>(visit(node->operands[0]));
1159
2/10
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
17 HANDLE_UNRESOLVED_TYPE_ER(lhs.type)
1160
1161 // Check operator
1162 17 ExprResult currentResult;
1163
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if (node->op == ShiftExprNode::OP_SHIFT_LEFT) // Operator was shl
1164
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 currentResult = opRuleManager.getShiftLeftResultType(node, lhs, rhs, 0);
1165
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 else if (node->op == ShiftExprNode::OP_SHIFT_RIGHT) // Operator was shr
1166
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 currentResult = opRuleManager.getShiftRightResultType(node, lhs, rhs, 0);
1167 else
1168 throw CompilerError(UNHANDLED_BRANCH, "ShiftExpr fall-through"); // GCOV_EXCL_LINE
1169
1170
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 node->setEvaluatedSymbolType(currentResult.type, manIdx);
1171
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 return currentResult;
1172 }
1173
1174 51907 std::any TypeChecker::visitAdditiveExpr(AdditiveExprNode *node) {
1175 // Check if at least one additive operator is applied
1176
2/2
✓ Branch 1 taken 48885 times.
✓ Branch 2 taken 3022 times.
51907 if (node->children.size() == 1)
1177
2/2
✓ Branch 2 taken 48875 times.
✓ Branch 3 taken 10 times.
48885 return visit(node->operands.front());
1178
1179 // Visit leftmost operand
1180
2/4
✓ Branch 2 taken 3022 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3022 times.
✗ Branch 6 not taken.
3022 auto currentResult = std::any_cast<ExprResult>(visit(node->operands[0]));
1181
2/10
✓ Branch 1 taken 3022 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3022 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
3022 HANDLE_UNRESOLVED_TYPE_ER(currentResult.type)
1182
1183 // Loop through remaining operands
1184
2/2
✓ Branch 1 taken 3437 times.
✓ Branch 2 taken 3021 times.
6458 for (size_t i = 0; i < node->opQueue.size(); i++) {
1185 // Visit next operand
1186 3437 MultiplicativeExprNode *operand = node->operands[i + 1];
1187
2/4
✓ Branch 1 taken 3437 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3437 times.
✗ Branch 5 not taken.
3437 auto operandResult = std::any_cast<ExprResult>(visit(operand));
1188
2/10
✓ Branch 1 taken 3437 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3437 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
3437 HANDLE_UNRESOLVED_TYPE_ER(operandResult.type)
1189
1190 // Check operator
1191 3437 const AdditiveExprNode::AdditiveOp &op = node->opQueue.front().first;
1192
2/2
✓ Branch 0 taken 2178 times.
✓ Branch 1 taken 1259 times.
3437 if (op == AdditiveExprNode::OP_PLUS)
1193
2/2
✓ Branch 1 taken 2177 times.
✓ Branch 2 taken 1 times.
2178 currentResult = opRuleManager.getPlusResultType(node, currentResult, operandResult, i);
1194
1/2
✓ Branch 0 taken 1259 times.
✗ Branch 1 not taken.
1259 else if (op == AdditiveExprNode::OP_MINUS)
1195
1/2
✓ Branch 1 taken 1259 times.
✗ Branch 2 not taken.
1259 currentResult = opRuleManager.getMinusResultType(node, currentResult, operandResult, i);
1196 else
1197 throw CompilerError(UNHANDLED_BRANCH, "AdditiveExpr fall-through"); // GCOV_EXCL_LINE
1198
1199 // Push the new item and pop the old one on the other side of the queue
1200
1/2
✓ Branch 1 taken 3436 times.
✗ Branch 2 not taken.
3436 node->opQueue.emplace(op, currentResult.type);
1201 3436 node->opQueue.pop();
1202 }
1203
1204
1/2
✓ Branch 1 taken 3021 times.
✗ Branch 2 not taken.
3021 node->setEvaluatedSymbolType(currentResult.type, manIdx);
1205
1/2
✓ Branch 1 taken 3021 times.
✗ Branch 2 not taken.
3021 return currentResult;
1206 }
1207
1208 55344 std::any TypeChecker::visitMultiplicativeExpr(MultiplicativeExprNode *node) {
1209 // Check if at least one multiplicative operator is applied
1210
2/2
✓ Branch 1 taken 54500 times.
✓ Branch 2 taken 844 times.
55344 if (node->children.size() == 1)
1211
2/2
✓ Branch 2 taken 54491 times.
✓ Branch 3 taken 9 times.
54500 return visit(node->operands.front());
1212
1213 // Visit leftmost operand
1214
2/4
✓ Branch 2 taken 844 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 844 times.
✗ Branch 6 not taken.
844 auto currentResult = std::any_cast<ExprResult>(visit(node->operands[0]));
1215
2/10
✓ Branch 1 taken 844 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 844 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
844 HANDLE_UNRESOLVED_TYPE_ER(currentResult.type)
1216 // Loop through remaining operands
1217
2/2
✓ Branch 1 taken 868 times.
✓ Branch 2 taken 843 times.
1711 for (size_t i = 0; i < node->opQueue.size(); i++) {
1218 // Visit next operand
1219 868 CastExprNode *operand = node->operands[i + 1];
1220
2/4
✓ Branch 1 taken 868 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 868 times.
✗ Branch 5 not taken.
868 auto operandResult = std::any_cast<ExprResult>(visit(operand));
1221
2/10
✓ Branch 1 taken 868 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 868 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
868 HANDLE_UNRESOLVED_TYPE_ER(operandResult.type)
1222
1223 // Check operator
1224 868 const MultiplicativeExprNode::MultiplicativeOp &op = node->opQueue.front().first;
1225
2/2
✓ Branch 0 taken 654 times.
✓ Branch 1 taken 214 times.
868 if (op == MultiplicativeExprNode::OP_MUL)
1226
2/2
✓ Branch 1 taken 653 times.
✓ Branch 2 taken 1 times.
654 currentResult = opRuleManager.getMulResultType(node, currentResult, operandResult, i);
1227
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 9 times.
214 else if (op == MultiplicativeExprNode::OP_DIV)
1228
1/2
✓ Branch 1 taken 205 times.
✗ Branch 2 not taken.
205 currentResult = opRuleManager.getDivResultType(node, currentResult, operandResult, i);
1229
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 else if (op == MultiplicativeExprNode::OP_REM)
1230
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 currentResult = OpRuleManager::getRemResultType(node, currentResult, operandResult);
1231 else
1232 throw CompilerError(UNHANDLED_BRANCH, "Multiplicative fall-through"); // GCOV_EXCL_LINE
1233
1234 // Push the new item and pop the old one on the other side of the queue
1235
1/2
✓ Branch 1 taken 867 times.
✗ Branch 2 not taken.
867 node->opQueue.emplace(op, currentResult.type);
1236 867 node->opQueue.pop();
1237 }
1238
1239
1/2
✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
843 node->setEvaluatedSymbolType(currentResult.type, manIdx);
1240
1/2
✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
843 return currentResult;
1241 }
1242
1243 56212 std::any TypeChecker::visitCastExpr(CastExprNode *node) {
1244 // Check if cast is applied
1245
2/2
✓ Branch 0 taken 53855 times.
✓ Branch 1 taken 2357 times.
56212 if (!node->isCast)
1246
2/2
✓ Branch 1 taken 53846 times.
✓ Branch 2 taken 9 times.
53855 return visit(node->prefixUnaryExpr);
1247
1248 // Visit source type
1249
2/4
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2357 times.
✗ Branch 5 not taken.
2357 const auto src = std::any_cast<ExprResult>(visit(node->prefixUnaryExpr));
1250
2/10
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2357 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
2357 HANDLE_UNRESOLVED_TYPE_ER(src.type)
1251 // Visit destination type
1252
2/4
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2357 times.
✗ Branch 5 not taken.
2357 const auto dstType = std::any_cast<QualType>(visit(node->dataType));
1253
2/10
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2357 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
2357 HANDLE_UNRESOLVED_TYPE_ER(dstType)
1254
1255 // Check for identity cast
1256
3/4
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1006 times.
✓ Branch 4 taken 1351 times.
2357 if (src.type == dstType) {
1257
2/4
✓ Branch 1 taken 1006 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1006 times.
✗ Branch 5 not taken.
1006 const CompilerWarning warning(node->codeLoc, IDENTITY_CAST, "You cast from a type to itself. Thus, this can be simplified.");
1258
1/2
✓ Branch 1 taken 1006 times.
✗ Branch 2 not taken.
1006 sourceFile->compilerOutput.warnings.push_back(warning);
1259 1006 }
1260
1261 // Get result type
1262
1/2
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
2357 const QualType resultType = opRuleManager.getCastResultType(node, dstType, src);
1263
1264
3/4
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 200 times.
✓ Branch 4 taken 2157 times.
2357 SymbolTableEntry *entry = src.type.isSameContainerTypeAs(dstType) ? src.entry : nullptr;
1265
2/4
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2357 times.
✗ Branch 5 not taken.
2357 return ExprResult{node->setEvaluatedSymbolType(resultType, manIdx), entry};
1266 }
1267
1268 61834 std::any TypeChecker::visitPrefixUnaryExpr(PrefixUnaryExprNode *node) {
1269 // Reset access scope
1270 61834 accessScope = nullptr;
1271
1272 // If no operator is applied, simply visit the postfix unary expression
1273
2/2
✓ Branch 0 taken 60995 times.
✓ Branch 1 taken 839 times.
61834 if (node->op == PrefixUnaryExprNode::OP_NONE)
1274
2/2
✓ Branch 1 taken 60987 times.
✓ Branch 2 taken 8 times.
60995 return visit(node->postfixUnaryExpr);
1275
1276 // Visit the right side
1277 839 PrefixUnaryExprNode *rhsNode = node->prefixUnaryExpr;
1278
2/4
✓ Branch 1 taken 839 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 839 times.
✗ Branch 5 not taken.
839 auto operand = std::any_cast<ExprResult>(visit(rhsNode));
1279 839 auto [operandType, operandEntry] = operand;
1280
6/10
✓ Branch 1 taken 839 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 838 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
839 HANDLE_UNRESOLVED_TYPE_ER(operandType)
1281 // Determine action, based on the given operator
1282
7/8
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 561 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 162 times.
✓ Branch 6 taken 63 times.
✗ Branch 7 not taken.
838 switch (node->op) {
1283 16 case PrefixUnaryExprNode::OP_MINUS:
1284
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 operandType = OpRuleManager::getPrefixMinusResultType(node, operand);
1285 16 break;
1286 28 case PrefixUnaryExprNode::OP_PLUS_PLUS:
1287
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 operandType = opRuleManager.getPrefixPlusPlusResultType(node, operand);
1288
1289
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3 times.
28 if (operandEntry) {
1290 // In case the lhs is captured, notify the capture about the write access
1291
2/4
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
25 if (Capture *lhsCapture = currentScope->symbolTable.lookupCapture(operandEntry->name); lhsCapture)
1292 lhsCapture->setAccessType(READ_WRITE);
1293
1294 // Update the state of the variable
1295
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 operandEntry->updateState(INITIALIZED, node, false);
1296 }
1297
1298 28 break;
1299 7 case PrefixUnaryExprNode::OP_MINUS_MINUS:
1300
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 times.
7 operandType = opRuleManager.getPrefixMinusMinusResultType(node, operand);
1301
1302
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (operandEntry) {
1303 // In case the lhs is captured, notify the capture about the write access
1304
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 if (Capture *lhsCapture = currentScope->symbolTable.lookupCapture(operandEntry->name); lhsCapture)
1305 lhsCapture->setAccessType(READ_WRITE);
1306
1307 // Update the state of the variable
1308
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 operandEntry->updateState(INITIALIZED, node, false);
1309 }
1310
1311 6 break;
1312 561 case PrefixUnaryExprNode::OP_NOT:
1313
1/2
✓ Branch 1 taken 561 times.
✗ Branch 2 not taken.
561 operandType = OpRuleManager::getPrefixNotResultType(node, operand);
1314 561 break;
1315 1 case PrefixUnaryExprNode::OP_BITWISE_NOT:
1316
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 operandType = OpRuleManager::getPrefixBitwiseNotResultType(node, operand);
1317 1 break;
1318 162 case PrefixUnaryExprNode::OP_DEREFERENCE:
1319
1/2
✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
162 operandType = OpRuleManager::getPrefixMulResultType(node, operand);
1320 162 break;
1321 63 case PrefixUnaryExprNode::OP_ADDRESS_OF:
1322
1/2
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
63 operandType = OpRuleManager::getPrefixBitwiseAndResultType(node, operand);
1323 63 break;
1324 default:
1325 throw CompilerError(UNHANDLED_BRANCH, "PrefixUnaryExpr fall-through"); // GCOV_EXCL_LINE
1326 }
1327
1328
2/4
✓ Branch 1 taken 837 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 837 times.
✗ Branch 5 not taken.
837 return ExprResult{node->setEvaluatedSymbolType(operandType, manIdx), operandEntry};
1329 }
1330
1331 77053 std::any TypeChecker::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) {
1332 // If no operator is applied, simply visit the atomic expression
1333
2/2
✓ Branch 0 taken 60995 times.
✓ Branch 1 taken 16058 times.
77053 if (node->op == PostfixUnaryExprNode::OP_NONE)
1334
2/2
✓ Branch 1 taken 60988 times.
✓ Branch 2 taken 7 times.
60995 return visit(node->atomicExpr);
1335
1336 // Visit left side
1337 16058 PostfixUnaryExprNode *lhsNode = node->postfixUnaryExpr;
1338
2/4
✓ Branch 1 taken 16058 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16058 times.
✗ Branch 5 not taken.
16058 auto lhs = std::any_cast<ExprResult>(visit(lhsNode));
1339 16058 auto [lhsType, lhsEntry] = lhs;
1340
6/10
✓ Branch 1 taken 16058 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 16052 times.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
16058 HANDLE_UNRESOLVED_TYPE_ER(lhsType)
1341
1342
4/5
✓ Branch 0 taken 2328 times.
✓ Branch 1 taken 12101 times.
✓ Branch 2 taken 1353 times.
✓ Branch 3 taken 270 times.
✗ Branch 4 not taken.
16052 switch (node->op) {
1343 2328 case PostfixUnaryExprNode::OP_SUBSCRIPT: {
1344
1/2
✓ Branch 1 taken 2328 times.
✗ Branch 2 not taken.
2328 lhsType = lhsType.removeReferenceWrapper();
1345
1346 // Check if we can apply the subscript operator on the lhs type
1347
2/4
✓ Branch 1 taken 2328 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2328 times.
2328 if (!lhsType.isOneOf({TY_ARRAY, TY_STRING, TY_PTR}))
1348 SOFT_ERROR_ER(node, OPERATOR_WRONG_DATA_TYPE,
1349 "Can only apply subscript operator on array type, got " + lhsType.getName(true))
1350
1351 // Visit index assignment
1352 2328 AssignExprNode *indexAssignExpr = node->subscriptIndexExpr;
1353
2/4
✓ Branch 1 taken 2328 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2328 times.
✗ Branch 5 not taken.
2328 QualType indexType = std::any_cast<ExprResult>(visit(indexAssignExpr)).type;
1354
2/10
✓ Branch 1 taken 2328 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2328 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
2328 HANDLE_UNRESOLVED_TYPE_ER(indexType)
1355 // Check if the index is of the right type
1356
3/4
✓ Branch 1 taken 2328 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 2327 times.
2328 if (!indexType.isOneOf({TY_INT, TY_LONG}))
1357
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node, ARRAY_INDEX_NOT_INT_OR_LONG, "Array index must be of type int or long")
1358
1359 // Check if we have an unsafe operation
1360
6/10
✓ Branch 1 taken 2327 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1546 times.
✓ Branch 4 taken 781 times.
✓ Branch 6 taken 1546 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1546 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2327 times.
2327 if (lhsType.isPtr() && !currentScope->doesAllowUnsafeOperations())
1361 SOFT_ERROR_ER(
1362 node, UNSAFE_OPERATION_IN_SAFE_CONTEXT,
1363 "The subscript operator on pointers is an unsafe operation. Use unsafe blocks if you know what you are doing.")
1364
1365 // Check if we have a hardcoded array index
1366
11/14
✓ Branch 1 taken 2327 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 136 times.
✓ Branch 4 taken 2191 times.
✓ Branch 6 taken 136 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 96 times.
✓ Branch 9 taken 40 times.
✓ Branch 11 taken 96 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 34 times.
✓ Branch 14 taken 62 times.
✓ Branch 15 taken 34 times.
✓ Branch 16 taken 2293 times.
2327 if (lhsType.isArray() && lhsType.getArraySize() != ARRAY_SIZE_UNKNOWN && indexAssignExpr->hasCompileTimeValue()) {
1367
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 const int32_t constIndex = indexAssignExpr->getCompileTimeValue().intValue;
1368
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 const unsigned int constSize = lhsType.getArraySize();
1369 // Check if we are accessing out-of-bounds memory
1370
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
34 if (constIndex >= static_cast<int32_t>(constSize)) {
1371 1 const std::string idxStr = std::to_string(constIndex);
1372 1 const std::string sizeStr = std::to_string(constSize);
1373
7/14
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
1 SOFT_ERROR_ER(node, ARRAY_INDEX_OUT_OF_BOUNDS,
1374 "You are trying to access element with index " + idxStr + " of an array with size " + sizeStr)
1375 1 }
1376 }
1377
1378 // Get item type
1379
1/2
✓ Branch 1 taken 2326 times.
✗ Branch 2 not taken.
2326 lhsType = lhsType.getContained();
1380
1381 // Remove heap specifier
1382 2326 lhsType.getSpecifiers().isHeap = false;
1383
1384 2326 break;
1385 }
1386 12101 case PostfixUnaryExprNode::OP_MEMBER_ACCESS: {
1387 12101 const std::string &fieldName = node->identifier;
1388
1389 // Check if lhs is enum or strobj
1390 12101 QualType lhsBaseTy = lhsType;
1391
1/2
✓ Branch 1 taken 12101 times.
✗ Branch 2 not taken.
12101 autoDeReference(lhsBaseTy);
1392
3/4
✓ Branch 1 taken 12101 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 12100 times.
12101 if (!lhsBaseTy.is(TY_STRUCT))
1393
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(node, INVALID_MEMBER_ACCESS, "Cannot apply member access operator on " + lhsType.getName(false))
1394
1395 // Retrieve registry entry
1396
1/2
✓ Branch 1 taken 12100 times.
✗ Branch 2 not taken.
12100 const std::string &structName = lhsBaseTy.getSubType();
1397
1/2
✓ Branch 1 taken 12100 times.
✗ Branch 2 not taken.
12100 Scope *structScope = lhsBaseTy.getBodyScope();
1398
1399 // If we only have the generic struct scope, lookup the concrete manifestation scope
1400
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 12025 times.
12100 if (structScope->isGenericScope) {
1401 75 Scope *matchScope = structScope->parent;
1402
2/4
✓ Branch 1 taken 75 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 75 times.
✗ Branch 5 not taken.
75 Struct *spiceStruct = StructManager::match(matchScope, structName, lhsBaseTy.getTemplateTypes(), node);
1403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 assert(spiceStruct != nullptr);
1404 75 structScope = spiceStruct->scope;
1405 }
1406
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12100 times.
12100 assert(!structScope->isGenericScope); // At this point we always expect a substantiation scope
1407
1408 // Get accessed field
1409 12100 std::vector<size_t> indexPath;
1410
1/2
✓ Branch 1 taken 12100 times.
✗ Branch 2 not taken.
12100 SymbolTableEntry *memberEntry = structScope->symbolTable.lookupInComposedFields(fieldName, indexPath);
1411
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12098 times.
12100 if (!memberEntry)
1412
7/14
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
2 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE, "Field '" + node->identifier + "' not found in struct " + structName)
1413
1/2
✓ Branch 1 taken 12098 times.
✗ Branch 2 not taken.
12098 const QualType memberType = memberEntry->getQualType();
1414
1415 // Check for insufficient visibility
1416
8/14
✓ Branch 1 taken 12098 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 67 times.
✓ Branch 4 taken 12031 times.
✓ Branch 6 taken 67 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 67 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 67 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 67 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 12098 times.
12098 if (structScope->isImportedBy(rootScope) && !memberEntry->getQualType().getBase().isPublic())
1417 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Cannot access field '" + fieldName + "' due to its private visibility")
1418
1419 // Set field to used
1420 12098 memberEntry->used = true;
1421
1422 // Overwrite type and entry of left side with member type and entry
1423 12098 lhsType = memberType;
1424 12098 lhsEntry = memberEntry;
1425 12098 break;
1426
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12098 times.
12100 }
1427 1353 case PostfixUnaryExprNode::OP_PLUS_PLUS: {
1428
2/2
✓ Branch 0 taken 1348 times.
✓ Branch 1 taken 5 times.
1353 if (lhsEntry) {
1429 // In case the lhs is captured, notify the capture about the write access
1430
3/4
✓ Branch 1 taken 1348 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1344 times.
1348 if (Capture *lhsCapture = currentScope->symbolTable.lookupCapture(lhsEntry->name); lhsCapture)
1431
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 lhsCapture->setAccessType(READ_WRITE);
1432
1433 // Update the state of the variable
1434
1/2
✓ Branch 1 taken 1348 times.
✗ Branch 2 not taken.
1348 lhsEntry->updateState(INITIALIZED, node, false);
1435 }
1436
1437
2/2
✓ Branch 1 taken 1352 times.
✓ Branch 2 taken 1 times.
1353 auto [type, entry] = opRuleManager.getPostfixPlusPlusResultType(node, lhs, 0);
1438 1352 lhsType = type;
1439 1352 lhsEntry = entry;
1440 1352 break;
1441 }
1442 270 case PostfixUnaryExprNode::OP_MINUS_MINUS: {
1443
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 4 times.
270 if (lhsEntry) {
1444 // In case the lhs is captured, notify the capture about the write access
1445
2/4
✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 266 times.
266 if (Capture *lhsCapture = currentScope->symbolTable.lookupCapture(lhsEntry->name); lhsCapture)
1446 lhsCapture->setAccessType(READ_WRITE);
1447
1448 // Update the state of the variable
1449
1/2
✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
266 lhsEntry->updateState(INITIALIZED, node, false);
1450 }
1451
1452
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
270 ExprResult result = opRuleManager.getPostfixMinusMinusResultType(node, lhs, 0);
1453 270 lhsType = result.type;
1454 270 lhsEntry = result.entry;
1455 270 break;
1456 }
1457 default:
1458 throw CompilerError(UNHANDLED_BRANCH, "PostfixUnaryExpr fall-through"); // GCOV_EXCL_LINE
1459 }
1460
1461
2/4
✓ Branch 1 taken 16046 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 16046 times.
16046 if (lhsType.is(TY_INVALID)) {
1462 const std::string varName = lhsEntry ? lhsEntry->name : "";
1463 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE, "Variable '" + varName + "' was referenced before declared")
1464 }
1465
1466
2/4
✓ Branch 1 taken 16046 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16046 times.
✗ Branch 5 not taken.
16046 return ExprResult{node->setEvaluatedSymbolType(lhsType, manIdx), lhsEntry};
1467 }
1468
1469 60995 std::any TypeChecker::visitAtomicExpr(AtomicExprNode *node) {
1470 // Check if constant
1471
2/2
✓ Branch 0 taken 11919 times.
✓ Branch 1 taken 49076 times.
60995 if (node->constant)
1472
1/2
✓ Branch 1 taken 11919 times.
✗ Branch 2 not taken.
11919 return visit(node->constant);
1473
1474 // Check if value
1475
2/2
✓ Branch 0 taken 11362 times.
✓ Branch 1 taken 37714 times.
49076 if (node->value)
1476
2/2
✓ Branch 1 taken 11358 times.
✓ Branch 2 taken 4 times.
11362 return visit(node->value);
1477
1478 // Check for builtin calls
1479
2/2
✓ Branch 0 taken 1184 times.
✓ Branch 1 taken 36530 times.
37714 if (node->builtinCall)
1480
1/2
✓ Branch 1 taken 1184 times.
✗ Branch 2 not taken.
1184 return visit(node->builtinCall);
1481
1482 // Check for assign expression within parentheses
1483
2/2
✓ Branch 0 taken 523 times.
✓ Branch 1 taken 36007 times.
36530 if (node->assignExpr)
1484
2/2
✓ Branch 1 taken 520 times.
✓ Branch 2 taken 3 times.
523 return visit(node->assignExpr);
1485
1486 // Identifier (local or global variable access)
1487
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36007 times.
36007 assert(!node->fqIdentifier.empty());
1488
1/2
✓ Branch 0 taken 36007 times.
✗ Branch 1 not taken.
36007 if (!accessScope)
1489 36007 accessScope = currentScope;
1490
1491 // Check if a local or global variable can be found by searching for the name
1492 36007 SymbolTableEntry *varEntry = nullptr;
1493
2/2
✓ Branch 1 taken 35758 times.
✓ Branch 2 taken 249 times.
36007 if (node->identifierFragments.size() == 1)
1494 71516 varEntry = accessScope->lookup(node->identifierFragments.back());
1495
1496 // If no local or global was found, search in the name registry
1497
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 35699 times.
36007 if (!varEntry) {
1498
1/2
✓ Branch 1 taken 308 times.
✗ Branch 2 not taken.
308 const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(node->fqIdentifier);
1499
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 307 times.
308 if (!registryEntry)
1500
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE, "The variable '" + node->fqIdentifier + "' could not be found")
1501 307 varEntry = registryEntry->targetEntry;
1502 307 accessScope = registryEntry->targetScope;
1503 }
1504
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36006 times.
36006 assert(varEntry != nullptr);
1505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36006 times.
36006 assert(accessScope != nullptr);
1506
1/2
✓ Branch 1 taken 36006 times.
✗ Branch 2 not taken.
36006 AtomicExprNode::VarAccessData &data = node->data.at(manIdx);
1507
1/2
✓ Branch 1 taken 36006 times.
✗ Branch 2 not taken.
36006 data = {varEntry, accessScope, accessScope->symbolTable.lookupCapture(varEntry->name)};
1508
1/2
✓ Branch 1 taken 36006 times.
✗ Branch 2 not taken.
36006 const QualType varType = varEntry->getQualType();
1509
6/10
✓ Branch 1 taken 36006 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 35998 times.
✓ Branch 6 taken 8 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 8 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 8 times.
✗ Branch 13 not taken.
36006 HANDLE_UNRESOLVED_TYPE_ER(varType)
1510
1511
7/8
✓ Branch 1 taken 35998 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 44 times.
✓ Branch 4 taken 35954 times.
✓ Branch 5 taken 9 times.
✓ Branch 6 taken 35 times.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 35989 times.
35998 if (varType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && varEntry->global) {
1512 // Check if overloaded function was referenced
1513
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 const std::vector<Function *> *manifestations = varEntry->declNode->getFctManifestations(varEntry->name);
1514
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 8 times.
9 if (manifestations->size() > 1)
1515
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node, REFERENCED_OVERLOADED_FCT, "Overloaded functions / functions with optional params cannot be referenced")
1516
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
8 if (!manifestations->front()->templateTypes.empty())
1517
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node, REFERENCED_OVERLOADED_FCT, "Generic functions cannot be referenced")
1518 // Set referenced function to used
1519 7 Function *referencedFunction = manifestations->front();
1520 7 referencedFunction->used = true;
1521 7 referencedFunction->entry->used = true;
1522 }
1523
1524
3/4
✓ Branch 1 taken 35996 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 35994 times.
35996 if (varType.is(TY_INVALID))
1525
6/12
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 2 times.
✗ Branch 19 not taken.
2 SOFT_ERROR_ER(node, USED_BEFORE_DECLARED, "Symbol '" + varEntry->name + "' was used before declared.")
1526
1527 // The base type should be a primitive, struct, interface, function or procedure
1528
1/2
✓ Branch 1 taken 35994 times.
✗ Branch 2 not taken.
35994 const QualType baseType = varType.getBase();
1529
6/10
✓ Branch 1 taken 35994 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13572 times.
✓ Branch 4 taken 22422 times.
✓ Branch 6 taken 13572 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 13572 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 35994 times.
35994 if (!baseType.isPrimitive() && !baseType.isOneOf({TY_STRUCT, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE, TY_DYN}))
1530 SOFT_ERROR_ER(node, INVALID_SYMBOL_ACCESS, "A symbol of type " + varType.getName(false) + " cannot be accessed here")
1531
1532 // Check if is an imported variable
1533
3/4
✓ Branch 1 taken 35994 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 171 times.
✓ Branch 4 taken 35823 times.
35994 if (accessScope->isImportedBy(rootScope)) {
1534 // Check if the entry is public
1535
8/10
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 117 times.
✓ Branch 3 taken 54 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 54 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 53 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 170 times.
171 if (varEntry->scope->type != ScopeType::ENUM && !varEntry->getQualType().isPublic())
1536
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Cannot access '" + varEntry->name + "' due to its private visibility")
1537 }
1538
1539 // Check if we have seen a 'this.' prefix, because the generator needs that
1540
6/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 35992 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 35992 times.
35993 if (varEntry->scope->type == ScopeType::STRUCT && node->identifierFragments.front() != THIS_VARIABLE_NAME)
1541
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE,
1542 "The symbol '" + node->fqIdentifier + "' could not be found. Missing 'this.' prefix?")
1543
1544 // Set symbol table entry to used
1545 35992 varEntry->used = true;
1546
1547 // Retrieve scope for the new scope path fragment
1548
3/4
✓ Branch 1 taken 35992 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13524 times.
✓ Branch 4 taken 22468 times.
35992 if (baseType.is(TY_STRUCT)) {
1549 // Set access scope to struct scope
1550
1/2
✓ Branch 1 taken 13524 times.
✗ Branch 2 not taken.
13524 const std::string &structName = baseType.getSubType();
1551
1/2
✓ Branch 1 taken 13524 times.
✗ Branch 2 not taken.
13524 const NameRegistryEntry *nameRegistryEntry = sourceFile->getNameRegistryEntry(structName);
1552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13524 times.
13524 assert(nameRegistryEntry != nullptr);
1553
1554 // Change the access scope to the struct scope
1555 13524 data.accessScope = accessScope = nameRegistryEntry->targetScope;
1556
1557 // Check if the entry is public if it is imported
1558
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13524 times.
13524 assert(nameRegistryEntry->targetEntry != nullptr);
1559
9/12
✓ Branch 1 taken 13524 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13524 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 801 times.
✓ Branch 7 taken 12723 times.
✓ Branch 9 taken 801 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 800 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 13523 times.
13524 if (!nameRegistryEntry->targetEntry->getQualType().isPublic() && accessScope->parent->isImportedBy(rootScope))
1560
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Cannot access struct '" + structName + "' due to its private visibility")
1561 }
1562
1563
2/4
✓ Branch 1 taken 35991 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35991 times.
✗ Branch 5 not taken.
35991 return ExprResult{node->setEvaluatedSymbolType(varType, manIdx), varEntry};
1564 }
1565
1566 11362 std::any TypeChecker::visitValue(ValueNode *node) {
1567 // Function call
1568
2/2
✓ Branch 0 taken 10118 times.
✓ Branch 1 taken 1244 times.
11362 if (node->fctCall)
1569 10118 return visit(node->fctCall);
1570
1571 // Array initialization
1572
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 1177 times.
1244 if (node->arrayInitialization)
1573 67 return visit(node->arrayInitialization);
1574
1575 // Struct instantiation
1576
2/2
✓ Branch 0 taken 177 times.
✓ Branch 1 taken 1000 times.
1177 if (node->structInstantiation)
1577 177 return visit(node->structInstantiation);
1578
1579 // Lambda function
1580
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 991 times.
1000 if (node->lambdaFunc)
1581 9 return visit(node->lambdaFunc);
1582
1583 // Lambda procedure
1584
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 963 times.
991 if (node->lambdaProc)
1585 28 return visit(node->lambdaProc);
1586
1587 // Lambda expression
1588
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 962 times.
963 if (node->lambdaExpr)
1589 1 return visit(node->lambdaExpr);
1590
1591 // Typed nil
1592
1/2
✓ Branch 0 taken 962 times.
✗ Branch 1 not taken.
962 if (node->isNil) {
1593
2/4
✓ Branch 1 taken 962 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 962 times.
✗ Branch 5 not taken.
962 const auto nilType = std::any_cast<QualType>(visit(node->nilType));
1594
2/10
✓ Branch 1 taken 962 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 962 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
962 HANDLE_UNRESOLVED_TYPE_ER(nilType)
1595
2/4
✓ Branch 1 taken 962 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 962 times.
962 if (nilType.is(TY_DYN))
1596 SOFT_ERROR_ER(node->nilType, UNEXPECTED_DYN_TYPE, "Nil must have an explicit type")
1597
2/4
✓ Branch 1 taken 962 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 962 times.
✗ Branch 5 not taken.
962 return ExprResult{node->setEvaluatedSymbolType(nilType, manIdx)};
1598 }
1599
1600 throw CompilerError(UNHANDLED_BRANCH, "Value fall-through"); // GCOV_EXCL_LINE
1601 }
1602
1603 15839 std::any TypeChecker::visitConstant(ConstantNode *node) {
1604 SuperType superType;
1605
7/9
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 2846 times.
✓ Branch 2 taken 190 times.
✓ Branch 3 taken 6012 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 617 times.
✓ Branch 6 taken 2202 times.
✓ Branch 7 taken 3767 times.
✗ Branch 8 not taken.
15839 switch (node->type) {
1606 205 case ConstantNode::TYPE_DOUBLE:
1607 205 superType = TY_DOUBLE;
1608 205 break;
1609 2846 case ConstantNode::TYPE_INT:
1610 2846 superType = TY_INT;
1611 2846 break;
1612 190 case ConstantNode::TYPE_SHORT:
1613 190 superType = TY_SHORT;
1614 190 break;
1615 6012 case ConstantNode::TYPE_LONG:
1616 6012 superType = TY_LONG;
1617 6012 break;
1618 case ConstantNode::TYPE_BYTE:
1619 superType = TY_BYTE;
1620 break;
1621 617 case ConstantNode::TYPE_CHAR:
1622 617 superType = TY_CHAR;
1623 617 break;
1624 2202 case ConstantNode::TYPE_STRING:
1625 2202 superType = TY_STRING;
1626 2202 break;
1627 3767 case ConstantNode::TYPE_BOOL:
1628 3767 superType = TY_BOOL;
1629 3767 break;
1630 default: // GCOV_EXCL_LINE
1631 throw CompilerError(UNHANDLED_BRANCH, "Constant fall-through"); // GCOV_EXCL_LINE
1632 }
1633
1634 // Create symbol type
1635
1/2
✓ Branch 1 taken 15839 times.
✗ Branch 2 not taken.
15839 QualType symbolType(superType);
1636
1/2
✓ Branch 1 taken 15839 times.
✗ Branch 2 not taken.
15839 symbolType.setSpecifiers(TypeSpecifiers::of(superType));
1637
1638
2/4
✓ Branch 1 taken 15839 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15839 times.
✗ Branch 5 not taken.
15839 return ExprResult{node->setEvaluatedSymbolType(symbolType, manIdx)};
1639 }
1640
1641 10118 std::any TypeChecker::visitFctCall(FctCallNode *node) {
1642
1/2
✓ Branch 1 taken 10118 times.
✗ Branch 2 not taken.
10118 FctCallNode::FctCallData &data = node->data.at(manIdx);
1643
1644 // Retrieve arg types
1645 10118 data.argResults.clear();
1646
2/2
✓ Branch 0 taken 7503 times.
✓ Branch 1 taken 2615 times.
10118 if (node->hasArgs) {
1647
1/2
✓ Branch 2 taken 7503 times.
✗ Branch 3 not taken.
7503 data.argResults.reserve(node->argLst->args.size());
1648
2/2
✓ Branch 5 taken 11157 times.
✓ Branch 6 taken 7503 times.
18660 for (AssignExprNode *arg : node->argLst->args) {
1649 // Visit argument
1650
2/4
✓ Branch 1 taken 11157 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11157 times.
✗ Branch 5 not taken.
11157 const auto argResult = std::any_cast<ExprResult>(visit(arg));
1651
2/10
✓ Branch 1 taken 11157 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 11157 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
11157 HANDLE_UNRESOLVED_TYPE_ER(argResult.type)
1652
2/4
✓ Branch 1 taken 11157 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 11157 times.
11157 assert(!argResult.type.hasAnyGenericParts());
1653 // Save arg type to arg types list
1654
1/2
✓ Branch 1 taken 11157 times.
✗ Branch 2 not taken.
11157 data.argResults.push_back(argResult);
1655 }
1656 }
1657
1658 // Retrieve entry of the first fragment
1659 10118 const std::string &firstFrag = node->functionNameFragments.front();
1660
1/2
✓ Branch 1 taken 10118 times.
✗ Branch 2 not taken.
10118 SymbolTableEntry *firstFragEntry = currentScope->lookup(firstFrag);
1661
2/2
✓ Branch 0 taken 7161 times.
✓ Branch 1 taken 2957 times.
10118 if (firstFragEntry) {
1662 // Check if we have seen a 'this.' prefix, because the generator needs that
1663
6/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7160 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 7160 times.
7161 if (firstFragEntry->scope->type == ScopeType::STRUCT && firstFrag != THIS_VARIABLE_NAME)
1664
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE,
1665 "The symbol '" + firstFrag + "' could not be found. Missing 'this.' prefix?")
1666
1667 7160 firstFragEntry->used = true;
1668 // Decide of which type the function call is
1669
2/4
✓ Branch 1 taken 7160 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7160 times.
✗ Branch 5 not taken.
7160 const QualType &baseType = firstFragEntry->getQualType().getBase();
1670
6/10
✓ Branch 1 taken 7160 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 7156 times.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
7160 HANDLE_UNRESOLVED_TYPE_ER(baseType)
1671
3/4
✓ Branch 1 taken 7156 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5500 times.
✓ Branch 4 taken 1656 times.
7156 if (baseType.isOneOf({TY_STRUCT, TY_INTERFACE})) {
1672
2/2
✓ Branch 0 taken 751 times.
✓ Branch 1 taken 4749 times.
5500 data.callType = firstFragEntry->scope->type == ScopeType::GLOBAL ? FctCallNode::TYPE_CTOR : FctCallNode::TYPE_METHOD;
1673
7/8
✓ Branch 1 taken 1656 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1590 times.
✓ Branch 4 taken 66 times.
✓ Branch 5 taken 39 times.
✓ Branch 6 taken 1551 times.
✓ Branch 7 taken 39 times.
✓ Branch 8 taken 1617 times.
1656 } else if (baseType.isOneOf({TY_FUNCTION, TY_PROCEDURE}) && firstFragEntry->scope->type != ScopeType::GLOBAL) {
1674 39 data.callType = FctCallNode::TYPE_FCT_PTR;
1675 }
1676 }
1677
1678 // Get struct name. Retrieve it from alias if required
1679
1/2
✓ Branch 1 taken 10113 times.
✗ Branch 2 not taken.
10113 std::string fqFunctionName = node->fqFunctionName;
1680
1/2
✓ Branch 1 taken 10113 times.
✗ Branch 2 not taken.
10113 SymbolTableEntry *aliasEntry = rootScope->lookupStrict(fqFunctionName);
1681 10113 SymbolTableEntry *aliasedTypeContainerEntry = nullptr;
1682
6/8
✓ Branch 0 taken 2304 times.
✓ Branch 1 taken 7809 times.
✓ Branch 3 taken 2304 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2304 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 2303 times.
10113 const bool isAliasType = aliasEntry && aliasEntry->getQualType().is(TY_ALIAS);
1683
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10112 times.
10113 if (isAliasType) {
1684
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 aliasedTypeContainerEntry = rootScope->lookupStrict(aliasEntry->name + ALIAS_CONTAINER_SUFFIX);
1685
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(aliasedTypeContainerEntry != nullptr);
1686 // Set alias entry used
1687 1 aliasEntry->used = true;
1688
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 fqFunctionName = aliasedTypeContainerEntry->getQualType().getSubType();
1689 }
1690
1691 // Get the concrete template types
1692 10113 QualTypeList concreteTemplateTypes;
1693
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10112 times.
10113 if (isAliasType) {
1694 // Retrieve concrete template types from type alias
1695
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 concreteTemplateTypes = aliasedTypeContainerEntry->getQualType().getTemplateTypes();
1696 // Check if the aliased type specified template types and the struct instantiation does
1697
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1 if (!concreteTemplateTypes.empty() && node->hasTemplateTypes)
1698 SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list")
1699 }
1700
1701 // Get concrete template types
1702
2/2
✓ Branch 0 taken 419 times.
✓ Branch 1 taken 9694 times.
10113 if (node->hasTemplateTypes) {
1703
2/2
✓ Branch 5 taken 498 times.
✓ Branch 6 taken 419 times.
917 for (DataTypeNode *templateTypeNode : node->templateTypeLst->dataTypes) {
1704
2/4
✓ Branch 1 taken 498 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 498 times.
✗ Branch 5 not taken.
498 auto templateType = std::any_cast<QualType>(visit(templateTypeNode));
1705
2/4
✓ Branch 1 taken 498 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 498 times.
498 assert(!templateType.isOneOf({TY_DYN, TY_INVALID}));
1706
1707 // Abort if the type is unresolved
1708
2/4
✓ Branch 1 taken 498 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 498 times.
498 if (templateType.is(TY_UNRESOLVED))
1709 HANDLE_UNRESOLVED_TYPE_ER(templateType)
1710
1711 // Check if the given type is generic
1712
2/4
✓ Branch 1 taken 498 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 498 times.
498 if (templateType.is(TY_GENERIC))
1713 SOFT_ERROR_ER(templateTypeNode, EXPECTED_NON_GENERIC_TYPE, "You must specify a concrete type here")
1714
1715
1/2
✓ Branch 1 taken 498 times.
✗ Branch 2 not taken.
498 concreteTemplateTypes.push_back(templateType);
1716 }
1717 }
1718
1719 // Check if this is a method call or a normal function call
1720
2/2
✓ Branch 1 taken 4749 times.
✓ Branch 2 taken 5364 times.
10113 if (data.isMethodCall()) {
1721 // This is a method call
1722
1/2
✓ Branch 1 taken 4749 times.
✗ Branch 2 not taken.
4749 data.thisType = firstFragEntry->getQualType();
1723
2/4
✓ Branch 1 taken 4749 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4749 times.
✗ Branch 5 not taken.
4749 Scope *structBodyScope = data.thisType.getBase().getBodyScope();
1724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4749 times.
4749 assert(structBodyScope != nullptr);
1725
3/4
✓ Branch 1 taken 4749 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 4747 times.
4749 if (bool success = visitMethodCall(node, structBodyScope, concreteTemplateTypes); !success) // Check if soft errors occurred
1726
3/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
2 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
1727
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4747 times.
4747 assert(data.calleeParentScope != nullptr);
1728
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 5325 times.
5364 } else if (data.isFctPtrCall()) {
1729 // This is a function pointer call
1730
2/4
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 39 times.
✗ Branch 5 not taken.
39 const QualType &functionType = firstFragEntry->getQualType().getBase();
1731
2/4
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 39 times.
39 assert(functionType.isOneOf({TY_FUNCTION, TY_PROCEDURE}));
1732
1/2
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
39 bool success = visitFctPtrCall(node, functionType);
1733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 if (!success) // Check if soft errors occurred
1734 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
1735 } else {
1736 // This is an ordinary function call
1737
3/4
✓ Branch 1 taken 751 times.
✓ Branch 2 taken 4574 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 751 times.
5325 assert(data.isOrdinaryCall() || data.isCtorCall());
1738
3/4
✓ Branch 1 taken 5325 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5323 times.
✓ Branch 5 taken 2 times.
5327 bool success = visitOrdinaryFctCall(node, concreteTemplateTypes, fqFunctionName);
1739
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5319 times.
5323 if (!success) // Check if soft errors occurred
1740
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
4 return ExprResult{node->setEvaluatedSymbolType(QualType(TY_UNRESOLVED), manIdx)};
1741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5319 times.
5319 assert(data.calleeParentScope != nullptr);
1742
1743 // Only ordinary function calls can be constructors
1744
2/2
✓ Branch 1 taken 1448 times.
✓ Branch 2 taken 3871 times.
5319 if (data.isCtorCall()) {
1745
2/4
✓ Branch 1 taken 1448 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1448 times.
1448 assert(data.thisType.is(TY_STRUCT));
1746 }
1747 }
1748
1749
2/2
✓ Branch 1 taken 10066 times.
✓ Branch 2 taken 39 times.
10105 if (!data.isFctPtrCall()) {
1750 // Check if we were able to find a function
1751
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10054 times.
10066 if (!data.callee) {
1752 // Build error message
1753
6/10
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 10 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 10 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
14 const std::string functionName = data.isCtorCall() ? CTOR_FUNCTION_NAME : node->functionNameFragments.back();
1754 12 ParamList errArgTypes;
1755
1/2
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 errArgTypes.reserve(data.argResults.size());
1756
2/2
✓ Branch 4 taken 7 times.
✓ Branch 5 taken 12 times.
19 for (const auto &[type, _] : data.argResults)
1757
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 errArgTypes.push_back({type, false});
1758
2/4
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
12 const std::string signature = Function::getSignature(functionName, data.thisType, QualType(TY_DYN), errArgTypes, {}, false);
1759 // Throw error
1760
6/12
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 12 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 12 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 12 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 12 times.
✗ Branch 19 not taken.
12 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_FUNCTION, "Function/procedure '" + signature + "' could not be found")
1761 12 }
1762
1763 // Check if we need to request a re-visit, because the function body was not type-checked yet
1764
1/2
✓ Branch 1 taken 10054 times.
✗ Branch 2 not taken.
10054 requestRevisitIfRequired(data.callee);
1765
1766 // Get function entry from function object
1767 10054 SymbolTableEntry *functionEntry = data.callee->entry;
1768
1769 // Check if the called function has sufficient visibility
1770
1/2
✓ Branch 1 taken 10054 times.
✗ Branch 2 not taken.
10054 data.isImported = data.calleeParentScope->isImportedBy(rootScope);
1771
8/10
✓ Branch 0 taken 2749 times.
✓ Branch 1 taken 7305 times.
✓ Branch 3 taken 2749 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 2749 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 2748 times.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 10053 times.
10054 if (data.isImported && !functionEntry->getQualType().isPublic()) {
1772
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType functionEntryType = functionEntry->getQualType();
1773
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const std::string signature = data.callee->getSignature();
1774
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 if (functionEntryType.is(TY_FUNCTION))
1775
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Function '" + signature + "' has insufficient visibility")
1776 else
1777 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Procedure '" + signature + "' has insufficient visibility")
1778 1 }
1779 }
1780
1781 // Retrieve return type
1782
6/10
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 10053 times.
✓ Branch 4 taken 39 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 39 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 39 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 10053 times.
✗ Branch 14 not taken.
20145 const bool isFct = data.isFctPtrCall() ? firstFragEntry->getQualType().getBase().is(TY_FUNCTION) : data.callee->isFunction();
1783 10092 QualType returnType;
1784
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 10053 times.
10092 if (data.isFctPtrCall()) {
1785
6/10
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 28 times.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 11 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 28 times.
✗ Branch 13 not taken.
39 returnType = isFct ? firstFragEntry->getQualType().getBase().getFunctionReturnType() : QualType(TY_BOOL);
1786
2/2
✓ Branch 1 taken 1446 times.
✓ Branch 2 taken 8607 times.
10053 } else if (data.isCtorCall()) {
1787 // Set return type to 'this' type
1788 1446 returnType = data.thisType;
1789
3/4
✓ Branch 1 taken 8607 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2242 times.
✓ Branch 4 taken 6365 times.
17214 } else if (data.callee->isProcedure()) {
1790 // Procedures always have the return type 'dyn'
1791
1/2
✓ Branch 1 taken 2242 times.
✗ Branch 2 not taken.
2242 returnType = QualType(TY_DYN);
1792 } else {
1793 6365 returnType = data.callee->returnType;
1794 }
1795
1796 // Initialize return type if required
1797 10092 SymbolTableEntry *anonymousSymbol = nullptr;
1798
3/4
✓ Branch 1 taken 10092 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2277 times.
✓ Branch 4 taken 7815 times.
10092 if (returnType.isBase(TY_STRUCT)) {
1799
1/2
✓ Branch 1 taken 2277 times.
✗ Branch 2 not taken.
2277 QualType returnBaseType = returnType.getBase();
1800
1/2
✓ Branch 1 taken 2277 times.
✗ Branch 2 not taken.
2277 const std::string &structName = returnBaseType.getSubType();
1801
1/2
✓ Branch 1 taken 2277 times.
✗ Branch 2 not taken.
2277 Scope *matchScope = returnBaseType.getBodyScope()->parent;
1802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2277 times.
2277 assert(matchScope != nullptr);
1803
2/4
✓ Branch 1 taken 2277 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2277 times.
✗ Branch 5 not taken.
2277 Struct *spiceStruct = StructManager::match(matchScope, structName, returnBaseType.getTemplateTypes(), node);
1804
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2277 times.
2277 if (!spiceStruct) {
1805 const std::string signature = Struct::getSignature(structName, returnBaseType.getTemplateTypes());
1806 SOFT_ERROR_ER(node, UNKNOWN_DATATYPE,
1807 "Could not find struct candidate for struct '" + signature + "'. Do the template types match?")
1808 }
1809
2/4
✓ Branch 1 taken 2277 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2277 times.
✗ Branch 5 not taken.
2277 returnType = returnType.getWithBodyScope(spiceStruct->scope).replaceBaseType(returnBaseType);
1810
1811
3/6
✓ Branch 1 taken 2277 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2277 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2277 times.
✗ Branch 8 not taken.
2277 returnType = mapImportedScopeTypeToLocalType(returnType.getBase().getBodyScope(), returnType);
1812
1813 // Add anonymous symbol to keep track of de-allocation
1814
3/4
✓ Branch 1 taken 2277 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2030 times.
✓ Branch 4 taken 247 times.
2277 if (returnType.is(TY_STRUCT))
1815
1/2
✓ Branch 1 taken 2030 times.
✗ Branch 2 not taken.
2030 anonymousSymbol = currentScope->symbolTable.insertAnonymous(returnType, node);
1816 }
1817
1818 // Remove public specifier to not have public local variables
1819 10092 returnType.getSpecifiers().isPublic = false;
1820
1821 // Check if the return value gets used
1822
7/8
✓ Branch 0 taken 6376 times.
✓ Branch 1 taken 3716 times.
✓ Branch 3 taken 6376 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 132 times.
✓ Branch 6 taken 6244 times.
✓ Branch 7 taken 132 times.
✓ Branch 8 taken 9960 times.
10092 if (isFct && !node->hasReturnValueReceiver())
1823
1/2
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
132 warnings.emplace_back(node->codeLoc, UNUSED_RETURN_VALUE, "The return value of the function call is unused");
1824
1825
2/4
✓ Branch 1 taken 10092 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10092 times.
✗ Branch 5 not taken.
10092 return ExprResult{node->setEvaluatedSymbolType(returnType, manIdx), anonymousSymbol};
1826 10115 }
1827
1828 5325 bool TypeChecker::visitOrdinaryFctCall(FctCallNode *node, QualTypeList &templateTypes, std::string fqFunctionName) {
1829
1/2
✓ Branch 1 taken 5325 times.
✗ Branch 2 not taken.
5325 FctCallNode::FctCallData &data = node->data.at(manIdx);
1830
1831 // Check if this is a ctor call to the String type
1832
2/2
✓ Branch 1 taken 5264 times.
✓ Branch 2 taken 61 times.
5325 if (node->functionNameFragments.size() == 1) {
1833
2/2
✓ Branch 7 taken 15792 times.
✓ Branch 8 taken 5264 times.
21056 for (const auto &[typeName, runtimeModule] : TYPE_NAME_TO_RT_MODULE_MAPPING)
1834
8/10
✓ Branch 1 taken 15792 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1087 times.
✓ Branch 4 taken 14705 times.
✓ Branch 6 taken 1087 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 439 times.
✓ Branch 9 taken 648 times.
✓ Branch 10 taken 439 times.
✓ Branch 11 taken 15353 times.
15792 if (fqFunctionName == typeName && !sourceFile->isRT(runtimeModule))
1835
1/2
✓ Branch 1 taken 439 times.
✗ Branch 2 not taken.
439 sourceFile->requestRuntimeModule(runtimeModule);
1836
2/2
✓ Branch 7 taken 57904 times.
✓ Branch 8 taken 5264 times.
63168 for (const auto &[fctName, runtimeModule] : FCT_NAME_TO_RT_MODULE_MAPPING)
1837
8/10
✓ Branch 1 taken 57904 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 377 times.
✓ Branch 4 taken 57527 times.
✓ Branch 6 taken 377 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 369 times.
✓ Branch 9 taken 8 times.
✓ Branch 10 taken 369 times.
✓ Branch 11 taken 57535 times.
57904 if (fqFunctionName == fctName && !sourceFile->isRT(runtimeModule))
1838
1/2
✓ Branch 1 taken 369 times.
✗ Branch 2 not taken.
369 sourceFile->requestRuntimeModule(runtimeModule);
1839 }
1840
1841 // Check if the type is generic (possible in case of ctor call)
1842
1/2
✓ Branch 1 taken 5325 times.
✗ Branch 2 not taken.
5325 const QualType *genericType = rootScope->lookupGenericType(fqFunctionName);
1843
6/8
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5324 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 5324 times.
5325 if (genericType && typeMapping.contains(fqFunctionName)) {
1844
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType &replacementType = typeMapping.at(fqFunctionName);
1845
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 if (replacementType.is(TY_STRUCT))
1846
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 fqFunctionName = replacementType.getSubType();
1847 }
1848
1849 // Check if the exported name registry contains that function name
1850
1/2
✓ Branch 1 taken 5325 times.
✗ Branch 2 not taken.
5325 const NameRegistryEntry *functionRegistryEntry = sourceFile->getNameRegistryEntry(fqFunctionName);
1851
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5322 times.
5325 if (!functionRegistryEntry) {
1852
2/4
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
3 const std::string msg = "Function/procedure/struct '" + node->functionNameFragments.back() + "' could not be found";
1853
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, msg)
1854 3 }
1855 5322 const SymbolTableEntry *functionEntry = functionRegistryEntry->targetEntry;
1856 5322 data.calleeParentScope = functionRegistryEntry->targetScope;
1857
1858 // Check if the target symbol is a struct -> this must be a constructor call
1859
7/10
✓ Branch 0 taken 5322 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 5322 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 5322 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1449 times.
✓ Branch 9 taken 3873 times.
✓ Branch 10 taken 1449 times.
✓ Branch 11 taken 3873 times.
5322 if (functionEntry != nullptr && functionEntry->getQualType().is(TY_STRUCT))
1860 1449 data.callType = FctCallNode::TYPE_CTOR;
1861
1862 // For constructor calls, do some preparation
1863
1/2
✓ Branch 2 taken 5322 times.
✗ Branch 3 not taken.
5322 std::string functionName = node->functionNameFragments.back();
1864
2/2
✓ Branch 1 taken 1449 times.
✓ Branch 2 taken 3873 times.
5322 if (data.isCtorCall()) {
1865 1449 const NameRegistryEntry *structRegistryEntry = functionRegistryEntry;
1866 1449 const SymbolTableEntry *structEntry = functionEntry;
1867
1/2
✓ Branch 1 taken 1449 times.
✗ Branch 2 not taken.
1449 const std::string structName = structRegistryEntry->targetEntry->name;
1868
1869 // Substantiate potentially generic this struct
1870
1/2
✓ Branch 1 taken 1449 times.
✗ Branch 2 not taken.
1449 const Struct *thisStruct = StructManager::match(structEntry->scope, structName, templateTypes, node);
1871
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1448 times.
1449 if (!thisStruct) {
1872
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const std::string signature = Struct::getSignature(structName, templateTypes);
1873
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 SOFT_ERROR_BOOL(node, UNKNOWN_DATATYPE,
1874 "Could not find struct candidate for struct '" + signature + "'. Do the template types match?")
1875 1 }
1876
1877 // Override function name
1878
1/2
✓ Branch 1 taken 1448 times.
✗ Branch 2 not taken.
1448 functionName = CTOR_FUNCTION_NAME;
1879
1880 // Set the 'this' type of the function to the struct type
1881
2/4
✓ Branch 1 taken 1448 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1448 times.
✗ Branch 5 not taken.
1448 data.thisType = structEntry->getQualType().getWithBodyScope(thisStruct->scope);
1882 1448 data.calleeParentScope = thisStruct->scope;
1883
2/2
✓ Branch 1 taken 1448 times.
✓ Branch 2 taken 1 times.
1449 }
1884
1885 // Attach the concrete template types to the 'this' type
1886
7/8
✓ Branch 1 taken 5321 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1448 times.
✓ Branch 4 taken 3873 times.
✓ Branch 6 taken 295 times.
✓ Branch 7 taken 1153 times.
✓ Branch 8 taken 295 times.
✓ Branch 9 taken 5026 times.
5321 if (!data.thisType.is(TY_DYN) && !templateTypes.empty())
1887
1/2
✓ Branch 1 taken 295 times.
✗ Branch 2 not taken.
295 data.thisType = data.thisType.getWithTemplateTypes(templateTypes);
1888
1889 // Map local arg types to imported types
1890 5321 ArgList localArgs;
1891
1/2
✓ Branch 2 taken 5321 times.
✗ Branch 3 not taken.
5321 localArgs.reserve(data.argResults.size());
1892
2/2
✓ Branch 4 taken 7751 times.
✓ Branch 5 taken 5321 times.
13072 for (const ExprResult &argResult : data.argResults)
1893
2/4
✓ Branch 2 taken 7751 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7751 times.
✗ Branch 6 not taken.
7751 localArgs.emplace_back(mapLocalTypeToImportedScopeType(data.calleeParentScope, argResult.type), argResult.isTemporary());
1894
1895 // Map local template types to imported types
1896
2/2
✓ Branch 4 taken 499 times.
✓ Branch 5 taken 5321 times.
5820 for (QualType &templateType : templateTypes)
1897
1/2
✓ Branch 1 taken 499 times.
✗ Branch 2 not taken.
499 templateType = mapLocalTypeToImportedScopeType(data.calleeParentScope, templateType);
1898
1899 // Retrieve function object
1900 5321 Scope *matchScope = data.calleeParentScope;
1901
2/2
✓ Branch 1 taken 5319 times.
✓ Branch 2 taken 2 times.
5321 data.callee = FunctionManager::match(this, matchScope, functionName, data.thisType, localArgs, templateTypes, false, node);
1902
1903 5319 return true;
1904 5324 }
1905
1906 39 bool TypeChecker::visitFctPtrCall(const FctCallNode *node, const QualType &functionType) const {
1907
1/2
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
39 const auto &[callType, isImported, thisType, argResults, callee, calleeParentScope] = node->data.at(manIdx);
1908
1909 // Check if the given argument types match the type
1910
1/2
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
39 const QualTypeList expectedArgTypes = functionType.getFunctionParamTypes();
1911
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 39 times.
39 if (argResults.size() != expectedArgTypes.size())
1912 SOFT_ERROR_BOOL(node, REFERENCED_UNDEFINED_FUNCTION, "Expected and actual number of arguments do not match")
1913
1914 // Create resolver function, that always returns a nullptr
1915 39 TypeMatcher::ResolverFct resolverFct = [](const std::string &genericTypeName) { return nullptr; };
1916
1917
2/2
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 39 times.
70 for (size_t i = 0; i < argResults.size(); i++) {
1918
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 const QualType &actualType = argResults.at(i).type;
1919
1/2
✓ Branch 1 taken 31 times.
✗ Branch 2 not taken.
31 const QualType &expectedType = expectedArgTypes.at(i);
1920
2/4
✓ Branch 2 taken 31 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 31 times.
31 if (TypeMapping tm; !TypeMatcher::matchRequestedToCandidateType(expectedType, actualType, tm, resolverFct, false))
1921
1/16
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 31 times.
✗ Branch 28 not taken.
31 SOFT_ERROR_BOOL(node->argLst->args.at(i), REFERENCED_UNDEFINED_FUNCTION,
1922 "Expected " + expectedType.getName(false) + " but got " + actualType.getName(false))
1923 }
1924 39 return true;
1925 39 }
1926
1927 4749 bool TypeChecker::visitMethodCall(FctCallNode *node, Scope *structScope, QualTypeList &templateTypes) {
1928
1/2
✓ Branch 1 taken 4749 times.
✗ Branch 2 not taken.
4749 auto &[callType, isImported, thisType, argResults, callee, calleeParentScope] = node->data.at(manIdx);
1929
1930 // Traverse through structs - the first fragment is already looked up and the last one is the method name
1931
2/2
✓ Branch 1 taken 628 times.
✓ Branch 2 taken 4747 times.
5375 for (size_t i = 1; i < node->functionNameFragments.size() - 1; i++) {
1932
2/4
✓ Branch 1 taken 628 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 628 times.
✗ Branch 5 not taken.
628 const std::string &identifier = node->functionNameFragments.at(i);
1933
1934 // Retrieve field entry
1935 628 SymbolTableEntry *fieldEntry = structScope->lookupStrict(identifier);
1936
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 627 times.
628 if (!fieldEntry) {
1937
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 const std::string name = thisType.getBase().getName(false, true);
1938
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
1 SOFT_ERROR_BOOL(node, ACCESS_TO_NON_EXISTING_MEMBER,
1939 "The type '" + name + "' does not have a member with the name '" + identifier + "'")
1940 1 }
1941
5/8
✓ Branch 1 taken 627 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 627 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 627 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 626 times.
627 if (!fieldEntry->getQualType().getBase().isOneOf({TY_STRUCT, TY_INTERFACE}))
1942
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS,
1943 "Cannot call a method on '" + identifier + "', since it is no struct or interface")
1944 626 fieldEntry->used = true;
1945
1946 // Get struct type and scope
1947
1/2
✓ Branch 1 taken 626 times.
✗ Branch 2 not taken.
626 thisType = fieldEntry->getQualType();
1948
2/4
✓ Branch 1 taken 626 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 626 times.
✗ Branch 5 not taken.
626 structScope = thisType.getBase().getBodyScope();
1949
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 626 times.
626 assert(structScope != nullptr);
1950 }
1951
1952
2/4
✓ Branch 1 taken 4747 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4747 times.
4747 if (thisType.is(TY_INTERFACE))
1953 SOFT_ERROR_BOOL(node, INVALID_MEMBER_ACCESS, "Cannot call a method on an interface")
1954
1955 // Map local arg types to imported types
1956 4747 Scope *matchScope = calleeParentScope = structScope;
1957 4747 ArgList localArgs;
1958
2/2
✓ Branch 4 taken 3369 times.
✓ Branch 5 taken 4747 times.
8116 for (const ExprResult &argResult : argResults)
1959
2/4
✓ Branch 2 taken 3369 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3369 times.
✗ Branch 6 not taken.
3369 localArgs.emplace_back(mapLocalTypeToImportedScopeType(calleeParentScope, argResult.type), argResult.isTemporary());
1960
1961 // Map local template types to imported types
1962
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 4747 times.
4747 for (QualType &templateType : templateTypes)
1963 templateType = mapLocalTypeToImportedScopeType(calleeParentScope, templateType);
1964
1965 // 'this' type
1966 4747 QualType localThisType = thisType;
1967
1/2
✓ Branch 1 taken 4747 times.
✗ Branch 2 not taken.
4747 autoDeReference(localThisType);
1968
1/2
✓ Branch 1 taken 4747 times.
✗ Branch 2 not taken.
4747 localThisType = mapLocalTypeToImportedScopeType(calleeParentScope, localThisType);
1969
1970 // Retrieve function object
1971 4747 const std::string &functionName = node->functionNameFragments.back();
1972
1/2
✓ Branch 1 taken 4747 times.
✗ Branch 2 not taken.
4747 callee = FunctionManager::match(this, matchScope, functionName, localThisType, localArgs, templateTypes, false, node);
1973
1974 4747 return true;
1975 4747 }
1976
1977 67 std::any TypeChecker::visitArrayInitialization(ArrayInitializationNode *node) {
1978
1/2
✓ Branch 1 taken 67 times.
✗ Branch 2 not taken.
67 QualType actualItemType(TY_DYN);
1979 // Check if all values have the same type
1980
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 2 times.
67 if (node->itemLst) {
1981 65 node->actualSize = static_cast<long>(node->itemLst->args.size());
1982
2/2
✓ Branch 5 taken 435 times.
✓ Branch 6 taken 64 times.
499 for (AssignExprNode *arg : node->itemLst->args) {
1983
2/4
✓ Branch 1 taken 435 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 435 times.
✗ Branch 5 not taken.
435 const QualType itemType = std::any_cast<ExprResult>(visit(arg)).type;
1984
2/10
✓ Branch 1 taken 435 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 435 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
435 HANDLE_UNRESOLVED_TYPE_ER(itemType)
1985
3/4
✓ Branch 1 taken 435 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 65 times.
✓ Branch 4 taken 370 times.
435 if (actualItemType.is(TY_DYN)) // Perform type inference
1986 65 actualItemType = itemType;
1987
3/4
✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 369 times.
370 else if (itemType != actualItemType) // Check if types are matching
1988
9/18
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 30 taken 1 times.
✗ Branch 31 not taken.
1 SOFT_ERROR_ER(arg, ARRAY_ITEM_TYPE_NOT_MATCHING,
1989 "All provided values have to be of the same data type. You provided " + actualItemType.getName(false) +
1990 " and " + itemType.getName(false))
1991 }
1992 }
1993
1994
1/2
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
66 const QualType arrayType = actualItemType.toArray(node, node->actualSize, true);
1995
2/4
✓ Branch 1 taken 66 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 66 times.
✗ Branch 5 not taken.
66 return ExprResult{node->setEvaluatedSymbolType(arrayType, manIdx)};
1996 }
1997
1998 177 std::any TypeChecker::visitStructInstantiation(StructInstantiationNode *node) {
1999 // Get struct name. Retrieve it from alias if required
2000
1/2
✓ Branch 1 taken 177 times.
✗ Branch 2 not taken.
177 std::string structName = node->fqStructName;
2001
1/2
✓ Branch 1 taken 177 times.
✗ Branch 2 not taken.
177 SymbolTableEntry *aliasEntry = rootScope->lookupStrict(structName);
2002 177 SymbolTableEntry *aliasedTypeContainerEntry = nullptr;
2003
6/8
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 6 times.
✓ Branch 3 taken 171 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 171 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 170 times.
177 const bool isAliasType = aliasEntry && aliasEntry->getQualType().is(TY_ALIAS);
2004
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 176 times.
177 if (isAliasType) {
2005
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 aliasedTypeContainerEntry = rootScope->lookupStrict(aliasEntry->name + ALIAS_CONTAINER_SUFFIX);
2006
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(aliasedTypeContainerEntry != nullptr);
2007 // Set alias entry used
2008 1 aliasEntry->used = true;
2009
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 structName = aliasedTypeContainerEntry->getQualType().getSubType();
2010 }
2011
2012 // Check if access scope was altered
2013
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 177 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
177 if (accessScope != nullptr && accessScope != currentScope)
2014 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT, "Cannot find struct '" + structName + "'")
2015
2016 // Retrieve struct
2017
1/2
✓ Branch 1 taken 177 times.
✗ Branch 2 not taken.
177 const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(structName);
2018
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 176 times.
177 if (!registryEntry)
2019
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
1 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT, "Cannot find struct '" + structName + "'")
2020
2/4
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 176 times.
✗ Branch 3 not taken.
176 assert(registryEntry->targetEntry != nullptr && registryEntry->targetScope != nullptr);
2021 176 SymbolTableEntry *structEntry = registryEntry->targetEntry;
2022 176 Scope *structScope = accessScope = registryEntry->targetScope;
2023
2024 // Get struct type
2025
1/2
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
176 QualType structType = structEntry->getQualType();
2026
2027 // Get the concrete template types
2028 176 QualTypeList concreteTemplateTypes;
2029
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 175 times.
176 if (isAliasType) {
2030 // Retrieve concrete template types from type alias
2031
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 concreteTemplateTypes = aliasedTypeContainerEntry->getQualType().getTemplateTypes();
2032 // Check if the aliased type specified template types and the struct instantiation does
2033
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1 if (!concreteTemplateTypes.empty() && node->templateTypeLst)
2034 SOFT_ERROR_ER(node->templateTypeLst, ALIAS_WITH_TEMPLATE_LIST, "The aliased type already has a template list")
2035 }
2036
2037
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 162 times.
176 if (node->templateTypeLst) {
2038
1/2
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 concreteTemplateTypes.reserve(node->templateTypeLst->dataTypes.size());
2039
2/2
✓ Branch 5 taken 21 times.
✓ Branch 6 taken 14 times.
35 for (DataTypeNode *dataType : node->templateTypeLst->dataTypes) {
2040
2/4
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
21 auto concreteType = std::any_cast<QualType>(visit(dataType));
2041
2/10
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
21 HANDLE_UNRESOLVED_TYPE_ER(concreteType)
2042 // Check if generic type
2043
2/4
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 21 times.
21 if (concreteType.is(TY_GENERIC))
2044 SOFT_ERROR_ER(dataType, EXPECTED_NON_GENERIC_TYPE, "Struct instantiations may only take concrete template types")
2045
1/2
✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
21 concreteTemplateTypes.push_back(concreteType);
2046 }
2047 }
2048
2049 // Get the struct instance
2050
1/2
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
176 structName = structEntry->name;
2051
1/2
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
176 Struct *spiceStruct = StructManager::match(structScope->parent, structName, concreteTemplateTypes, node);
2052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176 times.
176 if (!spiceStruct) {
2053 const std::string structSignature = Struct::getSignature(structName, concreteTemplateTypes);
2054 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_STRUCT, "Struct '" + structSignature + "' could not be found")
2055 }
2056
1/2
✓ Branch 1 taken 176 times.
✗ Branch 2 not taken.
176 node->instantiatedStructs.at(manIdx) = spiceStruct;
2057
2058 // Struct instantiation for an inheriting struct is forbidden, because the vtable needs to be initialized and this is done in
2059 // the ctor of the struct, which is never called in case of struct instantiation
2060
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 175 times.
176 if (!spiceStruct->interfaceTypes.empty())
2061
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node, INVALID_STRUCT_INSTANTIATION, "Struct instantiations for inheriting structs are forbidden")
2062
2063 // Use scope of concrete substantiation and not the scope of the generic type
2064 175 structScope = spiceStruct->scope;
2065
1/2
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
175 structType = structType.getWithBodyScope(structScope);
2066
2067 // Set template types to the struct
2068 175 QualTypeList templateTypes;
2069
2/2
✓ Branch 5 taken 22 times.
✓ Branch 6 taken 175 times.
197 for (const GenericType &genericType : spiceStruct->templateTypes)
2070
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 templateTypes.emplace_back(genericType);
2071
1/2
✓ Branch 1 taken 175 times.
✗ Branch 2 not taken.
175 structType = structType.getWithTemplateTypes(templateTypes);
2072
2073 // Check if the number of fields matches
2074
2/2
✓ Branch 0 taken 161 times.
✓ Branch 1 taken 14 times.
175 if (node->fieldLst) { // Check if any fields are passed. Empty braces are also allowed
2075
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 160 times.
161 if (spiceStruct->fieldTypes.size() != node->fieldLst->args.size())
2076
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node->fieldLst, NUMBER_OF_FIELDS_NOT_MATCHING,
2077 "You've passed too less/many field values. Pass either none or all of them")
2078
2079 // Check if the field types are matching
2080 160 const size_t fieldCount = spiceStruct->fieldTypes.size();
2081
1/2
✓ Branch 1 taken 160 times.
✗ Branch 2 not taken.
160 const size_t explicitFieldsStartIdx = structScope->getFieldCount() - fieldCount;
2082
2/2
✓ Branch 1 taken 245 times.
✓ Branch 2 taken 159 times.
404 for (size_t i = 0; i < node->fieldLst->args.size(); i++) {
2083 // Get actual type
2084
1/2
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
245 AssignExprNode *assignExpr = node->fieldLst->args.at(i);
2085
2/4
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 245 times.
✗ Branch 5 not taken.
245 auto fieldResult = std::any_cast<ExprResult>(visit(assignExpr));
2086
2/10
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 245 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
245 HANDLE_UNRESOLVED_TYPE_ER(fieldResult.type)
2087 // Get expected type
2088
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 SymbolTableEntry *expectedField = structScope->lookupField(explicitFieldsStartIdx + i);
2089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 245 times.
245 assert(expectedField != nullptr);
2090
1/2
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
245 const ExprResult expected = {expectedField->getQualType(), expectedField};
2091
1/2
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
245 const bool rhsIsImmediate = assignExpr->hasCompileTimeValue();
2092
2093 // Check if actual type matches expected type
2094
2/2
✓ Branch 1 taken 244 times.
✓ Branch 2 taken 1 times.
245 (void)opRuleManager.getFieldAssignResultType(assignExpr, expected, fieldResult, rhsIsImmediate, true);
2095
2096 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it
2097
4/4
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 175 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 68 times.
244 if (fieldResult.entry != nullptr && fieldResult.entry->anonymous) {
2098
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 currentScope->symbolTable.deleteAnonymous(fieldResult.entry->name);
2099 1 fieldResult.entry = nullptr;
2100 }
2101 }
2102 } else {
2103
2/2
✓ Branch 5 taken 43 times.
✓ Branch 6 taken 14 times.
57 for (QualType &fieldType : spiceStruct->fieldTypes) {
2104
2/4
✓ Branch 1 taken 43 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 43 times.
43 if (fieldType.isRef())
2105 SOFT_ERROR_ER(node, REFERENCE_WITHOUT_INITIALIZER,
2106 "The struct takes at least one reference field. You need to instantiate it with all fields.")
2107 }
2108 }
2109
2110 // Update type of struct entry
2111
1/2
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
173 structEntry->updateType(structType, true);
2112
2113 // If not all values are constant, insert anonymous symbol to keep track of dtor calls for de-allocation
2114 173 SymbolTableEntry *anonymousEntry = nullptr;
2115
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 14 times.
173 if (node->fieldLst != nullptr)
2116
3/4
✓ Branch 1 taken 159 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 134 times.
✓ Branch 4 taken 25 times.
357 if (std::ranges::any_of(node->fieldLst->args, [](const AssignExprNode *field) { return !field->hasCompileTimeValue(); }))
2117
1/2
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
134 anonymousEntry = currentScope->symbolTable.insertAnonymous(structType, node);
2118
2119 // Remove public specifier to not have public local variables
2120 173 structType.getSpecifiers().isPublic = false;
2121
2122
2/4
✓ Branch 1 taken 173 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 173 times.
✗ Branch 5 not taken.
173 return ExprResult{node->setEvaluatedSymbolType(structType, manIdx), anonymousEntry};
2123 179 }
2124
2125 9 std::any TypeChecker::visitLambdaFunc(LambdaFuncNode *node) {
2126 // Check if all control paths in the lambda body return
2127 9 bool returnsOnAllControlPaths = true;
2128
3/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 8 times.
9 if (!node->returnsOnAllControlPaths(&returnsOnAllControlPaths))
2129
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node, MISSING_RETURN_STMT, "Not all control paths of this lambda function have a return statement")
2130
2131 // Change to function scope
2132
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
2133
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
2134
2135 // Visit return type
2136
2/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
8 auto returnType = std::any_cast<QualType>(visit(node->returnType));
2137
2/8
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
8 HANDLE_UNRESOLVED_TYPE_QT(returnType)
2138
3/4
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 7 times.
8 if (returnType.is(TY_DYN))
2139
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
3 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed")
2140
2141 // Set the type of the result variable
2142
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
21 SymbolTableEntry *resultVarEntry = currentScope->lookupStrict(RETURN_VARIABLE_NAME);
2143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 assert(resultVarEntry != nullptr);
2144
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 resultVarEntry->updateType(returnType, true);
2145 7 resultVarEntry->used = true;
2146
2147 // Visit parameters
2148 7 QualTypeList paramTypes;
2149 7 ParamList paramList;
2150
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (node->hasParams) {
2151 // Visit param list to retrieve the param names
2152
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
2153
2/2
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 6 times.
16 for (const auto &[name, qualType, isOptional] : namedParamList) {
2154
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (isOptional)
2155 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
2156
2157
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 paramTypes.push_back(qualType);
2158
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 paramList.push_back({qualType, isOptional});
2159 }
2160 6 }
2161
2162 // Visit lambda body
2163
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 times.
7 visit(node->body);
2164
2165 // Leave function body scope
2166
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 scopeHandle.leaveScopeEarly();
2167
2168 // Prepare type of function
2169
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 const QualType functionType = QualType(TY_FUNCTION)
2170
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 .getWithFunctionParamAndReturnTypes(returnType, paramTypes)
2171
1/2
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
2172
2173 // Create function object
2174
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
2175
4/8
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 6 times.
✗ Branch 13 not taken.
6 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node);
2176
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 node->manifestations.at(manIdx).bodyScope = bodyScope;
2177
3/6
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
6 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
2178
2179 // Check special requirements if this is an async lambda
2180
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr);
2181
2182
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
2183 10 }
2184
2185 28 std::any TypeChecker::visitLambdaProc(LambdaProcNode *node) {
2186 // Mark unreachable statements
2187 28 bool doSetPredecessorsUnreachable = true;
2188
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 node->returnsOnAllControlPaths(&doSetPredecessorsUnreachable);
2189
2190 // Change to function scope
2191
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
2192
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
2193
2194 // Visit parameters
2195 28 QualTypeList paramTypes;
2196 28 ParamList paramList;
2197
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 21 times.
28 if (node->hasParams) {
2198 // Visit param list to retrieve the param names
2199
2/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
7 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
2200
2/2
✓ Branch 4 taken 11 times.
✓ Branch 5 taken 7 times.
18 for (const auto &[_, qualType, isOptional] : namedParamList) {
2201
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (isOptional)
2202
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
2203
2204
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 paramTypes.push_back(qualType);
2205
1/2
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
11 paramList.push_back({qualType, isOptional});
2206 }
2207 7 }
2208
2209 // Visit lambda body
2210
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 visit(node->body);
2211
2212 // Leave function body scope
2213
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 scopeHandle.leaveScopeEarly();
2214
2215 // Prepare type of function
2216
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 const QualType functionType = QualType(TY_PROCEDURE)
2217
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 .getWithFunctionParamAndReturnTypes(QualType(TY_DYN), paramTypes)
2218
1/2
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
28 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
2219
2220 // Create function object
2221
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
2222
5/10
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 28 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 28 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 28 times.
✗ Branch 12 not taken.
✓ Branch 15 taken 28 times.
✗ Branch 16 not taken.
28 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), QualType(TY_DYN), paramList, {}, node);
2223
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 node->manifestations.at(manIdx).bodyScope = bodyScope;
2224
3/6
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 28 times.
✗ Branch 8 not taken.
28 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
2225
2226 // Check special requirements if this is an async lambda
2227
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 (void)checkAsyncLambdaCaptureRules(node, node->lambdaAttr);
2228
2229
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
56 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
2230 28 }
2231
2232 1 std::any TypeChecker::visitLambdaExpr(LambdaExprNode *node) {
2233 // Change to function scope
2234
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 Scope *bodyScope = currentScope->getChildScope(node->getScopeId());
2235
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ScopeHandle scopeHandle(this, bodyScope, ScopeType::LAMBDA_BODY);
2236
2237 // Visit parameters
2238 1 QualTypeList paramTypes;
2239 1 ParamList paramList;
2240
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (node->hasParams) {
2241 // Visit param list to retrieve the param names
2242
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 auto namedParamList = std::any_cast<NamedParamList>(visit(node->paramLst));
2243
2/2
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 1 times.
3 for (const NamedParam &param : namedParamList) {
2244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (param.isOptional)
2245 softError(node, LAMBDA_WITH_OPTIONAL_PARAMS, "Lambdas cannot have optional parameters");
2246
2247
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 paramTypes.push_back(param.qualType);
2248
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 paramList.push_back({param.qualType, param.isOptional});
2249 }
2250 1 }
2251
2252 // Visit lambda expression
2253
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 QualType returnType = std::any_cast<ExprResult>(visit(node->lambdaExpr)).type;
2254
2/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
1 HANDLE_UNRESOLVED_TYPE_ER(returnType)
2255
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (returnType.is(TY_DYN))
2256 SOFT_ERROR_ER(node, UNEXPECTED_DYN_TYPE, "Dyn return types are not allowed")
2257
2258 // Leave function body scope
2259
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 scopeHandle.leaveScopeEarly();
2260
2261 // Prepare type of function
2262
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 const SuperType superType = returnType.is(TY_DYN) ? TY_PROCEDURE : TY_FUNCTION;
2263
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType functionType = QualType(superType)
2264
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 .getWithFunctionParamAndReturnTypes(returnType, paramTypes)
2265
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 .getWithLambdaCaptures(!bodyScope->symbolTable.captures.empty());
2266
2267 // Create function object
2268
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 const std::string fctName = "lambda." + node->codeLoc.toPrettyLineAndColumn();
2269
4/8
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
1 node->manifestations.at(manIdx) = Function(fctName, nullptr, QualType(TY_DYN), returnType, paramList, {}, node);
2270
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 node->manifestations.at(manIdx).bodyScope = bodyScope;
2271
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
1 node->manifestations.at(manIdx).mangleSuffix = "." + std::to_string(manIdx);
2272
2273
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 return ExprResult{node->setEvaluatedSymbolType(functionType, manIdx)};
2274 1 }
2275
2276 38607 std::any TypeChecker::visitDataType(DataTypeNode *node) {
2277 // Visit base data type
2278
2/4
✓ Branch 1 taken 38607 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 38607 times.
✗ Branch 5 not taken.
38607 auto type = std::any_cast<QualType>(visit(node->baseDataType));
2279
5/8
✓ Branch 1 taken 38607 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 38604 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
38607 HANDLE_UNRESOLVED_TYPE_QT(type)
2280
2281
1/2
✓ Branch 1 taken 38604 times.
✗ Branch 2 not taken.
38604 std::queue<DataTypeNode::TypeModifier> tmQueue = node->tmQueue;
2282
2/2
✓ Branch 1 taken 9984 times.
✓ Branch 2 taken 38596 times.
48580 while (!tmQueue.empty()) {
2283
1/2
✓ Branch 2 taken 9984 times.
✗ Branch 3 not taken.
9984 auto [modifierType, hasSize, hardcodedSize, sizeVarName] = tmQueue.front();
2284
2285 // Only the outermost array can have an unknown size
2286
8/10
✓ Branch 1 taken 9984 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 38 times.
✓ Branch 4 taken 9946 times.
✓ Branch 6 taken 38 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 36 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 9982 times.
9984 if (type.isArray() && type.getArraySize() == ARRAY_SIZE_UNKNOWN)
2287
4/8
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
6 SOFT_ERROR_QT(node, ARRAY_SIZE_INVALID,
2288 "Usage of incomplete array type. Only the outermost array type may have unknown size")
2289
2290
3/4
✓ Branch 0 taken 4492 times.
✓ Branch 1 taken 5352 times.
✓ Branch 2 taken 138 times.
✗ Branch 3 not taken.
9982 switch (modifierType) {
2291 4492 case DataTypeNode::TYPE_PTR: {
2292
2/2
✓ Branch 1 taken 4490 times.
✓ Branch 2 taken 2 times.
4492 type = type.toPtr(node);
2293 4490 break;
2294 }
2295 5352 case DataTypeNode::TYPE_REF: {
2296
1/2
✓ Branch 1 taken 5352 times.
✗ Branch 2 not taken.
5352 type = type.toRef(node);
2297 5352 break;
2298 }
2299 138 case DataTypeNode::TYPE_ARRAY: {
2300 138 const std::string &varName = sizeVarName;
2301
2/2
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 103 times.
138 if (!varName.empty()) {
2302
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 const SymbolTableEntry *globalVar = rootScope->lookupStrict(varName);
2303
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34 times.
35 if (!globalVar)
2304
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 SOFT_ERROR_QT(node, REFERENCED_UNDEFINED_VARIABLE, "Could not find global variable '" + varName + "' ")
2305
4/6
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 33 times.
34 if (!globalVar->getQualType().isConst())
2306
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
3 SOFT_ERROR_QT(node, EXPECTED_CONST_VARIABLE, "The size of the array must be known at compile time")
2307
4/6
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 33 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 32 times.
33 if (!globalVar->getQualType().is(TY_INT))
2308
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
3 SOFT_ERROR_QT(node, OPERATOR_WRONG_DATA_TYPE, "Expected variable of type int")
2309
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 hardcodedSize = globalVar->declNode->getCompileTimeValue().intValue;
2310 }
2311
2312
3/4
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 79 times.
135 if (hasSize && hardcodedSize <= 1)
2313 SOFT_ERROR_QT(node, ARRAY_SIZE_INVALID, "The size of an array must be > 1 and explicitly stated")
2314
2/2
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 1 times.
135 type = type.toArray(node, hardcodedSize);
2315 134 break;
2316 }
2317 default: // GCOV_EXCL_LINE
2318 throw CompilerError(UNHANDLED_BRANCH, "Modifier type fall-through"); // GCOV_EXCL_LINE
2319 }
2320 9976 tmQueue.pop();
2321
2/2
✓ Branch 1 taken 9976 times.
✓ Branch 2 taken 5 times.
9984 }
2322
2323 // Attach the specifiers to the type
2324
2/2
✓ Branch 0 taken 16612 times.
✓ Branch 1 taken 21984 times.
38596 if (node->specifierLst) {
2325
1/2
✓ Branch 1 taken 16612 times.
✗ Branch 2 not taken.
16612 const QualType baseType = type.getBase();
2326
2/2
✓ Branch 5 taken 19113 times.
✓ Branch 6 taken 16610 times.
35723 for (const SpecifierNode *specifier : node->specifierLst->specifiers) {
2327
2/2
✓ Branch 0 taken 8324 times.
✓ Branch 1 taken 10789 times.
19113 if (specifier->type == SpecifierNode::TY_CONST) {
2328 8324 type.getSpecifiers().isConst = true;
2329
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10787 times.
10789 } else if (specifier->type == SpecifierNode::TY_SIGNED) {
2330
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 if (!baseType.isOneOf({TY_INT, TY_LONG, TY_SHORT, TY_BYTE, TY_CHAR, TY_GENERIC}))
2331 SOFT_ERROR_QT(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on type " + baseType.getName(false))
2332 2 type.getSpecifiers().isSigned = true;
2333 2 type.getSpecifiers().isUnsigned = false;
2334
2/2
✓ Branch 0 taken 7443 times.
✓ Branch 1 taken 3344 times.
10787 } else if (specifier->type == SpecifierNode::TY_UNSIGNED) {
2335
2/4
✓ Branch 1 taken 7443 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 7443 times.
7443 if (!baseType.isOneOf({TY_INT, TY_LONG, TY_SHORT, TY_BYTE, TY_CHAR, TY_GENERIC}))
2336 SOFT_ERROR_QT(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "Cannot use this specifier on type " + baseType.getName(false))
2337 7443 type.getSpecifiers().isSigned = false;
2338 7443 type.getSpecifiers().isUnsigned = true;
2339
2/2
✓ Branch 0 taken 2894 times.
✓ Branch 1 taken 450 times.
3344 } else if (specifier->type == SpecifierNode::TY_HEAP) {
2340 // Heap variables can only be pointers
2341
4/6
✓ Branch 1 taken 2894 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2894 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 2893 times.
2894 if (!type.removeReferenceWrapper().isOneOf({TY_PTR, TY_ARRAY, TY_STRING}))
2342
5/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 1 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
1 SOFT_ERROR_QT(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT,
2343 "The heap specifier can only be applied to symbols of pointer type, you provided " +
2344 baseType.getName(false))
2345
2346 2893 type.getSpecifiers().isHeap = true;
2347
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 443 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
450 } else if (specifier->type == SpecifierNode::TY_COMPOSITION && node->isFieldType) {
2348
3/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 6 times.
7 if (!type.is(TY_STRUCT))
2349
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
3 SOFT_ERROR_QT(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT, "The compose specifier can only be used on plain struct fields")
2350 6 type.getSpecifiers().isComposition = true;
2351
4/6
✓ Branch 0 taken 443 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 258 times.
✓ Branch 3 taken 185 times.
✓ Branch 4 taken 258 times.
✗ Branch 5 not taken.
443 } else if (specifier->type == SpecifierNode::TY_PUBLIC && (node->isFieldType || node->isGlobalType)) {
2352 443 type.getSpecifiers().isPublic = true;
2353 } else {
2354 const char *entryName = "local variable";
2355 if (node->isGlobalType)
2356 entryName = "global variable";
2357 else if (node->isFieldType)
2358 entryName = "field";
2359 else if (node->isParamType)
2360 entryName = "param";
2361 else if (node->isReturnType)
2362 entryName = "return variable";
2363 SOFT_ERROR_QT(specifier, SPECIFIER_AT_ILLEGAL_CONTEXT,
2364 "Cannot use this specifier on a " + std::string(entryName) + " definition")
2365 }
2366 }
2367 }
2368
2369
2/4
✓ Branch 1 taken 38594 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 38594 times.
✗ Branch 5 not taken.
38594 return node->setEvaluatedSymbolType(type, manIdx);
2370 38604 }
2371
2372 38607 std::any TypeChecker::visitBaseDataType(BaseDataTypeNode *node) {
2373
11/11
✓ Branch 0 taken 202 times.
✓ Branch 1 taken 2381 times.
✓ Branch 2 taken 339 times.
✓ Branch 3 taken 8573 times.
✓ Branch 4 taken 1323 times.
✓ Branch 5 taken 3936 times.
✓ Branch 6 taken 5847 times.
✓ Branch 7 taken 2002 times.
✓ Branch 8 taken 13529 times.
✓ Branch 9 taken 127 times.
✓ Branch 10 taken 348 times.
38607 switch (node->type) {
2374 202 case BaseDataTypeNode::TYPE_DOUBLE:
2375
3/6
✓ Branch 1 taken 202 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 202 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 202 times.
✗ Branch 8 not taken.
202 return node->setEvaluatedSymbolType(QualType(TY_DOUBLE), manIdx);
2376 2381 case BaseDataTypeNode::TYPE_INT:
2377
3/6
✓ Branch 1 taken 2381 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2381 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2381 times.
✗ Branch 8 not taken.
2381 return node->setEvaluatedSymbolType(QualType(TY_INT), manIdx);
2378 339 case BaseDataTypeNode::TYPE_SHORT:
2379
3/6
✓ Branch 1 taken 339 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 339 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 339 times.
✗ Branch 8 not taken.
339 return node->setEvaluatedSymbolType(QualType(TY_SHORT), manIdx);
2380 8573 case BaseDataTypeNode::TYPE_LONG:
2381
3/6
✓ Branch 1 taken 8573 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 8573 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8573 times.
✗ Branch 8 not taken.
8573 return node->setEvaluatedSymbolType(QualType(TY_LONG), manIdx);
2382 1323 case BaseDataTypeNode::TYPE_BYTE:
2383
3/6
✓ Branch 1 taken 1323 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1323 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1323 times.
✗ Branch 8 not taken.
1323 return node->setEvaluatedSymbolType(QualType(TY_BYTE), manIdx);
2384 3936 case BaseDataTypeNode::TYPE_CHAR:
2385
3/6
✓ Branch 1 taken 3936 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3936 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3936 times.
✗ Branch 8 not taken.
3936 return node->setEvaluatedSymbolType(QualType(TY_CHAR), manIdx);
2386 5847 case BaseDataTypeNode::TYPE_STRING:
2387
3/6
✓ Branch 1 taken 5847 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5847 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5847 times.
✗ Branch 8 not taken.
5847 return node->setEvaluatedSymbolType(QualType(TY_STRING), manIdx);
2388 2002 case BaseDataTypeNode::TYPE_BOOL:
2389
3/6
✓ Branch 1 taken 2002 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2002 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2002 times.
✗ Branch 8 not taken.
2002 return node->setEvaluatedSymbolType(QualType(TY_BOOL), manIdx);
2390 13529 case BaseDataTypeNode::TYPE_CUSTOM: {
2391
2/4
✓ Branch 1 taken 13529 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13529 times.
✗ Branch 5 not taken.
13529 const auto customType = std::any_cast<QualType>(visit(node->customDataType));
2392
5/8
✓ Branch 1 taken 13529 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 13526 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
13529 HANDLE_UNRESOLVED_TYPE_QT(customType)
2393
2/4
✓ Branch 1 taken 13526 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13526 times.
✗ Branch 5 not taken.
13526 return node->setEvaluatedSymbolType(customType, manIdx);
2394 }
2395 127 case BaseDataTypeNode::TYPE_FUNCTION: {
2396
2/4
✓ Branch 1 taken 127 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 127 times.
✗ Branch 5 not taken.
127 const auto functionType = std::any_cast<QualType>(visit(node->functionDataType));
2397
2/8
✓ Branch 1 taken 127 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 127 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
127 HANDLE_UNRESOLVED_TYPE_QT(functionType)
2398
2/4
✓ Branch 1 taken 127 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 127 times.
✗ Branch 5 not taken.
127 return node->setEvaluatedSymbolType(functionType, manIdx);
2399 }
2400 348 default:
2401
3/6
✓ Branch 1 taken 348 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 348 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 348 times.
✗ Branch 8 not taken.
348 return node->setEvaluatedSymbolType(QualType(TY_DYN), manIdx);
2402 }
2403 }
2404
2405 13529 std::any TypeChecker::visitCustomDataType(CustomDataTypeNode *node) {
2406 // It is a struct type -> get the access scope
2407
2/2
✓ Branch 0 taken 3614 times.
✓ Branch 1 taken 9915 times.
13529 Scope *localAccessScope = accessScope ? accessScope : currentScope;
2408
2409
1/2
✓ Branch 2 taken 13529 times.
✗ Branch 3 not taken.
13529 const std::string firstFragment = node->typeNameFragments.front();
2410
2411 // Check this type requires a runtime module
2412
2/2
✓ Branch 1 taken 13503 times.
✓ Branch 2 taken 26 times.
13529 if (node->typeNameFragments.size() == 1)
2413
2/2
✓ Branch 7 taken 40509 times.
✓ Branch 8 taken 13503 times.
54012 for (const auto &[typeName, runtimeModule] : TYPE_NAME_TO_RT_MODULE_MAPPING)
2414
8/10
✓ Branch 1 taken 40509 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3661 times.
✓ Branch 4 taken 36848 times.
✓ Branch 6 taken 3661 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 712 times.
✓ Branch 9 taken 2949 times.
✓ Branch 10 taken 712 times.
✓ Branch 11 taken 39797 times.
40509 if (firstFragment == typeName && !sourceFile->isRT(runtimeModule))
2415
1/2
✓ Branch 1 taken 712 times.
✗ Branch 2 not taken.
712 sourceFile->requestRuntimeModule(runtimeModule);
2416
2417 // Check if it is a generic type
2418 13529 bool isImported = node->typeNameFragments.size() > 1;
2419
1/2
✓ Branch 1 taken 13529 times.
✗ Branch 2 not taken.
13529 const QualType *genericType = rootScope->lookupGenericType(firstFragment);
2420
4/4
✓ Branch 0 taken 13503 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 6582 times.
✓ Branch 3 taken 6921 times.
13529 if (!isImported && genericType) {
2421 // Take the concrete replacement type for the name of this generic type if available
2422 6582 QualType symbolType = *genericType;
2423
3/4
✓ Branch 1 taken 6582 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1596 times.
✓ Branch 4 taken 4986 times.
6582 if (typeMapping.contains(firstFragment))
2424
1/2
✓ Branch 1 taken 1596 times.
✗ Branch 2 not taken.
1596 symbolType = typeMapping.at(firstFragment);
2425
2426 // Check if the replacement is a String type
2427
9/12
✓ Branch 0 taken 6582 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6582 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 139 times.
✓ Branch 6 taken 6443 times.
✓ Branch 8 taken 139 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 121 times.
✓ Branch 11 taken 18 times.
✓ Branch 12 taken 121 times.
✓ Branch 13 taken 6461 times.
6721 if (!isImported && symbolType.isStringObj() && !sourceFile->isStringRT())
2428
1/2
✓ Branch 1 taken 121 times.
✗ Branch 2 not taken.
121 sourceFile->requestRuntimeModule(STRING_RT);
2429
2430
2/4
✓ Branch 1 taken 6582 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6582 times.
✗ Branch 5 not taken.
6582 return node->setEvaluatedSymbolType(symbolType, manIdx);
2431 }
2432
2433 // Check if the type exists in the exported names registry
2434
1/2
✓ Branch 1 taken 6947 times.
✗ Branch 2 not taken.
6947 const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(node->fqTypeName);
2435
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6945 times.
6947 if (!registryEntry)
2436
5/10
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
2 SOFT_ERROR_QT(node, UNKNOWN_DATATYPE, "Unknown datatype '" + node->fqTypeName + "'")
2437
2/4
✓ Branch 0 taken 6945 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6945 times.
✗ Branch 3 not taken.
6945 assert(registryEntry->targetEntry != nullptr && registryEntry->targetScope != nullptr);
2438 6945 SymbolTableEntry *entry = registryEntry->targetEntry;
2439
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6945 times.
6945 assert(entry != nullptr);
2440 6945 entry->used = true;
2441 6945 localAccessScope = registryEntry->targetScope->parent;
2442
2443 // Get struct type
2444
1/2
✓ Branch 1 taken 6945 times.
✗ Branch 2 not taken.
6945 QualType entryType = entry->getQualType();
2445
2446 // Enums can early-return
2447
3/4
✓ Branch 1 taken 6945 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
✓ Branch 4 taken 6876 times.
6945 if (entryType.is(TY_ENUM))
2448
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 69 times.
✗ Branch 5 not taken.
69 return QualType(TY_INT);
2449
2450
3/4
✓ Branch 1 taken 6876 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6385 times.
✓ Branch 4 taken 491 times.
6876 if (entryType.isOneOf({TY_STRUCT, TY_INTERFACE})) {
2451
2/4
✓ Branch 0 taken 6385 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6385 times.
6385 assert(dynamic_cast<DataTypeNode *>(node->parent->parent) != nullptr);
2452
2453 // Collect the concrete template types
2454 6385 bool allTemplateTypesConcrete = true;
2455 6385 QualTypeList templateTypes;
2456
2/2
✓ Branch 0 taken 1770 times.
✓ Branch 1 taken 4615 times.
6385 if (node->templateTypeLst) {
2457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1770 times.
1770 assert(localAccessScope != nullptr);
2458
1/2
✓ Branch 1 taken 1770 times.
✗ Branch 2 not taken.
1770 isImported = localAccessScope->isImportedBy(rootScope);
2459
2460
1/2
✓ Branch 2 taken 1770 times.
✗ Branch 3 not taken.
1770 templateTypes.reserve(node->templateTypeLst->dataTypes.size());
2461
2/2
✓ Branch 5 taken 2339 times.
✓ Branch 6 taken 1770 times.
4109 for (DataTypeNode *dataType : node->templateTypeLst->dataTypes) {
2462
2/4
✓ Branch 1 taken 2339 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2339 times.
✗ Branch 5 not taken.
2339 auto templateType = std::any_cast<QualType>(visit(dataType));
2463
2/8
✓ Branch 1 taken 2339 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2339 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
2339 HANDLE_UNRESOLVED_TYPE_QT(templateType)
2464
2/4
✓ Branch 1 taken 2339 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2339 times.
2339 if (entryType.is(TY_GENERIC)) {
2465 allTemplateTypesConcrete = false;
2466
2/2
✓ Branch 0 taken 820 times.
✓ Branch 1 taken 1519 times.
2339 } else if (isImported) {
2467 // Introduce the local type to the imported source file
2468
1/2
✓ Branch 1 taken 820 times.
✗ Branch 2 not taken.
820 [[maybe_unused]] QualType importedType = mapLocalTypeToImportedScopeType(localAccessScope, templateType);
2469
3/6
✓ Branch 1 taken 820 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 820 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 820 times.
820 assert(importedType.is(templateType.getSuperType()));
2470 }
2471
1/2
✓ Branch 1 taken 2339 times.
✗ Branch 2 not taken.
2339 templateTypes.push_back(templateType);
2472 }
2473
1/2
✓ Branch 1 taken 1770 times.
✗ Branch 2 not taken.
1770 entryType = entryType.getWithTemplateTypes(templateTypes);
2474 }
2475
2476 // Check if struct is defined before the current code location, if defined in the same source file
2477 6385 const CodeLoc &declCodeLoc = entry->declNode->codeLoc;
2478 6385 const CodeLoc &codeLoc = node->codeLoc;
2479
6/6
✓ Branch 1 taken 5115 times.
✓ Branch 2 taken 1270 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 5114 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 6384 times.
11500 if (declCodeLoc.sourceFile->filePath == codeLoc.sourceFile->filePath && declCodeLoc > codeLoc) {
2480
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
1 if (entryType.is(TY_STRUCT)) {
2481
4/8
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
3 SOFT_ERROR_QT(node, REFERENCED_UNDEFINED_STRUCT, "Structs must be defined before usage")
2482 } else {
2483 assert(entryType.is(TY_INTERFACE));
2484 SOFT_ERROR_QT(node, REFERENCED_UNDEFINED_INTERFACE, "Interfaces must be defined before usage")
2485 }
2486 }
2487
2488
1/2
✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
6384 if (allTemplateTypesConcrete) { // Only do the next step, if we have concrete template types
2489 // Set the struct/interface instance to used, if found
2490 // Here, it is allowed to accept, that the struct/interface cannot be found, because there are self-referencing ones
2491
3/4
✓ Branch 1 taken 6384 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6264 times.
✓ Branch 4 taken 120 times.
6384 if (entryType.is(TY_STRUCT)) {
2492
1/2
✓ Branch 2 taken 6264 times.
✗ Branch 3 not taken.
6264 const std::string structName = node->typeNameFragments.back();
2493
3/4
✓ Branch 1 taken 6264 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6230 times.
✓ Branch 4 taken 34 times.
6264 if (Struct *spiceStruct = StructManager::match(localAccessScope, structName, templateTypes, node))
2494
1/2
✓ Branch 1 taken 6230 times.
✗ Branch 2 not taken.
6230 entryType = entryType.getWithBodyScope(spiceStruct->scope);
2495 6264 } else {
2496
2/4
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 120 times.
120 assert(entryType.is(TY_INTERFACE));
2497
1/2
✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
120 const std::string interfaceName = node->typeNameFragments.back();
2498
2/4
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
120 if (const Interface *spiceInterface = InterfaceManager::match(localAccessScope, interfaceName, templateTypes, node))
2499
1/2
✓ Branch 1 taken 120 times.
✗ Branch 2 not taken.
120 entryType = entryType.getWithBodyScope(spiceInterface->scope);
2500 120 }
2501 }
2502
2503
2/4
✓ Branch 1 taken 6384 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6384 times.
✗ Branch 5 not taken.
6384 return node->setEvaluatedSymbolType(entryType, manIdx);
2504 6385 }
2505
2506
2/4
✓ Branch 1 taken 491 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 491 times.
✗ Branch 4 not taken.
491 if (entryType.is(TY_ALIAS)) {
2507 // Get type of aliased type container entry
2508
1/2
✓ Branch 1 taken 491 times.
✗ Branch 2 not taken.
491 const std::string aliasedContainerEntryName = entry->name + ALIAS_CONTAINER_SUFFIX;
2509
1/2
✓ Branch 1 taken 491 times.
✗ Branch 2 not taken.
491 SymbolTableEntry *aliasedTypeContainerEntry = entry->scope->lookupStrict(aliasedContainerEntryName);
2510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
491 assert(aliasedTypeContainerEntry != nullptr);
2511
3/6
✓ Branch 1 taken 491 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 491 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 491 times.
✗ Branch 8 not taken.
491 return node->setEvaluatedSymbolType(aliasedTypeContainerEntry->getQualType(), manIdx);
2512 491 }
2513
2514 const bool isInvalid = entryType.is(TY_INVALID);
2515 SOFT_ERROR_QT(node, EXPECTED_TYPE, isInvalid ? "Used type before declared" : "Expected type, but got " + entryType.getName())
2516 13529 }
2517
2518 127 std::any TypeChecker::visitFunctionDataType(FunctionDataTypeNode *node) {
2519 // Visit return type
2520
1/2
✓ Branch 1 taken 127 times.
✗ Branch 2 not taken.
127 QualType returnType(TY_DYN);
2521
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 101 times.
127 if (node->isFunction) {
2522
2/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 5 not taken.
26 returnType = std::any_cast<QualType>(visit(node->returnType));
2523
2/8
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
26 HANDLE_UNRESOLVED_TYPE_QT(returnType)
2524
2/4
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
26 if (returnType.is(TY_DYN))
2525 SOFT_ERROR_ER(node->returnType, UNEXPECTED_DYN_TYPE, "Function types cannot have return type dyn")
2526 }
2527
2528 // Visit param types
2529 127 QualTypeList paramTypes;
2530
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 42 times.
127 if (const TypeLstNode *paramTypeListNode = node->paramTypeLst; paramTypeListNode != nullptr) {
2531
2/2
✓ Branch 5 taken 98 times.
✓ Branch 6 taken 85 times.
183 for (DataTypeNode *paramTypeNode : paramTypeListNode->dataTypes) {
2532
2/4
✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
98 auto paramType = std::any_cast<QualType>(visit(paramTypeNode));
2533
2/8
✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 98 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
98 HANDLE_UNRESOLVED_TYPE_QT(returnType)
2534
1/2
✓ Branch 1 taken 98 times.
✗ Branch 2 not taken.
98 paramTypes.push_back(paramType);
2535 }
2536 }
2537
2538 // Build function type
2539
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 101 times.
127 const SuperType superType = node->isFunction ? TY_FUNCTION : TY_PROCEDURE;
2540
2/4
✓ Branch 1 taken 127 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 127 times.
✗ Branch 5 not taken.
127 const QualType functionType = QualType(superType).getWithFunctionParamAndReturnTypes(returnType, paramTypes);
2541
2542
2/4
✓ Branch 1 taken 127 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 127 times.
✗ Branch 5 not taken.
127 return node->setEvaluatedSymbolType(functionType, manIdx);
2543 127 }
2544
2545 /**
2546 * Check if the the capture rules for async lambdas are enforced if the async attribute is set
2547 *
2548 * Only one capture with pointer type, pass-by-val is allowed, since only then we can store it in the second field of the
2549 * fat pointer and can ensure, that no stack variable is referenced inside the lambda.
2550 *
2551 * @param node Lambda base node
2552 * @param attrs Lambda attributes
2553 * @return False if the rules are violated, true otherwise
2554 */
2555 34 bool TypeChecker::checkAsyncLambdaCaptureRules(const LambdaBaseNode *node, const LambdaAttrNode *attrs) const {
2556 // If the async attribute is not set, we can return early
2557
18/32
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 18 times.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 16 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 16 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 16 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 16 times.
✓ Branch 18 taken 16 times.
✓ Branch 19 taken 18 times.
✓ Branch 21 taken 16 times.
✓ Branch 22 taken 18 times.
✓ Branch 23 taken 16 times.
✓ Branch 24 taken 18 times.
✓ Branch 26 taken 16 times.
✓ Branch 27 taken 18 times.
✓ Branch 28 taken 18 times.
✓ Branch 29 taken 16 times.
✗ Branch 30 not taken.
✗ Branch 31 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
98 if (!attrs || !attrs->attrLst->hasAttr(ATTR_ASYNC) || !attrs->attrLst->getAttrValueByName(ATTR_ASYNC)->boolValue)
2558 18 return true; // Not violated
2559
2560 // If we don't have any captures, we can return early
2561 16 const CaptureMap &captures = node->bodyScope->symbolTable.captures;
2562
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 6 times.
16 if (captures.empty())
2563 10 return true; // Not violated
2564
2565 // Check for the capture rules
2566 6 if (const Capture &capture = captures.begin()->second;
2567
8/8
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 2 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 1 times.
6 captures.size() > 1 || !capture.capturedSymbol->getQualType().isPtr() || capture.getMode() != BY_VALUE) {
2568 5 const auto warningMessage =
2569 "Async lambdas can only capture one pointer by value without storing captures in the caller stack frame, which can lead "
2570 "to bugs due to references, outliving the validity scope of the referenced variable.";
2571
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
5 const CompilerWarning warning(node->codeLoc, ASYNC_LAMBDA_CAPTURE_RULE_VIOLATION, warningMessage);
2572
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 currentScope->sourceFile->compilerOutput.warnings.push_back(warning);
2573 5 }
2574
2575 6 return false; // Violated
2576 }
2577
2578 72732 QualType TypeChecker::mapLocalTypeToImportedScopeType(const Scope *targetScope, const QualType &symbolType) const {
2579 // Skip all types, except structs
2580
3/4
✓ Branch 1 taken 72732 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 63832 times.
✓ Branch 4 taken 8900 times.
72732 if (!symbolType.isBase(TY_STRUCT))
2581 63832 return symbolType;
2582
2583 // If the target scope is in the current source file, we can return the symbol type as is
2584 8900 SourceFile *targetSourceFile = targetScope->sourceFile;
2585
2/2
✓ Branch 0 taken 4152 times.
✓ Branch 1 taken 4748 times.
8900 if (targetSourceFile == sourceFile)
2586 4152 return symbolType;
2587
2588 // Match the scope of the symbol type against all scopes in the name registry of the target source file
2589
5/8
✓ Branch 1 taken 4748 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4748 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4748 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 164456 times.
✓ Branch 13 taken 141 times.
164597 for (const auto &entry : targetSourceFile->exportedNameRegistry | std::views::values)
2590
7/10
✓ Branch 0 taken 164456 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 164456 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 164456 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 14659 times.
✓ Branch 9 taken 149797 times.
✓ Branch 10 taken 14659 times.
✓ Branch 11 taken 149797 times.
164456 if (entry.targetEntry != nullptr && entry.targetEntry->getQualType().isBase(TY_STRUCT))
2591
3/4
✓ Branch 1 taken 14659 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 28954 times.
✓ Branch 9 taken 10052 times.
39006 for (const Struct *manifestation : *entry.targetEntry->declNode->getStructManifestations())
2592
4/6
✓ Branch 1 taken 28954 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28954 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4607 times.
✓ Branch 7 taken 24347 times.
28954 if (manifestation->scope == symbolType.getBase().getBodyScope())
2593 4607 return symbolType;
2594
2595 // The target source file does not know about the struct at all
2596 // -> show it how to find the struct
2597
3/6
✓ Branch 1 taken 141 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 141 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 141 times.
✗ Branch 8 not taken.
141 const std::string structName = symbolType.getBase().getSubType();
2598
1/2
✓ Branch 1 taken 141 times.
✗ Branch 2 not taken.
141 const NameRegistryEntry *origRegistryEntry = sourceFile->getNameRegistryEntry(structName);
2599
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 assert(origRegistryEntry != nullptr);
2600 141 const uint64_t targetTypeId = origRegistryEntry->typeId;
2601 141 SymbolTableEntry *targetEntry = origRegistryEntry->targetEntry;
2602
1/2
✓ Branch 1 taken 141 times.
✗ Branch 2 not taken.
141 targetSourceFile->addNameRegistryEntry(structName, targetTypeId, targetEntry, origRegistryEntry->targetScope, false);
2603
2604 141 return symbolType;
2605 141 }
2606
2607 2706 QualType TypeChecker::mapImportedScopeTypeToLocalType(const Scope *sourceScope, const QualType &symbolType) const {
2608 // Skip all types, except structs
2609
3/4
✓ Branch 1 taken 2706 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 367 times.
✓ Branch 4 taken 2339 times.
2706 if (!symbolType.isBase(TY_STRUCT))
2610 367 return symbolType;
2611
2612 // If the source scope is in the current source file, we can return the symbol type as is
2613 2339 const SourceFile *sourceSourceFile = sourceScope->sourceFile;
2614
2/2
✓ Branch 0 taken 836 times.
✓ Branch 1 taken 1503 times.
2339 if (sourceSourceFile == sourceFile)
2615 836 return symbolType;
2616
2617 // Match the scope of the symbol type against all scopes in the name registry of this source file
2618
1/2
✓ Branch 1 taken 1503 times.
✗ Branch 2 not taken.
1503 const QualType baseType = symbolType.getBase();
2619
5/8
✓ Branch 1 taken 1503 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1503 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1503 times.
✗ Branch 8 not taken.
✓ Branch 12 taken 82763 times.
✓ Branch 13 taken 42 times.
82805 for (const auto &entry : sourceFile->exportedNameRegistry | std::views::values)
2620
7/10
✓ Branch 0 taken 82763 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 82763 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 82763 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5234 times.
✓ Branch 9 taken 77529 times.
✓ Branch 10 taken 5234 times.
✓ Branch 11 taken 77529 times.
82763 if (entry.targetEntry != nullptr && entry.targetEntry->getQualType().isBase(TY_STRUCT))
2621
3/4
✓ Branch 1 taken 5234 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 10273 times.
✓ Branch 9 taken 3773 times.
14046 for (const Struct *manifestation : *entry.targetEntry->declNode->getStructManifestations())
2622
3/4
✓ Branch 1 taken 10273 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1461 times.
✓ Branch 4 taken 8812 times.
10273 if (manifestation->scope == baseType.getBodyScope())
2623 1461 return symbolType;
2624
2625 // This source file does not know about the struct at all
2626 // -> show it how to find the struct
2627
2/4
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
42 const NameRegistryEntry *origRegistryEntry = sourceSourceFile->getNameRegistryEntry(baseType.getSubType());
2628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 assert(origRegistryEntry != nullptr);
2629 42 const uint64_t typeId = origRegistryEntry->typeId;
2630 42 SymbolTableEntry *targetEntry = origRegistryEntry->targetEntry;
2631
2/4
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
42 sourceFile->addNameRegistryEntry(baseType.getSubType(), typeId, targetEntry, origRegistryEntry->targetScope, false);
2632
2633 42 return symbolType;
2634 }
2635
2636 /**
2637 * Auto-dereference the given symbol type.
2638 * This process is NOT equivalent with getBase() because getBase() also removes e.g. array wrappers
2639 *
2640 * @param symbolType Input symbol type
2641 */
2642 16848 void TypeChecker::autoDeReference(QualType &symbolType) {
2643
6/6
✓ Branch 1 taken 18470 times.
✓ Branch 2 taken 12885 times.
✓ Branch 4 taken 1622 times.
✓ Branch 5 taken 16848 times.
✓ Branch 6 taken 14507 times.
✓ Branch 7 taken 16848 times.
31355 while (symbolType.isPtr() || symbolType.isRef())
2644
1/2
✓ Branch 1 taken 14507 times.
✗ Branch 2 not taken.
14507 symbolType = symbolType.getContained();
2645 16848 }
2646
2647 /**
2648 * Returns the operator function list for the current manifestation and the given node
2649 *
2650 * @param node Node to retrieve the op fct pointer list from
2651 * @return Op fct pointer list
2652 */
2653 563 std::vector<const Function *> &TypeChecker::getOpFctPointers(ASTNode *node) const {
2654
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 563 times.
563 assert(node->getOpFctPointers()->size() > manIdx);
2655 563 return node->getOpFctPointers()->at(manIdx);
2656 }
2657
2658 /**
2659 * Check if a function has been type-checked already. If not, request a revisit
2660 *
2661 * @param fct Function to check
2662 */
2663 15981 void TypeChecker::requestRevisitIfRequired(const Function *fct) const {
2664
8/8
✓ Branch 0 taken 15914 times.
✓ Branch 1 taken 67 times.
✓ Branch 2 taken 8730 times.
✓ Branch 3 taken 7184 times.
✓ Branch 5 taken 4192 times.
✓ Branch 6 taken 4538 times.
✓ Branch 7 taken 4192 times.
✓ Branch 8 taken 11789 times.
15981 if (fct && !fct->alreadyTypeChecked && !fct->entry->scope->isImportedBy(rootScope))
2665 4192 fct->entry->scope->sourceFile->reVisitRequested = true;
2666 15981 }
2667
2668 /**
2669 * Add a soft error to the error list
2670 */
2671 25 void TypeChecker::softError(const ASTNode *node, const SemanticErrorType errorType, const std::string &message) const {
2672 25 resourceManager.errorManager.addSoftError(node, errorType, message);
2673 25 }
2674
2675 } // namespace spice::compiler
2676