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