GCC Code Coverage Report


Directory: ../
File: src/typechecker/TypeChecker.cpp
Date: 2024-11-22 23:10:59
Exec Total Coverage
Lines: 1523 1596 95.4%
Functions: 80 81 98.8%
Branches: 2687 5145 52.2%

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
2/4
✓ Branch 1 taken 1661 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1661 times.
✗ Branch 5 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
2/4
✓ Branch 1 taken 1049 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1049 times.
✗ Branch 5 not taken.
1049 visit(node->initDecl());
132
133 // Visit condition
134
3/6
✓ Branch 1 taken 1049 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1049 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1049 times.
✗ Branch 8 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
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 11 taken 1 times.
✗ Branch 12 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.
3 SOFT_ERROR_ER(node->condAssign(), CONDITION_MUST_BE_BOOL, "For loop condition must be of type bool")
139
140 // Visit incrementer
141
2/4
✓ Branch 1 taken 1048 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1048 times.
✗ Branch 5 not taken.
1048 visit(node->incAssign());
142
143 // Visit body
144
2/4
✓ Branch 1 taken 1048 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1048 times.
✗ Branch 5 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
1/2
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
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
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 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
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 11 taken 1 times.
✗ Branch 12 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.
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
1/2
✓ Branch 1 taken 87 times.
✗ Branch 2 not taken.
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
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 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
8/16
✓ 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 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 1 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 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
2/4
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 5 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
3/6
✓ Branch 1 taken 86 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 86 times.
✗ Branch 8 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
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 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
3/4
✓ Branch 1 taken 82 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 81 times.
✓ Branch 5 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
2/4
✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 85 times.
✗ Branch 5 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
4/6
✓ Branch 1 taken 468 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 467 times.
✓ Branch 5 taken 1 times.
✓ Branch 7 taken 467 times.
✗ Branch 8 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
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 11 taken 1 times.
✗ Branch 12 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.
3 SOFT_ERROR_ER(node->condition(), CONDITION_MUST_BE_BOOL, "While loop condition must be of type bool")
269
270 // Visit body
271
2/4
✓ Branch 1 taken 466 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 466 times.
✗ Branch 5 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
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
9 visit(node->body());
282
283 // Visit condition
284
3/6
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 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
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 11 taken 1 times.
✗ Branch 12 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.
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
1/2
✓ Branch 1 taken 3030 times.
✗ Branch 2 not taken.
3030 AssignExprNode *condition = node->condition();
299
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(condition)).type;
300
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)
301 // Check if condition evaluates to bool
302
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))
303
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 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
6 SOFT_ERROR_ER(node->condition(), CONDITION_MUST_BE_BOOL, "If condition must be of type bool")
304
305 // Warning for bool assignment
306
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3024 times.
3025 if (condition->op == AssignExprNode::OP_ASSIGN)
307
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 sourceFile->compilerOutput.warnings.emplace_back(condition->codeLoc, BOOL_ASSIGN_AS_CONDITION,
308 "If you want to compare the values, use '=='");
309
310 // Visit body
311
2/4
✓ Branch 1 taken 3025 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3025 times.
✗ Branch 5 not taken.
3025 visit(node->thenBody());
312
313 // Leave then body scope
314
1/2
✓ Branch 1 taken 3025 times.
✗ Branch 2 not taken.
3025 scopeHandle.leaveScopeEarly();
315
316 // Visit else statement if existing
317
3/4
✓ Branch 1 taken 3025 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 141 times.
✓ Branch 4 taken 2884 times.
3025 if (node->elseStmt())
318
2/4
✓ Branch 1 taken 141 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 141 times.
✗ Branch 5 not taken.
141 visit(node->elseStmt());
319
320
1/2
✓ Branch 1 taken 3025 times.
✗ Branch 2 not taken.
3025 return nullptr;
321 3030 }
322
323 141 std::any TypeChecker::visitElseStmt(ElseStmtNode *node) {
324 // Visit if statement in the case of an else if branch
325
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 99 times.
141 if (node->isElseIf) {
326
2/4
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 42 times.
✗ Branch 5 not taken.
42 visit(node->ifStmt());
327
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 return nullptr;
328 }
329
330 // Change to else body scope
331
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);
332
333 // Visit body
334
2/4
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 99 times.
✗ Branch 5 not taken.
99 visit(node->body());
335
336
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 return nullptr;
337 99 }
338
339 8 std::any TypeChecker::visitSwitchStmt(SwitchStmtNode *node) {
340 // Check expression type
341
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 AssignExprNode *expr = node->assignExpr();
342
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(expr)).type;
343
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)
344
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}))
345
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 11 taken 1 times.
✗ Branch 12 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.
3 SOFT_ERROR_ER(node->assignExpr(), SWITCH_EXPR_MUST_BE_PRIMITIVE,
346 "Switch expression must be of int, short, long, byte, char or bool type")
347
348 // Visit children
349
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 visitChildren(node);
350
351 // Check if case constant types match switch expression type
352
3/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 28 times.
✓ Branch 9 taken 5 times.
33 for (const CaseBranchNode *caseBranchNode : node->caseBranches())
353
3/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 28 times.
✓ Branch 9 taken 26 times.
54 for (CaseConstantNode *constantNode : caseBranchNode->caseConstants()) {
354
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;
355
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))
356
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")
357
4/4
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 2 times.
35 }
358
359
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 return nullptr;
360 }
361
362 28 std::any TypeChecker::visitCaseBranch(CaseBranchNode *node) {
363 // Change to case body scope
364
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);
365
366 // Visit constant list
367
3/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 7 taken 28 times.
✓ Branch 8 taken 28 times.
56 for (CaseConstantNode *constant : node->caseConstants())
368
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
56 visit(constant);
369
370 // Visit body
371
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
28 visit(node->body());
372
373
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
56 return nullptr;
374 28 }
375
376 3 std::any TypeChecker::visitDefaultBranch(DefaultBranchNode *node) {
377 // Change to default body scope
378
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);
379
380 // Visit body
381
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 visit(node->body());
382
383
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
6 return nullptr;
384 3 }
385
386 13 std::any TypeChecker::visitAnonymousBlockStmt(AnonymousBlockStmtNode *node) {
387 // Change to anonymous scope body scope
388
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);
389
390 // Visit body
391
2/4
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
13 visit(node->body());
392
393
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
26 return nullptr;
394 13 }
395
396 13253 std::any TypeChecker::visitStmtLst(StmtLstNode *node) {
397 // Visit nodes in this scope
398
2/2
✓ Branch 5 taken 26430 times.
✓ Branch 6 taken 13222 times.
39652 for (ASTNode *stmt : node->children) {
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26430 times.
26430 if (!stmt)
400 continue;
401 // Print warning if statement is unreachable
402
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 26425 times.
26430 if (stmt->unreachable) {
403
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 warnings.emplace_back(stmt->codeLoc, UNREACHABLE_CODE, "This statement is unreachable");
404 5 continue;
405 }
406 // Visit the statement
407
2/2
✓ Branch 1 taken 26394 times.
✓ Branch 2 taken 31 times.
26425 visit(stmt);
408 }
409
410 // Do cleanup of this scope, e.g. dtor calls for struct instances
411 13222 doScopeCleanup(node);
412
413
1/2
✓ Branch 1 taken 13222 times.
✗ Branch 2 not taken.
13222 return nullptr;
414 }
415
416 9504 std::any TypeChecker::visitParamLst(ParamLstNode *node) {
417 9504 NamedParamList namedParams;
418 9504 bool metOptional = false;
419
420
3/4
✓ Branch 1 taken 9504 times.
✗ Branch 2 not taken.
✓ Branch 8 taken 15064 times.
✓ Branch 9 taken 9504 times.
24568 for (DeclStmtNode *param : node->params()) {
421 // Visit param
422
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));
423
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))
424 11 continue;
425
426 // Check if the type could be inferred. Dyn without a default value is forbidden
427
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)) {
428
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");
429 3 continue;
430 }
431
432 // Ensure that no optional param comes after a mandatory param
433
2/2
✓ Branch 0 taken 1859 times.
✓ Branch 1 taken 13200 times.
15059 if (param->hasAssignment) {
434 1859 metOptional = true;
435
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 13194 times.
13200 } else if (metOptional) {
436
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");
437 6 continue;
438 }
439
440 // Add parameter to named param list
441
1/2
✓ Branch 2 taken 15053 times.
✗ Branch 3 not taken.
15053 namedParams.push_back({param->varName.c_str(), paramType, metOptional});
442 9504 }
443
444
1/2
✓ Branch 1 taken 9504 times.
✗ Branch 2 not taken.
19008 return namedParams;
445 9504 }
446
447 1182 std::any TypeChecker::visitField(FieldNode *node) {
448
3/6
✓ Branch 1 taken 1182 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1182 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1182 times.
✗ Branch 8 not taken.
1182 auto fieldType = std::any_cast<QualType>(visit(node->dataType()));
449
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)
450
451
3/4
✓ Branch 1 taken 1181 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 151 times.
✓ Branch 4 taken 1030 times.
1181 if (TernaryExprNode *defaultValueNode = node->defaultValue()) {
452
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;
453
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)
454
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))
455
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")
456 }
457
458
1/2
✓ Branch 1 taken 1180 times.
✗ Branch 2 not taken.
1180 return fieldType;
459 }
460
461 172 std::any TypeChecker::visitSignature(SignatureNode *node) {
462 172 const bool isFunction = node->signatureType == SignatureNode::TYPE_FUNCTION;
463
464 // Retrieve function template types
465 172 std::vector<GenericType> usedGenericTypes;
466
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 81 times.
172 if (node->hasTemplateTypes) {
467
4/6
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 91 times.
✗ Branch 5 not taken.
✓ Branch 11 taken 91 times.
✓ Branch 12 taken 90 times.
181 for (DataTypeNode *dataType : node->templateTypeLst()->dataTypes()) {
468 // Visit template type
469
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));
470
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))
471 return static_cast<std::vector<Function *> *>(nullptr);
472 // Check if it is a generic type
473
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)) {
474
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");
475
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 return static_cast<std::vector<Function *> *>(nullptr);
476 }
477 // Convert generic symbol type to generic type
478
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());
479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 assert(genericType != nullptr);
480
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
90 usedGenericTypes.push_back(*genericType);
481
2/2
✓ Branch 1 taken 90 times.
✓ Branch 2 taken 1 times.
91 }
482 }
483
484 // Visit return type
485
1/2
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
171 QualType returnType(TY_DYN);
486
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 39 times.
171 if (isFunction) {
487
3/6
✓ Branch 1 taken 132 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 132 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 132 times.
✗ Branch 8 not taken.
132 returnType = std::any_cast<QualType>(visit(node->returnType()));
488
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))
489 return static_cast<std::vector<Function *> *>(nullptr);
490
491
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))
492
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.
2 softError(node->returnType(), GENERIC_TYPE_NOT_IN_TEMPLATE,
493 "Generic return type not included in the template type list of the function");
494 }
495
496 // Visit params
497 171 QualTypeList paramTypes;
498 171 ParamList paramList;
499
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 159 times.
171 if (node->hasParams) {
500
3/6
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 9 not taken.
12 paramList.reserve(node->paramTypeLst()->dataTypes().size());
501
4/6
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 11 taken 14 times.
✓ Branch 12 taken 12 times.
26 for (DataTypeNode *param : node->paramTypeLst()->dataTypes()) {
502
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));
503
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))
504 return static_cast<std::vector<Function *> *>(nullptr);
505
506 // Check if the type is present in the template for generic types
507
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)) {
508
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 softError(node->paramTypeLst(), GENERIC_TYPE_NOT_IN_TEMPLATE,
509 "Generic param type not included in the template type list of the function");
510 2 continue;
511 }
512
513
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 paramTypes.push_back(paramType);
514
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 paramList.push_back({paramType, false});
515
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 }
516 }
517
518 // Build signature object
519
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);
520
521 // Add signature to current scope
522
1/2
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
171 Function *manifestation = FunctionManager::insert(currentScope, signature, &node->signatureManifestations);
523 171 manifestation->entry = node->entry;
524 171 manifestation->used = true;
525
526 // Prepare signature type
527
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 39 times.
171 const SuperType superType = isFunction ? TY_FUNCTION : TY_PROCEDURE;
528
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);
529 171 signatureType.setSpecifiers(node->signatureSpecifiers);
530
531 // Set entry to signature type
532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 171 times.
171 assert(node->entry != nullptr);
533
1/2
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
171 node->entry->updateType(signatureType, false);
534 171 node->entry->used = true;
535
536
1/2
✓ Branch 1 taken 171 times.
✗ Branch 2 not taken.
171 return &node->signatureManifestations;
537 172 }
538
539 20795 std::any TypeChecker::visitDeclStmt(DeclStmtNode *node) {
540 // Retrieve entry of the lhs variable
541
1/2
✓ Branch 1 taken 20795 times.
✗ Branch 2 not taken.
20795 SymbolTableEntry *localVarEntry = currentScope->lookupStrict(node->varName);
542
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20795 times.
20795 assert(localVarEntry != nullptr);
543
544 20795 QualType localVarType;
545
2/2
✓ Branch 0 taken 7384 times.
✓ Branch 1 taken 13411 times.
20795 if (node->hasAssignment) {
546 // Visit the right side
547
4/6
✓ Branch 1 taken 7384 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7379 times.
✓ Branch 5 taken 5 times.
✓ Branch 7 taken 7379 times.
✗ Branch 8 not taken.
7384 auto rhs = std::any_cast<ExprResult>(visit(node->assignExpr()));
548 7379 auto [rhsTy, rhsEntry] = rhs;
549
550 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it
551
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) {
552
1/2
✓ Branch 1 taken 803 times.
✗ Branch 2 not taken.
803 currentScope->symbolTable.deleteAnonymous(rhsEntry->name);
553 803 rhs.entry = rhsEntry = nullptr;
554 }
555
556 // Visit data type
557
4/6
✓ Branch 1 taken 7379 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 7376 times.
✓ Branch 5 taken 3 times.
✓ Branch 7 taken 7376 times.
✗ Branch 8 not taken.
7379 localVarType = std::any_cast<QualType>(visit(node->dataType()));
558
559 // Infer the type left to right if the right side is an empty array initialization
560
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))
561 2 rhsTy = QualType(localVarType);
562
563 // Check if type has to be inferred or both types are fixed
564
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)) {
565 7353 const ExprResult lhsResult = {localVarType, localVarEntry};
566
2/2
✓ Branch 1 taken 7343 times.
✓ Branch 2 taken 10 times.
7353 localVarType = opRuleManager.getAssignResultType(node, lhsResult, rhs, true);
567
568 // Call copy ctor if required
569
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->isParam && !rhs.isTemporary()) {
570
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 Scope *matchScope = localVarType.getBodyScope();
571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(matchScope != nullptr);
572 // Check if we have a no-args ctor to call
573 3 const QualType &thisType = localVarType;
574
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}};
575
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);
576 3 }
577
578 // If this is a struct type, check if the type is known. If not, error out
579
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())) {
580 const std::string structName = localVarType.getBase().getSubType();
581 softError(node->dataType(), UNKNOWN_DATATYPE, "Unknown struct type '" + structName + "'. Forgot to import?");
582 localVarType = QualType(TY_UNRESOLVED);
583 }
584 } else {
585
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 localVarType = QualType(TY_UNRESOLVED);
586 }
587 } else {
588 // Visit data type
589
3/6
✓ Branch 1 taken 13411 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13411 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 13411 times.
✗ Branch 8 not taken.
13411 localVarType = std::any_cast<QualType>(visit(node->dataType()));
590
591 // References with no initialization are illegal
592
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->isParam && !node->isForEachItem)
593
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");
594
595 // If this is a struct, check for the default ctor
596
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->isParam && !node->isForEachItem) {
597
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 Scope *matchScope = localVarType.getBodyScope();
598
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49 times.
49 assert(matchScope != nullptr);
599 // Check if we are required to call a ctor
600
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);
601
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;
602 // Check if we have a no-args ctor to call
603
1/2
✓ Branch 1 taken 49 times.
✗ Branch 2 not taken.
49 const std::string &structName = localVarType.getSubType();
604 49 const QualType &thisType = localVarType;
605
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);
606
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)
607
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")
608 }
609 }
610
611 // Update the type of the variable
612
1/2
✓ Branch 1 taken 20775 times.
✗ Branch 2 not taken.
20775 localVarEntry->updateType(localVarType, true);
613
1/2
✓ Branch 1 taken 20775 times.
✗ Branch 2 not taken.
20775 node->entries.at(manIdx) = localVarEntry;
614
615 // Update the state of the variable
616
1/2
✓ Branch 1 taken 20775 times.
✗ Branch 2 not taken.
20775 localVarEntry->updateState(INITIALIZED, node, true);
617
618
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);
619 }
620
621 56 std::any TypeChecker::visitCaseConstant(CaseConstantNode *node) {
622 // If we have a normal constant, we can take the symbol type from there
623
3/4
✓ Branch 1 taken 56 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 20 times.
56 if (node->constant())
624
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
36 return visit(node->constant());
625
626 // Check if a local or global variable can be found by searching for the name
627
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 18 times.
20 if (node->identifierFragments.size() == 1)
628 4 node->enumItemEntry = currentScope->lookup(node->identifierFragments.back());
629
630 // If no local or global was found, search in the name registry
631
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
20 if (!node->enumItemEntry) {
632
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(node->fqIdentifier);
633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (!registryEntry)
634 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE, "The variable '" + node->fqIdentifier + "' could not be found")
635 9 node->enumItemEntry = registryEntry->targetEntry;
636 }
637
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 assert(node->enumItemEntry != nullptr);
638
639 // Check for the correct type
640
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 18 times.
20 if (node->enumItemEntry->scope->type != ScopeType::ENUM)
641
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")
642
643
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 const QualType varType = node->enumItemEntry->getQualType();
644
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));
645
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)};
646 }
647
648 5860 std::any TypeChecker::visitReturnStmt(ReturnStmtNode *node) {
649 // Retrieve return variable entry
650
1/2
✓ Branch 1 taken 5860 times.
✗ Branch 2 not taken.
17580 SymbolTableEntry *returnVar = currentScope->lookup(RETURN_VARIABLE_NAME);
651 5860 const bool isFunction = returnVar != nullptr;
652
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);
653
654 // Check if procedure with return value
655
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 5816 times.
5860 if (!isFunction) {
656
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 42 times.
44 if (node->hasReturnValue)
657
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 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 2 times.
✗ Branch 18 not taken.
✓ Branch 20 taken 2 times.
✗ Branch 21 not taken.
6 SOFT_ERROR_ER(node->assignExpr(), RETURN_WITH_VALUE_IN_PROCEDURE, "Return with value in procedure is not allowed")
658
1/2
✓ Branch 1 taken 42 times.
✗ Branch 2 not taken.
42 return nullptr;
659 }
660
661
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())
662
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")
663
664
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5810 times.
5814 if (!node->hasReturnValue)
665
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 return nullptr;
666
667 // Visit right side
668
3/6
✓ Branch 1 taken 5810 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5810 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 5810 times.
✗ Branch 8 not taken.
5810 auto rhs = std::any_cast<ExprResult>(visit(node->assignExpr()));
669
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)
670
671 // Check if types match
672 5810 const ExprResult returnResult = {returnType, returnVar};
673
3/4
✓ Branch 1 taken 5810 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5808 times.
✓ Branch 5 taken 2 times.
5810 (void)opRuleManager.getAssignResultType(node->assignExpr(), returnResult, rhs, false, true, ERROR_MSG_RETURN);
674
675 // Manage dtor call
676
2/2
✓ Branch 0 taken 1575 times.
✓ Branch 1 taken 4233 times.
5808 if (rhs.entry != nullptr) {
677
2/2
✓ Branch 0 taken 622 times.
✓ Branch 1 taken 953 times.
1575 if (rhs.entry->anonymous) {
678 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it
679
1/2
✓ Branch 1 taken 622 times.
✗ Branch 2 not taken.
622 currentScope->symbolTable.deleteAnonymous(rhs.entry->name);
680 622 rhs.entry = nullptr;
681 } else {
682 // Otherwise omit the destructor call, because the caller destructs the value
683 953 rhs.entry->omitDtorCall = true;
684 }
685 }
686
687
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);
688 }
689
690 101 std::any TypeChecker::visitBreakStmt(BreakStmtNode *node) {
691 // Check if the stated number is valid
692
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 100 times.
101 if (node->breakTimes < 1)
693
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))
694
695 // Check if we can break this often
696 100 const unsigned int maxBreaks = currentScope->getLoopNestingDepth();
697
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 99 times.
100 if (static_cast<unsigned int>(node->breakTimes) > maxBreaks)
698
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")
699
700
1/2
✓ Branch 1 taken 99 times.
✗ Branch 2 not taken.
99 return nullptr;
701 }
702
703 335 std::any TypeChecker::visitContinueStmt(ContinueStmtNode *node) {
704 // Check if the stated number is valid
705
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 334 times.
335 if (node->continueTimes < 1)
706
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,
707 "Continue count must be >= 1, you provided " + std::to_string(node->continueTimes))
708
709 // Check if we can continue this often
710 334 const unsigned int maxContinues = currentScope->getLoopNestingDepth();
711
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 333 times.
334 if (static_cast<unsigned int>(node->continueTimes) > maxContinues)
712
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")
713
714
1/2
✓ Branch 1 taken 333 times.
✗ Branch 2 not taken.
333 return nullptr;
715 }
716
717 6 std::any TypeChecker::visitFallthroughStmt(FallthroughStmtNode *node) {
718 // Check if we can do a fallthrough here
719
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (!currentScope->isInCaseBranch())
720
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")
721
722
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 return nullptr;
723 }
724
725 657 std::any TypeChecker::visitAssertStmt(AssertStmtNode *node) {
726 // Visit condition
727
3/6
✓ Branch 1 taken 657 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 657 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 657 times.
✗ Branch 8 not taken.
657 const QualType conditionType = std::any_cast<ExprResult>(visit(node->assignExpr())).type;
728
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)
729
730 // Check if condition evaluates to bool
731
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))
732
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 11 taken 1 times.
✗ Branch 12 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.
3 SOFT_ERROR_ER(node->assignExpr(), ASSERTION_CONDITION_BOOL, "The asserted condition must be of type bool")
733
734
1/2
✓ Branch 1 taken 656 times.
✗ Branch 2 not taken.
656 return nullptr;
735 }
736
737 651 std::any TypeChecker::visitPrintfCall(PrintfCallNode *node) {
738 // Check if assignment types match placeholder types
739 651 size_t placeholderCount = 0;
740 651 size_t index = node->templatedString.find_first_of('%');
741
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) {
742 // Check if there is another assignExpr
743
3/4
✓ Branch 1 taken 550 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 549 times.
550 if (node->args().size() <= placeholderCount)
744
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")
745
746 // Get next assignment
747
2/4
✓ Branch 1 taken 549 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 549 times.
✗ Branch 5 not taken.
549 AssignExprNode *assignment = node->args().at(placeholderCount);
748 // Visit assignment
749
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;
750
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)
751
1/2
✓ Branch 1 taken 534 times.
✗ Branch 2 not taken.
534 argType = argType.removeReferenceWrapper();
752
753
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)) {
754 15 case 'c': {
755
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))
756
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))
757 14 placeholderCount++;
758 14 break;
759 }
760 292 case 'd':
761 case 'i':
762 case 'l':
763 case 'o':
764 case 'u':
765 case 'x':
766 case 'X': {
767
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}))
768
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,
769 "The placeholder string expects int, short, long, byte or bool, but got " + argType.getName(false))
770 290 placeholderCount++;
771 290 break;
772 }
773 34 case 'a':
774 case 'A':
775 case 'f':
776 case 'F':
777 case 'e':
778 case 'E':
779 case 'g':
780 case 'G': {
781
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))
782
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))
783 33 placeholderCount++;
784 33 break;
785 }
786 188 case 's': {
787
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))
788
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,
789 "The placeholder string expects string, String, char* or char[], but got " + argType.getName(false))
790 187 placeholderCount++;
791 187 break;
792 }
793 5 case 'p': {
794
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))
795
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,
796 "The placeholder string expects pointer, array or string, but got " + argType.getName(false))
797 4 placeholderCount++;
798 4 break;
799 }
800 default:
801 SOFT_ERROR_ER(node, PRINTF_TYPE_ERROR, "The placeholder string contains an invalid placeholder")
802 }
803 528 index = node->templatedString.find_first_of('%', index + 2); // We can also skip the following char
804 }
805
806 // Check if the number of placeholders matches the number of args
807
3/4
✓ Branch 1 taken 629 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 628 times.
629 if (placeholderCount < node->args().size())
808
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")
809
810
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)};
811 }
812
813 119 std::any TypeChecker::visitSizeofCall(SizeofCallNode *node) {
814
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 17 times.
119 if (node->isType) { // Size of type
815
2/4
✓ Branch 1 taken 102 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 102 times.
✗ Branch 5 not taken.
102 visit(node->dataType());
816 } else { // Size of value
817
2/4
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 17 times.
✗ Branch 5 not taken.
17 visit(node->assignExpr());
818 }
819
820
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)};
821 }
822
823 11 std::any TypeChecker::visitAlignofCall(AlignofCallNode *node) {
824
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (node->isType) { // Align of type
825
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 visit(node->dataType());
826 } else { // Align of value
827
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
10 visit(node->assignExpr());
828 }
829
830
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)};
831 }
832
833 36 std::any TypeChecker::visitLenCall(LenCallNode *node) {
834
3/6
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 36 times.
✗ Branch 8 not taken.
36 QualType argType = std::any_cast<ExprResult>(visit(node->assignExpr())).type;
835
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)
836
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 argType = argType.removeReferenceWrapper();
837
838 // Check if arg is of type array
839
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))
840
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 11 taken 1 times.
✗ Branch 12 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.
3 SOFT_ERROR_ER(node->assignExpr(), EXPECTED_ARRAY_TYPE, "The len builtin can only work on arrays or strings")
841
842 // If we want to use the len builtin on a string, we need to import the string runtime module
843
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())
844
1/2
✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
23 sourceFile->requestRuntimeModule(STRING_RT);
845
846
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)};
847 }
848
849 366 std::any TypeChecker::visitPanicCall(PanicCallNode *node) {
850
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 QualType argType = std::any_cast<ExprResult>(visit(node->assignExpr())).type;
851
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)
852
1/2
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
366 argType = argType.removeReferenceWrapper();
853
854 // Check if arg is of type array
855
2/4
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 366 times.
366 if (!argType.isErrorObj())
856 SOFT_ERROR_ER(node->assignExpr(), EXPECTED_ERROR_TYPE, "The panic builtin can only work with errors")
857
858
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)};
859 }
860
861 1 std::any TypeChecker::visitSysCall(SysCallNode *node) {
862 // Check if the syscall number if of type short
863
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const std::vector<AssignExprNode *> assignExprs = node->assignExprs();
864
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(assignExprs.front())).type;
865
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))
866 SOFT_ERROR_ER(assignExprs.front(), INVALID_SYSCALL_NUMBER_TYPE, "Syscall number must be of type short")
867
868 // Check if the syscall number is out of range
869 // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/
870
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
1 if (node->hasCompileTimeValue()) {
871 const unsigned short sysCallNumber = node->getCompileTimeValue().shortValue;
872 if (sysCallNumber < 0 || sysCallNumber > 439)
873 SOFT_ERROR_ER(node, SYSCALL_NUMBER_OUT_OF_RANGE, "Only syscall numbers between 0 and 439 are supported")
874 }
875
876 // Check if too many syscall args are given
877 // According to https://www.chromium.org/chromium-os/developer-library/reference/linux-constants/syscalls/
878
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
1 if (node->assignExprs().size() > 6)
879 SOFT_ERROR_ER(node->assignExprs().front(), TOO_MANY_SYSCALL_ARGS, "There are no syscalls that support more than 6 arguments")
880
881 // Visit children
882
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
4 for (size_t i = 1; i < assignExprs.size(); i++)
883
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 visit(assignExprs.at(i));
884
885
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)};
886 1 }
887
888 48605 std::any TypeChecker::visitAssignExpr(AssignExprNode *node) {
889 // Check if ternary
890
2/2
✓ Branch 1 taken 43821 times.
✓ Branch 2 taken 4784 times.
48605 if (node->ternaryExpr()) {
891
4/6
✓ Branch 1 taken 43821 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 43806 times.
✓ Branch 5 taken 15 times.
✓ Branch 7 taken 43806 times.
✗ Branch 8 not taken.
43821 auto result = std::any_cast<ExprResult>(visit(node->ternaryExpr()));
892
1/2
✓ Branch 1 taken 43806 times.
✗ Branch 2 not taken.
43806 node->setEvaluatedSymbolType(result.type, manIdx);
893
1/2
✓ Branch 1 taken 43806 times.
✗ Branch 2 not taken.
43806 return result;
894 }
895
896 // Check if assignment
897
1/2
✓ Branch 0 taken 4784 times.
✗ Branch 1 not taken.
4784 if (node->op != AssignExprNode::OP_NONE) {
898 // Visit the right side first
899
3/6
✓ Branch 1 taken 4784 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4784 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4784 times.
✗ Branch 8 not taken.
4784 auto rhs = std::any_cast<ExprResult>(visit(node->rhs()));
900 4784 auto [rhsType, rhsEntry] = rhs;
901
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)
902 // Then visit the left side
903
3/6
✓ Branch 1 taken 4783 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4783 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4783 times.
✗ Branch 8 not taken.
4783 auto lhs = std::any_cast<ExprResult>(visit(node->lhs()));
904 4783 auto [lhsType, lhsVar] = lhs;
905
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)
906
907 // Take a look at the operator
908
2/2
✓ Branch 0 taken 4251 times.
✓ Branch 1 taken 531 times.
4782 if (node->op == AssignExprNode::OP_ASSIGN) {
909
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();
910
2/2
✓ Branch 1 taken 4249 times.
✓ Branch 2 taken 2 times.
4251 rhsType = opRuleManager.getAssignResultType(node, lhs, rhs, isDecl);
911
912 // If there is an anonymous entry attached (e.g. for struct instantiation), delete it
913
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) {
914
1/2
✓ Branch 1 taken 125 times.
✗ Branch 2 not taken.
125 currentScope->symbolTable.deleteAnonymous(rhsEntry->name);
915 125 rhsEntry = nullptr;
916 }
917
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 318 times.
531 } else if (node->op == AssignExprNode::OP_PLUS_EQUAL) {
918
1/2
✓ Branch 1 taken 213 times.
✗ Branch 2 not taken.
213 rhsType = opRuleManager.getPlusEqualResultType(node, lhs, rhs, 0).type;
919
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 291 times.
318 } else if (node->op == AssignExprNode::OP_MINUS_EQUAL) {
920
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 rhsType = opRuleManager.getMinusEqualResultType(node, lhs, rhs, 0).type;
921
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 276 times.
291 } else if (node->op == AssignExprNode::OP_MUL_EQUAL) {
922
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 rhsType = opRuleManager.getMulEqualResultType(node, lhs, rhs, 0).type;
923
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 241 times.
276 } else if (node->op == AssignExprNode::OP_DIV_EQUAL) {
924
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 rhsType = opRuleManager.getDivEqualResultType(node, lhs, rhs, 0).type;
925
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 236 times.
241 } else if (node->op == AssignExprNode::OP_REM_EQUAL) {
926
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 rhsType = OpRuleManager::getRemEqualResultType(node, lhs, rhs);
927
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 235 times.
236 } else if (node->op == AssignExprNode::OP_SHL_EQUAL) {
928
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 rhsType = OpRuleManager::getSHLEqualResultType(node, lhs, rhs);
929
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 233 times.
235 } else if (node->op == AssignExprNode::OP_SHR_EQUAL) {
930
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 rhsType = OpRuleManager::getSHREqualResultType(node, lhs, rhs);
931
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 232 times.
233 } else if (node->op == AssignExprNode::OP_AND_EQUAL) {
932
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 rhsType = OpRuleManager::getAndEqualResultType(node, lhs, rhs);
933
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 231 times.
232 } else if (node->op == AssignExprNode::OP_OR_EQUAL) {
934
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 rhsType = OpRuleManager::getOrEqualResultType(node, lhs, rhs);
935
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 } else if (node->op == AssignExprNode::OP_XOR_EQUAL) {
936
1/2
✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
231 rhsType = OpRuleManager::getXorEqualResultType(node, lhs, rhs);
937 }
938
939
1/2
✓ Branch 0 taken 4780 times.
✗ Branch 1 not taken.
4780 if (lhsVar) { // Variable is involved on the left side
940 // Perform type inference
941
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))
942
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 lhsVar->updateType(rhsType, false);
943
944 // In case the lhs variable is captured, notify the capture about the write access
945
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)
946
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 lhsCapture->setAccessType(READ_WRITE);
947
948 // Update the state of the variable
949
1/2
✓ Branch 1 taken 4780 times.
✗ Branch 2 not taken.
4780 lhsVar->updateState(INITIALIZED, node, false);
950 }
951
952
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)};
953 }
954
955 throw CompilerError(UNHANDLED_BRANCH, "AssignExpr fall-through"); // GCOV_EXCL_LINE
956 }
957
958 44653 std::any TypeChecker::visitTernaryExpr(TernaryExprNode *node) {
959 // Check if there is a ternary operator applied
960
2/2
✓ Branch 1 taken 44370 times.
✓ Branch 2 taken 283 times.
44653 if (node->children.size() == 1)
961
3/4
✓ Branch 1 taken 44370 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 44355 times.
✓ Branch 6 taken 15 times.
88740 return visit(node->operands().front());
962
963 // Visit condition
964
1/2
✓ Branch 1 taken 283 times.
✗ Branch 2 not taken.
283 LogicalOrExprNode *condition = node->operands()[0];
965
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(condition)).type;
966
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)
967
968 283 QualType trueType;
969 283 QualType falseType;
970
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 282 times.
283 if (node->isShortened) {
971 1 trueType = conditionType;
972
3/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
1 falseType = std::any_cast<ExprResult>(visit(node->operands()[1])).type;
973 } else {
974
3/6
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 282 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 282 times.
✗ Branch 9 not taken.
282 trueType = std::any_cast<ExprResult>(visit(node->operands()[1])).type;
975
2/10
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 282 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.
282 HANDLE_UNRESOLVED_TYPE_ER(trueType)
976
3/6
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 282 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 282 times.
✗ Branch 9 not taken.
282 falseType = std::any_cast<ExprResult>(visit(node->operands()[2])).type;
977 }
978
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)
979
980 // Check if the condition evaluates to bool
981
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))
982
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(condition, OPERATOR_WRONG_DATA_TYPE, "Condition operand in ternary must be a bool")
983
984 // Check if trueType and falseType are matching
985
1/2
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
282 const QualType trueTypeModified = trueType.removeReferenceWrapper();
986
1/2
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
282 const QualType falseTypeModified = falseType.removeReferenceWrapper();
987
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))
988
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,
989 "True and false operands in ternary must be of same data type. Got " + trueType.getName(true) + " and " +
990 falseType.getName(true))
991
992
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)};
993 }
994
995 45218 std::any TypeChecker::visitLogicalOrExpr(LogicalOrExprNode *node) {
996 // Check if a logical or operator is applied
997
2/2
✓ Branch 1 taken 44957 times.
✓ Branch 2 taken 261 times.
45218 if (node->children.size() == 1)
998
3/4
✓ Branch 1 taken 44957 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 44943 times.
✓ Branch 6 taken 14 times.
89914 return visit(node->operands().front());
999
1000 // Visit leftmost operand
1001
3/6
✓ Branch 1 taken 261 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 261 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 261 times.
✗ Branch 9 not taken.
261 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands()[0]));
1002
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)
1003 // Loop through all remaining operands
1004
3/4
✓ Branch 1 taken 548 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 288 times.
✓ Branch 6 taken 260 times.
548 for (size_t i = 1; i < node->operands().size(); i++) {
1005
3/6
✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 288 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 288 times.
✗ Branch 9 not taken.
288 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands()[i]));
1006
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)
1007
2/2
✓ Branch 1 taken 287 times.
✓ Branch 2 taken 1 times.
288 currentOperand = {OpRuleManager::getLogicalOrResultType(node, currentOperand, rhsOperand)};
1008 }
1009
1010
1/2
✓ Branch 1 taken 260 times.
✗ Branch 2 not taken.
260 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1011
1/2
✓ Branch 1 taken 260 times.
✗ Branch 2 not taken.
260 return currentOperand;
1012 }
1013
1014 45506 std::any TypeChecker::visitLogicalAndExpr(LogicalAndExprNode *node) {
1015 // Check if a logical and operator is applied
1016
2/2
✓ Branch 1 taken 45448 times.
✓ Branch 2 taken 58 times.
45506 if (node->children.size() == 1)
1017
3/4
✓ Branch 1 taken 45448 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 45434 times.
✓ Branch 6 taken 14 times.
90896 return visit(node->operands().front());
1018
1019 // Visit leftmost operand
1020
3/6
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 58 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 58 times.
✗ Branch 9 not taken.
58 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands()[0]));
1021
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)
1022 // Loop through all remaining operands
1023
3/4
✓ Branch 1 taken 123 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 65 times.
✓ Branch 6 taken 58 times.
123 for (size_t i = 1; i < node->operands().size(); i++) {
1024
3/6
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 65 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 65 times.
✗ Branch 9 not taken.
65 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands()[i]));
1025
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)
1026
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 currentOperand = {OpRuleManager::getLogicalAndResultType(node, currentOperand, rhsOperand)};
1027 }
1028
1029
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1030
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 return currentOperand;
1031 }
1032
1033 45571 std::any TypeChecker::visitBitwiseOrExpr(BitwiseOrExprNode *node) {
1034 // Check if a bitwise or operator is applied
1035
2/2
✓ Branch 1 taken 45538 times.
✓ Branch 2 taken 33 times.
45571 if (node->children.size() == 1)
1036
3/4
✓ Branch 1 taken 45538 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 45525 times.
✓ Branch 6 taken 13 times.
91076 return visit(node->operands().front());
1037
1038 // Visit leftmost operand
1039
3/6
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 33 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 33 times.
✗ Branch 9 not taken.
33 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands()[0]));
1040
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)
1041 // Loop through all remaining operands
1042
3/4
✓ Branch 1 taken 68 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 36 times.
✓ Branch 6 taken 32 times.
68 for (size_t i = 1; i < node->operands().size(); i++) {
1043
3/6
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 36 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 36 times.
✗ Branch 9 not taken.
36 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands()[i]));
1044
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)
1045
2/2
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 1 times.
36 currentOperand = {OpRuleManager::getBitwiseOrResultType(node, currentOperand, rhsOperand)};
1046 }
1047
1048
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1049
1/2
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
32 return currentOperand;
1050 }
1051
1052 45607 std::any TypeChecker::visitBitwiseXorExpr(BitwiseXorExprNode *node) {
1053 // Check if a bitwise xor operator is applied
1054
2/2
✓ Branch 1 taken 45603 times.
✓ Branch 2 taken 4 times.
45607 if (node->children.size() == 1)
1055
3/4
✓ Branch 1 taken 45603 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 45590 times.
✓ Branch 6 taken 13 times.
91206 return visit(node->operands().front());
1056
1057 // Visit leftmost operand
1058
3/6
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
4 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands()[0]));
1059
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)
1060 // Loop through all remaining operands
1061
3/4
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 4 times.
11 for (size_t i = 1; i < node->operands().size(); i++) {
1062
3/6
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
7 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands()[i]));
1063
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)
1064
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 currentOperand = {OpRuleManager::getBitwiseXorResultType(node, currentOperand, rhsOperand)};
1065 }
1066
1067
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1068
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 return currentOperand;
1069 }
1070
1071 45614 std::any TypeChecker::visitBitwiseAndExpr(BitwiseAndExprNode *node) {
1072 // Check if a bitwise and operator is applied
1073
2/2
✓ Branch 1 taken 45584 times.
✓ Branch 2 taken 30 times.
45614 if (node->children.size() == 1)
1074
3/4
✓ Branch 1 taken 45584 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 45571 times.
✓ Branch 6 taken 13 times.
91168 return visit(node->operands().front());
1075
1076 // Visit leftmost operand
1077
3/6
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 30 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 30 times.
✗ Branch 9 not taken.
30 auto currentOperand = std::any_cast<ExprResult>(visit(node->operands()[0]));
1078
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)
1079 // Loop through all remaining operands
1080
3/4
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 33 times.
✓ Branch 6 taken 30 times.
63 for (size_t i = 1; i < node->operands().size(); i++) {
1081
3/6
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 33 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 33 times.
✗ Branch 9 not taken.
33 auto rhsOperand = std::any_cast<ExprResult>(visit(node->operands()[i]));
1082
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)
1083
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 currentOperand = {OpRuleManager::getBitwiseAndResultType(node, currentOperand, rhsOperand)};
1084 }
1085
1086
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 node->setEvaluatedSymbolType(currentOperand.type, manIdx);
1087
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 return currentOperand;
1088 }
1089
1090 45647 std::any TypeChecker::visitEqualityExpr(EqualityExprNode *node) {
1091 // Check if at least one equality operator is applied
1092
2/2
✓ Branch 1 taken 41953 times.
✓ Branch 2 taken 3694 times.
45647 if (node->children.size() == 1)
1093
3/4
✓ Branch 1 taken 41953 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 41941 times.
✓ Branch 6 taken 12 times.
83906 return visit(node->operands().front());
1094
1095 // Visit right side first, then left side
1096
3/6
✓ Branch 1 taken 3694 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3694 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3694 times.
✗ Branch 9 not taken.
3694 auto rhs = std::any_cast<ExprResult>(visit(node->operands()[1]));
1097
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)
1098
3/6
✓ Branch 1 taken 3694 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3694 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3694 times.
✗ Branch 9 not taken.
3694 auto lhs = std::any_cast<ExprResult>(visit(node->operands()[0]));
1099
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)
1100
1101 // Check if we need the string runtime to perform a string comparison
1102
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())
1103
1/2
✓ Branch 1 taken 117 times.
✗ Branch 2 not taken.
117 sourceFile->requestRuntimeModule(STRING_RT);
1104
1105 // Check operator
1106 3694 ExprResult result;
1107
2/2
✓ Branch 0 taken 2379 times.
✓ Branch 1 taken 1315 times.
3694 if (node->op == EqualityExprNode::OP_EQUAL) // Operator was equal
1108
2/2
✓ Branch 1 taken 2378 times.
✓ Branch 2 taken 1 times.
2379 result = opRuleManager.getEqualResultType(node, lhs, rhs, 0);
1109
1/2
✓ Branch 0 taken 1315 times.
✗ Branch 1 not taken.
1315 else if (node->op == EqualityExprNode::OP_NOT_EQUAL) // Operator was not equal
1110
1/2
✓ Branch 1 taken 1315 times.
✗ Branch 2 not taken.
1315 result = opRuleManager.getNotEqualResultType(node, lhs, rhs, 0);
1111 else
1112 throw CompilerError(UNHANDLED_BRANCH, "EqualityExpr fall-through"); // GCOV_EXCL_LINE
1113
1114
1/2
✓ Branch 1 taken 3693 times.
✗ Branch 2 not taken.
3693 node->setEvaluatedSymbolType(result.type, manIdx);
1115
1/2
✓ Branch 1 taken 3693 times.
✗ Branch 2 not taken.
3693 return result;
1116 }
1117
1118 49341 std::any TypeChecker::visitRelationalExpr(RelationalExprNode *node) {
1119 // Check if a relational operator is applied
1120
2/2
✓ Branch 1 taken 46791 times.
✓ Branch 2 taken 2550 times.
49341 if (node->children.size() == 1)
1121
3/4
✓ Branch 1 taken 46791 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 46780 times.
✓ Branch 6 taken 11 times.
93582 return visit(node->operands().front());
1122
1123 // Visit right side first, then left side
1124
3/6
✓ Branch 1 taken 2550 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2550 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2550 times.
✗ Branch 9 not taken.
2550 auto rhs = std::any_cast<ExprResult>(visit(node->operands()[1]));
1125
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)
1126
3/6
✓ Branch 1 taken 2549 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2549 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2549 times.
✗ Branch 9 not taken.
2549 auto lhs = std::any_cast<ExprResult>(visit(node->operands()[0]));
1127
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)
1128
1129 // Check operator
1130 2549 QualType resultType;
1131
2/2
✓ Branch 0 taken 1476 times.
✓ Branch 1 taken 1073 times.
2549 if (node->op == RelationalExprNode::OP_LESS) // Operator was less
1132
1/2
✓ Branch 1 taken 1476 times.
✗ Branch 2 not taken.
1476 resultType = OpRuleManager::getLessResultType(node, lhs, rhs);
1133
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 827 times.
1073 else if (node->op == RelationalExprNode::OP_GREATER) // Operator was greater
1134
2/2
✓ Branch 1 taken 245 times.
✓ Branch 2 taken 1 times.
246 resultType = OpRuleManager::getGreaterResultType(node, lhs, rhs);
1135
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
1136
1/2
✓ Branch 1 taken 263 times.
✗ Branch 2 not taken.
263 resultType = OpRuleManager::getLessEqualResultType(node, lhs, rhs);
1137
1/2
✓ Branch 0 taken 564 times.
✗ Branch 1 not taken.
564 else if (node->op == RelationalExprNode::OP_GREATER_EQUAL) // Operator was greater equal
1138
1/2
✓ Branch 1 taken 564 times.
✗ Branch 2 not taken.
564 resultType = OpRuleManager::getGreaterEqualResultType(node, lhs, rhs);
1139 else
1140 throw CompilerError(UNHANDLED_BRANCH, "RelationalExpr fall-through"); // GCOV_EXCL_LINE
1141
1142
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)};
1143 }
1144
1145 51890 std::any TypeChecker::visitShiftExpr(ShiftExprNode *node) {
1146 // Check if at least one shift operator is applied
1147
2/2
✓ Branch 1 taken 51873 times.
✓ Branch 2 taken 17 times.
51890 if (node->children.size() == 1)
1148
3/4
✓ Branch 1 taken 51873 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 51862 times.
✓ Branch 6 taken 11 times.
103746 return visit(node->operands().front());
1149
1150 // Visit right side first, then left
1151
3/6
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 17 times.
✗ Branch 9 not taken.
17 auto rhs = std::any_cast<ExprResult>(visit(node->operands()[1]));
1152
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)
1153
3/6
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 17 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 17 times.
✗ Branch 9 not taken.
17 auto lhs = std::any_cast<ExprResult>(visit(node->operands()[0]));
1154
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)
1155
1156 // Check operator
1157 17 ExprResult currentResult;
1158
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 if (node->op == ShiftExprNode::OP_SHIFT_LEFT) // Operator was shl
1159
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 currentResult = opRuleManager.getShiftLeftResultType(node, lhs, rhs, 0);
1160
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 else if (node->op == ShiftExprNode::OP_SHIFT_RIGHT) // Operator was shr
1161
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 currentResult = opRuleManager.getShiftRightResultType(node, lhs, rhs, 0);
1162 else
1163 throw CompilerError(UNHANDLED_BRANCH, "ShiftExpr fall-through"); // GCOV_EXCL_LINE
1164
1165
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 node->setEvaluatedSymbolType(currentResult.type, manIdx);
1166
1/2
✓ Branch 1 taken 17 times.
✗ Branch 2 not taken.
17 return currentResult;
1167 }
1168
1169 51907 std::any TypeChecker::visitAdditiveExpr(AdditiveExprNode *node) {
1170 // Check if at least one additive operator is applied
1171
2/2
✓ Branch 1 taken 48885 times.
✓ Branch 2 taken 3022 times.
51907 if (node->children.size() == 1)
1172
3/4
✓ Branch 1 taken 48885 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 48875 times.
✓ Branch 6 taken 10 times.
97770 return visit(node->operands().front());
1173
1174 // Visit leftmost operand
1175
3/6
✓ Branch 1 taken 3022 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3022 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 3022 times.
✗ Branch 9 not taken.
3022 auto currentResult = std::any_cast<ExprResult>(visit(node->operands()[0]));
1176
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)
1177
1178 // Loop through remaining operands
1179
2/2
✓ Branch 1 taken 3437 times.
✓ Branch 2 taken 3021 times.
6458 for (size_t i = 0; i < node->opQueue.size(); i++) {
1180 // Visit next operand
1181
1/2
✓ Branch 1 taken 3437 times.
✗ Branch 2 not taken.
3437 MultiplicativeExprNode *operand = node->operands()[i + 1];
1182
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));
1183
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)
1184
1185 // Check operator
1186 3437 const AdditiveExprNode::AdditiveOp &op = node->opQueue.front().first;
1187
2/2
✓ Branch 0 taken 2178 times.
✓ Branch 1 taken 1259 times.
3437 if (op == AdditiveExprNode::OP_PLUS)
1188
2/2
✓ Branch 1 taken 2177 times.
✓ Branch 2 taken 1 times.
2178 currentResult = opRuleManager.getPlusResultType(node, currentResult, operandResult, i);
1189
1/2
✓ Branch 0 taken 1259 times.
✗ Branch 1 not taken.
1259 else if (op == AdditiveExprNode::OP_MINUS)
1190
1/2
✓ Branch 1 taken 1259 times.
✗ Branch 2 not taken.
1259 currentResult = opRuleManager.getMinusResultType(node, currentResult, operandResult, i);
1191 else
1192 throw CompilerError(UNHANDLED_BRANCH, "AdditiveExpr fall-through"); // GCOV_EXCL_LINE
1193
1194 // Push the new item and pop the old one on the other side of the queue
1195
1/2
✓ Branch 1 taken 3436 times.
✗ Branch 2 not taken.
3436 node->opQueue.emplace(op, currentResult.type);
1196 3436 node->opQueue.pop();
1197 }
1198
1199
1/2
✓ Branch 1 taken 3021 times.
✗ Branch 2 not taken.
3021 node->setEvaluatedSymbolType(currentResult.type, manIdx);
1200
1/2
✓ Branch 1 taken 3021 times.
✗ Branch 2 not taken.
3021 return currentResult;
1201 }
1202
1203 55344 std::any TypeChecker::visitMultiplicativeExpr(MultiplicativeExprNode *node) {
1204 // Check if at least one multiplicative operator is applied
1205
2/2
✓ Branch 1 taken 54500 times.
✓ Branch 2 taken 844 times.
55344 if (node->children.size() == 1)
1206
3/4
✓ Branch 1 taken 54500 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 54491 times.
✓ Branch 6 taken 9 times.
109000 return visit(node->operands().front());
1207
1208 // Visit leftmost operand
1209
3/6
✓ Branch 1 taken 844 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 844 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 844 times.
✗ Branch 9 not taken.
844 auto currentResult = std::any_cast<ExprResult>(visit(node->operands()[0]));
1210
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)
1211 // Loop through remaining operands
1212
2/2
✓ Branch 1 taken 868 times.
✓ Branch 2 taken 843 times.
1711 for (size_t i = 0; i < node->opQueue.size(); i++) {
1213 // Visit next operand
1214
1/2
✓ Branch 1 taken 868 times.
✗ Branch 2 not taken.
868 CastExprNode *operand = node->operands()[i + 1];
1215
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));
1216
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)
1217
1218 // Check operator
1219 868 const MultiplicativeExprNode::MultiplicativeOp &op = node->opQueue.front().first;
1220
2/2
✓ Branch 0 taken 654 times.
✓ Branch 1 taken 214 times.
868 if (op == MultiplicativeExprNode::OP_MUL)
1221
2/2
✓ Branch 1 taken 653 times.
✓ Branch 2 taken 1 times.
654 currentResult = opRuleManager.getMulResultType(node, currentResult, operandResult, i);
1222
2/2
✓ Branch 0 taken 205 times.
✓ Branch 1 taken 9 times.
214 else if (op == MultiplicativeExprNode::OP_DIV)
1223
1/2
✓ Branch 1 taken 205 times.
✗ Branch 2 not taken.
205 currentResult = opRuleManager.getDivResultType(node, currentResult, operandResult, i);
1224
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 else if (op == MultiplicativeExprNode::OP_REM)
1225
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 currentResult = OpRuleManager::getRemResultType(node, currentResult, operandResult);
1226 else
1227 throw CompilerError(UNHANDLED_BRANCH, "Multiplicative fall-through"); // GCOV_EXCL_LINE
1228
1229 // Push the new item and pop the old one on the other side of the queue
1230
1/2
✓ Branch 1 taken 867 times.
✗ Branch 2 not taken.
867 node->opQueue.emplace(op, currentResult.type);
1231 867 node->opQueue.pop();
1232 }
1233
1234
1/2
✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
843 node->setEvaluatedSymbolType(currentResult.type, manIdx);
1235
1/2
✓ Branch 1 taken 843 times.
✗ Branch 2 not taken.
843 return currentResult;
1236 }
1237
1238 56212 std::any TypeChecker::visitCastExpr(CastExprNode *node) {
1239 // Check if cast is applied
1240
2/2
✓ Branch 0 taken 53855 times.
✓ Branch 1 taken 2357 times.
56212 if (!node->isCast)
1241
3/4
✓ Branch 1 taken 53855 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 53846 times.
✓ Branch 5 taken 9 times.
53855 return visit(node->prefixUnaryExpr());
1242
1243 // Visit source type
1244
3/6
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2357 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2357 times.
✗ Branch 8 not taken.
2357 const auto src = std::any_cast<ExprResult>(visit(node->prefixUnaryExpr()));
1245
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)
1246 // Visit destination type
1247
3/6
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2357 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2357 times.
✗ Branch 8 not taken.
2357 const auto dstType = std::any_cast<QualType>(visit(node->dataType()));
1248
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)
1249
1250 // Check for identity cast
1251
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) {
1252
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.");
1253
1/2
✓ Branch 1 taken 1006 times.
✗ Branch 2 not taken.
1006 sourceFile->compilerOutput.warnings.push_back(warning);
1254 1006 }
1255
1256 // Get result type
1257
1/2
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
2357 const QualType resultType = opRuleManager.getCastResultType(node, dstType, src);
1258
1259
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;
1260
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};
1261 }
1262
1263 61834 std::any TypeChecker::visitPrefixUnaryExpr(PrefixUnaryExprNode *node) {
1264 // Reset access scope
1265 61834 accessScope = nullptr;
1266
1267 // If no operator is applied, simply visit the postfix unary expression
1268
2/2
✓ Branch 0 taken 60995 times.
✓ Branch 1 taken 839 times.
61834 if (node->op == PrefixUnaryExprNode::OP_NONE)
1269
3/4
✓ Branch 1 taken 60995 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 60987 times.
✓ Branch 5 taken 8 times.
60995 return visit(node->postfixUnaryExpr());
1270
1271 // Visit the right side
1272
1/2
✓ Branch 1 taken 839 times.
✗ Branch 2 not taken.
839 PrefixUnaryExprNode *rhsNode = node->prefixUnary();
1273
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));
1274 839 auto [operandType, operandEntry] = operand;
1275
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)
1276 // Determine action, based on the given operator
1277
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) {
1278 16 case PrefixUnaryExprNode::OP_MINUS:
1279
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 operandType = OpRuleManager::getPrefixMinusResultType(node, operand);
1280 16 break;
1281 28 case PrefixUnaryExprNode::OP_PLUS_PLUS:
1282
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 operandType = opRuleManager.getPrefixPlusPlusResultType(node, operand);
1283
1284
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 3 times.
28 if (operandEntry) {
1285 // In case the lhs is captured, notify the capture about the write access
1286
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)
1287 lhsCapture->setAccessType(READ_WRITE);
1288
1289 // Update the state of the variable
1290
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 operandEntry->updateState(INITIALIZED, node, false);
1291 }
1292
1293 28 break;
1294 7 case PrefixUnaryExprNode::OP_MINUS_MINUS:
1295
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 times.
7 operandType = opRuleManager.getPrefixMinusMinusResultType(node, operand);
1296
1297
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (operandEntry) {
1298 // In case the lhs is captured, notify the capture about the write access
1299
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)
1300 lhsCapture->setAccessType(READ_WRITE);
1301
1302 // Update the state of the variable
1303
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 operandEntry->updateState(INITIALIZED, node, false);
1304 }
1305
1306 6 break;
1307 561 case PrefixUnaryExprNode::OP_NOT:
1308
1/2
✓ Branch 1 taken 561 times.
✗ Branch 2 not taken.
561 operandType = OpRuleManager::getPrefixNotResultType(node, operand);
1309 561 break;
1310 1 case PrefixUnaryExprNode::OP_BITWISE_NOT:
1311
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 operandType = OpRuleManager::getPrefixBitwiseNotResultType(node, operand);
1312 1 break;
1313 162 case PrefixUnaryExprNode::OP_DEREFERENCE:
1314
1/2
✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
162 operandType = OpRuleManager::getPrefixMulResultType(node, operand);
1315 162 break;
1316 63 case PrefixUnaryExprNode::OP_ADDRESS_OF:
1317
1/2
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
63 operandType = OpRuleManager::getPrefixBitwiseAndResultType(node, operand);
1318 63 break;
1319 default:
1320 throw CompilerError(UNHANDLED_BRANCH, "PrefixUnaryExpr fall-through"); // GCOV_EXCL_LINE
1321 }
1322
1323
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};
1324 }
1325
1326 77053 std::any TypeChecker::visitPostfixUnaryExpr(PostfixUnaryExprNode *node) {
1327 // If no operator is applied, simply visit the atomic expression
1328
2/2
✓ Branch 0 taken 60995 times.
✓ Branch 1 taken 16058 times.
77053 if (node->op == PostfixUnaryExprNode::OP_NONE)
1329
3/4
✓ Branch 1 taken 60995 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 60988 times.
✓ Branch 5 taken 7 times.
60995 return visit(node->atomicExpr());
1330
1331 // Visit left side
1332
1/2
✓ Branch 1 taken 16058 times.
✗ Branch 2 not taken.
16058 PostfixUnaryExprNode *lhsNode = node->postfixUnaryExpr();
1333
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));
1334 16058 auto [lhsType, lhsEntry] = lhs;
1335
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)
1336
1337
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) {
1338 2328 case PostfixUnaryExprNode::OP_SUBSCRIPT: {
1339
1/2
✓ Branch 1 taken 2328 times.
✗ Branch 2 not taken.
2328 lhsType = lhsType.removeReferenceWrapper();
1340
1341 // Check if we can apply the subscript operator on the lhs type
1342
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}))
1343 SOFT_ERROR_ER(node, OPERATOR_WRONG_DATA_TYPE,
1344 "Can only apply subscript operator on array type, got " + lhsType.getName(true))
1345
1346 // Visit index assignment
1347
1/2
✓ Branch 1 taken 2328 times.
✗ Branch 2 not taken.
2328 AssignExprNode *indexAssignExpr = node->assignExpr();
1348
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;
1349
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)
1350 // Check if the index is of the right type
1351
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}))
1352
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")
1353
1354 // Check if we have an unsafe operation
1355
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())
1356 SOFT_ERROR_ER(
1357 node, UNSAFE_OPERATION_IN_SAFE_CONTEXT,
1358 "The subscript operator on pointers is an unsafe operation. Use unsafe blocks if you know what you are doing.")
1359
1360 // Check if we have a hardcoded array index
1361
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()) {
1362
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 const int32_t constIndex = indexAssignExpr->getCompileTimeValue().intValue;
1363
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 const unsigned int constSize = lhsType.getArraySize();
1364 // Check if we are accessing out-of-bounds memory
1365
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 33 times.
34 if (constIndex >= static_cast<int32_t>(constSize)) {
1366 1 const std::string idxStr = std::to_string(constIndex);
1367 1 const std::string sizeStr = std::to_string(constSize);
1368
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,
1369 "You are trying to access element with index " + idxStr + " of an array with size " + sizeStr)
1370 1 }
1371 }
1372
1373 // Get item type
1374
1/2
✓ Branch 1 taken 2326 times.
✗ Branch 2 not taken.
2326 lhsType = lhsType.getContained();
1375
1376 // Remove heap specifier
1377 2326 lhsType.getSpecifiers().isHeap = false;
1378
1379 2326 break;
1380 }
1381 12101 case PostfixUnaryExprNode::OP_MEMBER_ACCESS: {
1382 12101 const std::string &fieldName = node->identifier;
1383
1384 // Check if lhs is enum or strobj
1385 12101 QualType lhsBaseTy = lhsType;
1386
1/2
✓ Branch 1 taken 12101 times.
✗ Branch 2 not taken.
12101 autoDeReference(lhsBaseTy);
1387
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))
1388
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))
1389
1390 // Retrieve registry entry
1391
1/2
✓ Branch 1 taken 12100 times.
✗ Branch 2 not taken.
12100 const std::string &structName = lhsBaseTy.getSubType();
1392
1/2
✓ Branch 1 taken 12100 times.
✗ Branch 2 not taken.
12100 Scope *structScope = lhsBaseTy.getBodyScope();
1393
1394 // If we only have the generic struct scope, lookup the concrete manifestation scope
1395
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 12025 times.
12100 if (structScope->isGenericScope) {
1396 75 Scope *matchScope = structScope->parent;
1397
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);
1398
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 assert(spiceStruct != nullptr);
1399 75 structScope = spiceStruct->scope;
1400 }
1401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12100 times.
12100 assert(!structScope->isGenericScope); // At this point we always expect a substantiation scope
1402
1403 // Get accessed field
1404 12100 std::vector<size_t> indexPath;
1405
1/2
✓ Branch 1 taken 12100 times.
✗ Branch 2 not taken.
12100 SymbolTableEntry *memberEntry = structScope->symbolTable.lookupInComposedFields(fieldName, indexPath);
1406
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12098 times.
12100 if (!memberEntry)
1407
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)
1408
1/2
✓ Branch 1 taken 12098 times.
✗ Branch 2 not taken.
12098 const QualType memberType = memberEntry->getQualType();
1409
1410 // Check for insufficient visibility
1411
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())
1412 SOFT_ERROR_ER(node, INSUFFICIENT_VISIBILITY, "Cannot access field '" + fieldName + "' due to its private visibility")
1413
1414 // Set field to used
1415 12098 memberEntry->used = true;
1416
1417 // Overwrite type and entry of left side with member type and entry
1418 12098 lhsType = memberType;
1419 12098 lhsEntry = memberEntry;
1420 12098 break;
1421
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 12098 times.
12100 }
1422 1353 case PostfixUnaryExprNode::OP_PLUS_PLUS: {
1423
2/2
✓ Branch 0 taken 1348 times.
✓ Branch 1 taken 5 times.
1353 if (lhsEntry) {
1424 // In case the lhs is captured, notify the capture about the write access
1425
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)
1426
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 lhsCapture->setAccessType(READ_WRITE);
1427
1428 // Update the state of the variable
1429
1/2
✓ Branch 1 taken 1348 times.
✗ Branch 2 not taken.
1348 lhsEntry->updateState(INITIALIZED, node, false);
1430 }
1431
1432
2/2
✓ Branch 1 taken 1352 times.
✓ Branch 2 taken 1 times.
1353 auto [type, entry] = opRuleManager.getPostfixPlusPlusResultType(node, lhs, 0);
1433 1352 lhsType = type;
1434 1352 lhsEntry = entry;
1435 1352 break;
1436 }
1437 270 case PostfixUnaryExprNode::OP_MINUS_MINUS: {
1438
2/2
✓ Branch 0 taken 266 times.
✓ Branch 1 taken 4 times.
270 if (lhsEntry) {
1439 // In case the lhs is captured, notify the capture about the write access
1440
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)
1441 lhsCapture->setAccessType(READ_WRITE);
1442
1443 // Update the state of the variable
1444
1/2
✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
266 lhsEntry->updateState(INITIALIZED, node, false);
1445 }
1446
1447
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
270 ExprResult result = opRuleManager.getPostfixMinusMinusResultType(node, lhs, 0);
1448 270 lhsType = result.type;
1449 270 lhsEntry = result.entry;
1450 270 break;
1451 }
1452 default:
1453 throw CompilerError(UNHANDLED_BRANCH, "PostfixUnaryExpr fall-through"); // GCOV_EXCL_LINE
1454 }
1455
1456
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)) {
1457 const std::string varName = lhsEntry ? lhsEntry->name : "";
1458 SOFT_ERROR_ER(node, REFERENCED_UNDEFINED_VARIABLE, "Variable '" + varName + "' was referenced before declared")
1459 }
1460
1461
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};
1462 }
1463
1464 60995 std::any TypeChecker::visitAtomicExpr(AtomicExprNode *node) {
1465 // Check if constant
1466
3/4
✓ Branch 1 taken 60995 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11919 times.
✓ Branch 4 taken 49076 times.
60995 if (node->constant())
1467
2/4
✓ Branch 1 taken 11919 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11919 times.
✗ Branch 5 not taken.
11919 return visit(node->constant());
1468
1469 // Check if value
1470
3/4
✓ Branch 1 taken 49076 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11362 times.
✓ Branch 4 taken 37714 times.
49076 if (node->value())
1471
3/4
✓ Branch 1 taken 11362 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11358 times.
✓ Branch 5 taken 4 times.
11362 return visit(node->value());
1472
1473 // Check for builtin calls
1474
3/4
✓ Branch 1 taken 37714 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 651 times.
✓ Branch 4 taken 37063 times.
37714 if (node->printfCall())
1475
2/4
✓ Branch 1 taken 651 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 651 times.
✗ Branch 5 not taken.
651 return visit(node->printfCall());
1476
3/4
✓ Branch 1 taken 37063 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 119 times.
✓ Branch 4 taken 36944 times.
37063 if (node->sizeofCall())
1477
2/4
✓ Branch 1 taken 119 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 119 times.
✗ Branch 5 not taken.
119 return visit(node->sizeofCall());
1478
3/4
✓ Branch 1 taken 36944 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 36933 times.
36944 if (node->alignofCall())
1479
2/4
✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
11 return visit(node->alignofCall());
1480
3/4
✓ Branch 1 taken 36933 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 36 times.
✓ Branch 4 taken 36897 times.
36933 if (node->lenCall())
1481
2/4
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 36 times.
✗ Branch 5 not taken.
36 return visit(node->lenCall());
1482
3/4
✓ Branch 1 taken 36897 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 366 times.
✓ Branch 4 taken 36531 times.
36897 if (node->panicCall())
1483
2/4
✓ Branch 1 taken 366 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 366 times.
✗ Branch 5 not taken.
366 return visit(node->panicCall());
1484
3/4
✓ Branch 1 taken 36531 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 36530 times.
36531 if (node->sysCall())
1485
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 return visit(node->sysCall());
1486
1487 // Check for assign expression within parentheses
1488
3/4
✓ Branch 1 taken 36530 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 523 times.
✓ Branch 4 taken 36007 times.
36530 if (node->assignExpr())
1489
3/4
✓ Branch 1 taken 523 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 520 times.
✓ Branch 5 taken 3 times.
523 return visit(node->assignExpr());
1490
1491 // Identifier (local or global variable access)
1492
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 36007 times.
36007 assert(!node->fqIdentifier.empty());
1493
1/2
✓ Branch 0 taken 36007 times.
✗ Branch 1 not taken.
36007 if (!accessScope)
1494 36007 accessScope = currentScope;
1495
1496 // Check if a local or global variable can be found by searching for the name
1497 36007 SymbolTableEntry *varEntry = nullptr;
1498
2/2
✓ Branch 1 taken 35758 times.
✓ Branch 2 taken 249 times.
36007 if (node->identifierFragments.size() == 1)
1499 71516 varEntry = accessScope->lookup(node->identifierFragments.back());
1500
1501 // If no local or global was found, search in the name registry
1502
2/2
✓ Branch 0 taken 308 times.
✓ Branch 1 taken 35699 times.
36007 if (!varEntry) {
1503
1/2
✓ Branch 1 taken 308 times.
✗ Branch 2 not taken.
308 const NameRegistryEntry *registryEntry = sourceFile->getNameRegistryEntry(node->fqIdentifier);
1504
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 307 times.
308 if (!registryEntry)
1505
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")
1506 307 varEntry = registryEntry->targetEntry;
1507 307 accessScope = registryEntry->targetScope;
1508 }
1509
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36006 times.
36006 assert(varEntry != nullptr);
1510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36006 times.
36006 assert(accessScope != nullptr);
1511
1/2
✓ Branch 1 taken 36006 times.
✗ Branch 2 not taken.
36006 AtomicExprNode::VarAccessData &data = node->data.at(manIdx);
1512
1/2
✓ Branch 1 taken 36006 times.
✗ Branch 2 not taken.
36006 data = {varEntry, accessScope, accessScope->symbolTable.lookupCapture(varEntry->name)};
1513
1/2
✓ Branch 1 taken 36006 times.
✗ Branch 2 not taken.
36006 const QualType varType = varEntry->getQualType();
1514
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)
1515
1516
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) {
1517 // Check if overloaded function was referenced
1518
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 const std::vector<Function *> *manifestations = varEntry->declNode->getFctManifestations(varEntry->name);
1519
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 8 times.
9 if (manifestations->size() > 1)
1520
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")
1521
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7 times.
8 if (!manifestations->front()->templateTypes.empty())
1522
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")
1523 // Set referenced function to used
1524 7 Function *referencedFunction = manifestations->front();
1525 7 referencedFunction->used = true;
1526 7 referencedFunction->entry->used = true;
1527 }
1528
1529
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))
1530
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.")
1531
1532 // The base type should be a primitive, struct, interface, function or procedure
1533
1/2
✓ Branch 1 taken 35994 times.
✗ Branch 2 not taken.
35994 const QualType baseType = varType.getBase();
1534
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}))
1535 SOFT_ERROR_ER(node, INVALID_SYMBOL_ACCESS, "A symbol of type " + varType.getName(false) + " cannot be accessed here")
1536
1537 // Check if is an imported variable
1538
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)) {
1539 // Check if the entry is public
1540
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())
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, INSUFFICIENT_VISIBILITY, "Cannot access '" + varEntry->name + "' due to its private visibility")
1542 }
1543
1544 // Check if we have seen a 'this.' prefix, because the generator needs that
1545
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)
1546
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,
1547 "The symbol '" + node->fqIdentifier + "' could not be found. Missing 'this.' prefix?")
1548
1549 // Set symbol table entry to used
1550 35992