Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2021-2025 ChilliBits. All rights reserved. | ||
2 | |||
3 | #include <ast/ASTNodes.h> | ||
4 | |||
5 | #include "SourceFile.h" | ||
6 | #include <ast/Attributes.h> | ||
7 | #include <exception/SemanticError.h> | ||
8 | #include <symboltablebuilder/SymbolTableBuilder.h> | ||
9 | |||
10 | namespace spice::compiler { | ||
11 | |||
12 | // Constant definitions | ||
13 | static constexpr size_t ERROR_MESSAGE_CONTEXT = 20; | ||
14 | |||
15 | 845 | std::string ASTNode::getErrorMessage() const { | |
16 | 845 | antlr4::CharStream *inputStream = codeLoc.sourceFile->antlrCtx.inputStream.get(); | |
17 | 845 | const antlr4::misc::Interval &sourceInterval = codeLoc.sourceInterval; | |
18 | 845 | antlr4::misc::Interval extSourceInterval(sourceInterval); | |
19 | |||
20 | // If we have a multi-line interval, only use the first line | ||
21 |
3/4✓ Branch 3 → 4 taken 845 times.
✗ Branch 3 → 77 not taken.
✓ Branch 6 → 7 taken 19 times.
✓ Branch 6 → 8 taken 826 times.
|
845 | if (const size_t offset = inputStream->getText(extSourceInterval).find('\n'); offset != std::string::npos) |
22 | 19 | extSourceInterval.b = extSourceInterval.a + static_cast<ssize_t>(offset); | |
23 | |||
24 | 845 | size_t markerIndentation = 0; | |
25 |
2/2✓ Branch 20 → 9 taken 9152 times.
✓ Branch 20 → 21 taken 212 times.
|
9364 | for (; markerIndentation < ERROR_MESSAGE_CONTEXT; markerIndentation++) { |
26 | 9152 | extSourceInterval.a--; | |
27 |
9/12✓ Branch 9 → 10 taken 9138 times.
✓ Branch 9 → 13 taken 14 times.
✓ Branch 10 → 11 taken 9138 times.
✗ Branch 10 → 78 not taken.
✓ Branch 12 → 13 taken 619 times.
✓ Branch 12 → 14 taken 8519 times.
✓ Branch 15 → 16 taken 9138 times.
✓ Branch 15 → 17 taken 14 times.
✓ Branch 17 → 18 taken 633 times.
✓ Branch 17 → 19 taken 8519 times.
✗ Branch 78 → 79 not taken.
✗ Branch 78 → 80 not taken.
|
9152 | if (extSourceInterval.a < 0 || inputStream->getText(extSourceInterval).find('\n') != std::string::npos) { |
28 | 633 | extSourceInterval.a++; | |
29 | 633 | break; | |
30 | } | ||
31 | } | ||
32 |
2/2✓ Branch 34 → 22 taken 2411 times.
✓ Branch 34 → 35 taken 8 times.
|
2419 | for (size_t suffixContext = 0; suffixContext < ERROR_MESSAGE_CONTEXT; suffixContext++) { |
33 | 2411 | extSourceInterval.b++; | |
34 |
4/6✓ Branch 22 → 23 taken 2411 times.
✗ Branch 22 → 82 not taken.
✓ Branch 23 → 24 taken 2411 times.
✗ Branch 23 → 27 not taken.
✓ Branch 26 → 27 taken 837 times.
✓ Branch 26 → 28 taken 1574 times.
|
4822 | if (static_cast<size_t>(extSourceInterval.b) > inputStream->size() || |
35 |
4/8✓ Branch 24 → 25 taken 2411 times.
✗ Branch 24 → 82 not taken.
✓ Branch 29 → 30 taken 2411 times.
✗ Branch 29 → 31 not taken.
✓ Branch 31 → 32 taken 837 times.
✓ Branch 31 → 33 taken 1574 times.
✗ Branch 82 → 83 not taken.
✗ Branch 82 → 84 not taken.
|
4822 | inputStream->getText(extSourceInterval).find('\n') != std::string::npos) { |
36 | 837 | extSourceInterval.b--; | |
37 | 837 | break; | |
38 | } | ||
39 | } | ||
40 | |||
41 | // Trim start | ||
42 |
3/4✓ Branch 37 → 38 taken 4825 times.
✗ Branch 37 → 86 not taken.
✓ Branch 40 → 36 taken 3980 times.
✓ Branch 40 → 41 taken 845 times.
|
4825 | while (inputStream->getText(extSourceInterval)[0] == ' ') { |
43 | 3980 | extSourceInterval.a++; | |
44 | 3980 | markerIndentation--; | |
45 | } | ||
46 | |||
47 | // Trim end | ||
48 |
3/4✓ Branch 41 → 42 taken 845 times.
✗ Branch 41 → 87 not taken.
✓ Branch 45 → 46 taken 19 times.
✓ Branch 45 → 47 taken 826 times.
|
845 | if (inputStream->getText(extSourceInterval)[extSourceInterval.length() - 1] == '\n') |
49 | 19 | extSourceInterval.b--; | |
50 | |||
51 | 845 | const std::string lineNumberStr = std::to_string(codeLoc.line); | |
52 | 845 | markerIndentation += lineNumberStr.length() + 2; | |
53 | |||
54 | // Build error message | ||
55 |
1/2✓ Branch 49 → 50 taken 845 times.
✗ Branch 49 → 107 not taken.
|
845 | std::stringstream ss; |
56 |
5/10✓ Branch 50 → 51 taken 845 times.
✗ Branch 50 → 105 not taken.
✓ Branch 51 → 52 taken 845 times.
✗ Branch 51 → 105 not taken.
✓ Branch 52 → 53 taken 845 times.
✗ Branch 52 → 90 not taken.
✓ Branch 53 → 54 taken 845 times.
✗ Branch 53 → 88 not taken.
✓ Branch 54 → 55 taken 845 times.
✗ Branch 54 → 88 not taken.
|
845 | ss << lineNumberStr << " " << inputStream->getText(extSourceInterval) << "\n"; |
57 |
2/4✓ Branch 58 → 59 taken 845 times.
✗ Branch 58 → 93 not taken.
✓ Branch 59 → 60 taken 845 times.
✗ Branch 59 → 91 not taken.
|
1690 | ss << std::string(markerIndentation, ' '); |
58 |
2/4✓ Branch 67 → 68 taken 845 times.
✗ Branch 67 → 99 not taken.
✓ Branch 68 → 69 taken 845 times.
✗ Branch 68 → 97 not taken.
|
845 | ss << std::string(std::min(sourceInterval.length(), extSourceInterval.length()), '^'); |
59 |
1/2✓ Branch 71 → 72 taken 845 times.
✗ Branch 71 → 105 not taken.
|
1690 | return ss.str(); |
60 | 845 | } | |
61 | |||
62 | 30938 | const StmtLstNode *ASTNode::getNextOuterStmtLst() const { // NOLINT(*-no-recursion) | |
63 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 30938 times.
|
30938 | assert(parent != nullptr && "Could not find next outer statement list"); |
64 |
2/2✓ Branch 5 → 6 taken 18664 times.
✓ Branch 5 → 14 taken 12274 times.
|
49602 | return isStmtLst() ? spice_pointer_cast<const StmtLstNode *>(this) : parent->getNextOuterStmtLst(); |
65 | } | ||
66 | |||
67 | 368 | bool MainFctDefNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
68 | 368 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
69 | } | ||
70 | |||
71 | 11250 | bool FctDefBaseNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
72 | 11250 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
73 | } | ||
74 | |||
75 | 46 | CompileTimeValue GlobalVarDefNode::getCompileTimeValue() const { return constant->getCompileTimeValue(); } | |
76 | |||
77 | 1108 | bool ForLoopNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
78 | // If we have the guarantee that the loop condition is always true and the loop body returns on all control paths, | ||
79 | // we can assume that the loop itself will always return | ||
80 |
3/4✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 7 taken 1107 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 1 time.
|
1108 | const bool loopConditionAlwaysTrue = condAssign->hasCompileTimeValue() && condAssign->getCompileTimeValue().boolValue; |
81 |
1/4✗ Branch 8 → 9 not taken.
✓ Branch 8 → 12 taken 1108 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
1108 | return loopConditionAlwaysTrue && body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
82 | } | ||
83 | |||
84 | 725 | bool WhileLoopNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
85 | // If we have the guarantee that the loop condition is always true and the loop body returns on all control paths, | ||
86 | // we can assume that the loop itself will always return | ||
87 |
3/4✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 7 taken 721 times.
✓ Branch 5 → 6 taken 4 times.
✗ Branch 5 → 7 not taken.
|
725 | const bool loopConditionAlwaysTrue = condition->hasCompileTimeValue() && condition->getCompileTimeValue().boolValue; |
88 |
3/4✓ Branch 8 → 9 taken 4 times.
✓ Branch 8 → 12 taken 721 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 4 times.
|
725 | return loopConditionAlwaysTrue && body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
89 | } | ||
90 | |||
91 | 9 | bool DoWhileLoopNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
92 | // Do-while loops will always be executed at least once. So if the body returns on all control paths, the loop will as well | ||
93 | 9 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
94 | } | ||
95 | |||
96 | 3313 | bool IfStmtNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { // NOLINT(misc-no-recursion) | |
97 | // If the condition always evaluates to 'true' the then block must return | ||
98 |
6/6✓ Branch 3 → 4 taken 13 times.
✓ Branch 3 → 7 taken 3300 times.
✓ Branch 5 → 6 taken 4 times.
✓ Branch 5 → 7 taken 9 times.
✓ Branch 8 → 9 taken 4 times.
✓ Branch 8 → 11 taken 3309 times.
|
3313 | if (condition->hasCompileTimeValue() && condition->getCompileTimeValue().boolValue) |
99 | 4 | return thenBody->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
100 | |||
101 | // If the condition always evaluates to 'false' the else block must return | ||
102 |
5/6✓ Branch 12 → 13 taken 9 times.
✓ Branch 12 → 16 taken 3300 times.
✓ Branch 14 → 15 taken 9 times.
✗ Branch 14 → 16 not taken.
✓ Branch 17 → 18 taken 9 times.
✓ Branch 17 → 24 taken 3300 times.
|
3309 | if (condition->hasCompileTimeValue() && !condition->getCompileTimeValue().boolValue) |
103 |
3/4✓ Branch 18 → 19 taken 4 times.
✓ Branch 18 → 22 taken 5 times.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 4 times.
|
9 | return elseStmt != nullptr && elseStmt->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
104 | |||
105 | // If the condition does not always evaluate to 'true' or 'false' we need to check both branches | ||
106 |
4/4✓ Branch 25 → 26 taken 2472 times.
✓ Branch 25 → 30 taken 828 times.
✓ Branch 26 → 27 taken 30 times.
✓ Branch 26 → 30 taken 2442 times.
|
3330 | return thenBody->returnsOnAllControlPaths(doSetPredecessorsUnreachable) && elseStmt != nullptr && |
107 |
1/2✓ Branch 28 → 29 taken 30 times.
✗ Branch 28 → 30 not taken.
|
3330 | elseStmt->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
108 | } | ||
109 | |||
110 | 34 | bool ElseStmtNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { // NOLINT(misc-no-recursion) | |
111 |
2/2✓ Branch 2 → 3 taken 11 times.
✓ Branch 2 → 5 taken 23 times.
|
34 | if (isElseIf) |
112 | 11 | return ifStmt->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
113 | 23 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
114 | } | ||
115 | |||
116 | 12 | bool SwitchStmtNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
117 | 42 | const auto pred = [=](const CaseBranchNode *node) { return node->returnsOnAllControlPaths(doSetPredecessorsUnreachable); }; | |
118 |
1/2✓ Branch 2 → 3 taken 12 times.
✗ Branch 2 → 15 not taken.
|
12 | const bool allCaseBranchesReturn = std::ranges::all_of(caseBranches, pred); |
119 |
4/6✓ Branch 3 → 4 taken 6 times.
✓ Branch 3 → 6 taken 6 times.
✓ Branch 4 → 5 taken 6 times.
✗ Branch 4 → 15 not taken.
✓ Branch 5 → 6 taken 6 times.
✗ Branch 5 → 7 not taken.
|
12 | const bool defaultBranchReturns = !defaultBranch || defaultBranch->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
120 |
3/4✓ Branch 8 → 9 taken 9 times.
✓ Branch 8 → 11 taken 3 times.
✓ Branch 9 → 10 taken 9 times.
✗ Branch 9 → 11 not taken.
|
24 | return allCaseBranchesReturn && defaultBranchReturns; |
121 | } | ||
122 | |||
123 | 42 | bool CaseBranchNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
124 | 42 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
125 | } | ||
126 | |||
127 | 6 | bool DefaultBranchNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
128 | 6 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
129 | } | ||
130 | |||
131 | 17215 | bool StmtLstNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
132 | // An empty statement list does not return at all | ||
133 |
2/2✓ Branch 3 → 4 taken 32 times.
✓ Branch 3 → 5 taken 17183 times.
|
17215 | if (statements.empty()) |
134 | 32 | return false; | |
135 | // A statement list returns on all control paths, if the one direct child statement returns on all control paths | ||
136 | 17183 | bool returnsOnAllControlPaths = false; | |
137 |
2/2✓ Branch 18 → 7 taken 32849 times.
✓ Branch 18 → 19 taken 17183 times.
|
50032 | for (StmtNode *child : statements) { |
138 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 32849 times.
|
32849 | assert(child != nullptr); |
139 | |||
140 | // Prevent marking instructions as unreachable if doSetPredecessorsUnreachable is set to false | ||
141 |
4/4✓ Branch 10 → 11 taken 882 times.
✓ Branch 10 → 13 taken 31967 times.
✓ Branch 11 → 12 taken 7 times.
✓ Branch 11 → 13 taken 875 times.
|
32849 | if (returnsOnAllControlPaths && *doSetPredecessorsUnreachable) |
142 | 7 | child->unreachable = true; | |
143 | |||
144 |
3/4✓ Branch 13 → 14 taken 32849 times.
✗ Branch 13 → 21 not taken.
✓ Branch 14 → 15 taken 10653 times.
✓ Branch 14 → 16 taken 22196 times.
|
32849 | if (child->returnsOnAllControlPaths(doSetPredecessorsUnreachable)) |
145 | 10653 | returnsOnAllControlPaths = true; | |
146 | } | ||
147 | 17183 | return returnsOnAllControlPaths; | |
148 | } | ||
149 | |||
150 | 2419 | std::vector<const CompileTimeValue *> AttrLstNode::getAttrValuesByName(const std::string &key) const { | |
151 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2419 times.
|
2419 | assert(ATTR_CONFIGS.contains(key)); |
152 | |||
153 | 2419 | std::vector<const CompileTimeValue *> attributeValues; | |
154 |
2/2✓ Branch 19 → 7 taken 3765 times.
✓ Branch 19 → 20 taken 2419 times.
|
6184 | for (const AttrNode *attrNode : attributes) { |
155 | // Skip attributes with different keys | ||
156 |
2/2✓ Branch 9 → 10 taken 2821 times.
✓ Branch 9 → 11 taken 944 times.
|
3765 | if (attrNode->key != key) |
157 | 2821 | continue; | |
158 | |||
159 | // Found a matching attribute | ||
160 | 944 | const CompileTimeValue *value = attrNode->getValue(); | |
161 |
2/2✓ Branch 12 → 13 taken 57 times.
✓ Branch 12 → 15 taken 887 times.
|
944 | if (!value) { |
162 | // If the attribute has no value, we use the default value | ||
163 |
1/2✓ Branch 13 → 14 taken 57 times.
✗ Branch 13 → 22 not taken.
|
57 | attributeValues.push_back(&DEFAULT_BOOL_COMPILE_VALUE); |
164 | } else { | ||
165 | // If the attribute has a value, we use the value | ||
166 |
1/2✓ Branch 15 → 16 taken 887 times.
✗ Branch 15 → 23 not taken.
|
887 | attributeValues.push_back(value); |
167 | } | ||
168 | } | ||
169 | |||
170 | 2419 | return attributeValues; | |
171 | ✗ | } | |
172 | |||
173 | 1441 | const CompileTimeValue *AttrLstNode::getAttrValueByName(const std::string &key) const { | |
174 |
1/2✓ Branch 2 → 3 taken 1441 times.
✗ Branch 2 → 12 not taken.
|
1441 | const std::vector<const CompileTimeValue *> attrs = getAttrValuesByName(key); |
175 |
2/2✓ Branch 4 → 5 taken 928 times.
✓ Branch 4 → 6 taken 513 times.
|
2882 | return attrs.empty() ? nullptr : attrs.back(); |
176 | 1441 | } | |
177 | |||
178 | 1288 | bool AttrLstNode::hasAttr(const std::string &key) const { | |
179 | 3453 | return std::ranges::any_of(attributes, [&](const AttrNode *attr) { return attr->key == key; }); | |
180 | } | ||
181 | |||
182 |
2/2✓ Branch 2 → 3 taken 887 times.
✓ Branch 2 → 4 taken 57 times.
|
944 | const CompileTimeValue *AttrNode::getValue() const { return value ? &value->compileTimeValue : nullptr; } |
183 | |||
184 | 706 | bool AssertStmtNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
185 | // If the expression, passed to the assert statement is always evaluated to false, the assert statement will never succeed | ||
186 |
4/4✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 7 taken 702 times.
✓ Branch 5 → 6 taken 3 times.
✓ Branch 5 → 7 taken 1 time.
|
706 | return assignExpr->hasCompileTimeValue() && !assignExpr->getCompileTimeValue().boolValue; |
187 | } | ||
188 | |||
189 | 13325 | bool AssignExprNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
190 | // If it's a ternary, do the default thing | ||
191 |
2/2✓ Branch 2 → 3 taken 7604 times.
✓ Branch 2 → 5 taken 5721 times.
|
13325 | if (op == AssignOp::OP_NONE) |
192 | 7604 | return ternaryExpr->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
193 | |||
194 | // If it's a modification on the result variable, we technically return from the function, but at the end of the function. | ||
195 |
2/2✓ Branch 5 → 6 taken 5716 times.
✓ Branch 5 → 7 taken 5 times.
|
5721 | const AtomicExprNode *atomicExpr = lhs->postfixUnaryExpr ? lhs->postfixUnaryExpr->atomicExpr : nullptr; |
196 |
6/6✓ Branch 8 → 9 taken 1230 times.
✓ Branch 8 → 12 taken 4491 times.
✓ Branch 10 → 11 taken 616 times.
✓ Branch 10 → 12 taken 614 times.
✓ Branch 13 → 14 taken 616 times.
✓ Branch 13 → 15 taken 5105 times.
|
5721 | if (atomicExpr && atomicExpr->fqIdentifier == RETURN_VARIABLE_NAME) { |
197 | // If we assign the result variable, we technically return from the function, but at the end of the function. | ||
198 | // Therefore, the following code is not unreachable, but will be executed in any case. | ||
199 | 616 | *doSetPredecessorsUnreachable = false; | |
200 | 616 | return true; | |
201 | } | ||
202 | |||
203 | 5105 | return false; | |
204 | } | ||
205 | |||
206 | 10097 | bool TernaryExprNode::hasCompileTimeValue() const { | |
207 |
4/4✓ Branch 2 → 3 taken 7 times.
✓ Branch 2 → 5 taken 10090 times.
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 6 taken 3 times.
|
10097 | const bool trueExprHasCompileTimeValue = !trueExpr || trueExpr->hasCompileTimeValue(); |
208 |
4/4✓ Branch 7 → 8 taken 7 times.
✓ Branch 7 → 10 taken 10090 times.
✓ Branch 9 → 10 taken 5 times.
✓ Branch 9 → 11 taken 2 times.
|
10097 | const bool falseExprHasCompileTimeValue = !falseExpr || falseExpr->hasCompileTimeValue(); |
209 |
4/6✓ Branch 13 → 14 taken 219 times.
✓ Branch 13 → 17 taken 9878 times.
✓ Branch 14 → 15 taken 219 times.
✗ Branch 14 → 17 not taken.
✓ Branch 15 → 16 taken 219 times.
✗ Branch 15 → 17 not taken.
|
10097 | return condition->hasCompileTimeValue() && trueExprHasCompileTimeValue && falseExprHasCompileTimeValue; |
210 | } | ||
211 | |||
212 | 82 | CompileTimeValue TernaryExprNode::getCompileTimeValue() const { | |
213 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 82 times.
|
82 | assert(condition != nullptr); |
214 |
2/4✓ Branch 4 → 5 taken 82 times.
✗ Branch 4 → 7 not taken.
✓ Branch 5 → 6 taken 82 times.
✗ Branch 5 → 7 not taken.
|
82 | if (!trueExpr && !falseExpr) |
215 | 82 | return condition->getCompileTimeValue(); | |
216 | |||
217 | // If the condition has no compile time value, we do not need to evaluate the true and false values | ||
218 | ✗ | if (!condition->hasCompileTimeValue()) | |
219 | ✗ | return {}; | |
220 | |||
221 | // Check if the condition always evaluates to 'true' | ||
222 | ✗ | if (condition->getCompileTimeValue().boolValue) { | |
223 | ✗ | const LogicalOrExprNode *trueValue = isShortened ? condition : trueExpr; | |
224 | ✗ | assert(trueValue != nullptr); | |
225 | ✗ | return trueValue->getCompileTimeValue(); | |
226 | } | ||
227 | |||
228 | ✗ | assert(falseExpr != nullptr); | |
229 | ✗ | return falseExpr->getCompileTimeValue(); | |
230 | } | ||
231 | |||
232 | 10694 | bool LogicalOrExprNode::hasCompileTimeValue() const { | |
233 | 21390 | return std::ranges::all_of(operands, [](const LogicalAndExprNode *node) { return node->hasCompileTimeValue(); }); | |
234 | } | ||
235 | |||
236 | 82 | CompileTimeValue LogicalOrExprNode::getCompileTimeValue() const { | |
237 |
2/2✓ Branch 3 → 4 taken 80 times.
✓ Branch 3 → 6 taken 2 times.
|
82 | if (operands.size() == 1) |
238 | 80 | return operands.front()->getCompileTimeValue(); | |
239 | |||
240 | // Check if one expression evaluates to 'true' | ||
241 |
2/2✓ Branch 17 → 8 taken 4 times.
✓ Branch 17 → 18 taken 2 times.
|
6 | for (const LogicalAndExprNode *op : operands) { |
242 |
2/4✓ Branch 9 → 10 taken 4 times.
✗ Branch 9 → 21 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 4 times.
|
4 | assert(op->hasCompileTimeValue()); |
243 | // If one operand evaluates to 'true' the whole expression is 'true' | ||
244 |
2/4✓ Branch 12 → 13 taken 4 times.
✗ Branch 12 → 20 not taken.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 4 times.
|
4 | if (const CompileTimeValue opCompileTimeValue = op->getCompileTimeValue(); opCompileTimeValue.boolValue) |
245 | ✗ | return CompileTimeValue{.boolValue = true}; | |
246 | } | ||
247 | |||
248 | // Return 'false' | ||
249 | 2 | return CompileTimeValue{.boolValue = false}; | |
250 | } | ||
251 | |||
252 | 10700 | bool LogicalAndExprNode::hasCompileTimeValue() const { | |
253 | 21402 | return std::ranges::all_of(operands, [](const BitwiseOrExprNode *node) { return node->hasCompileTimeValue(); }); | |
254 | } | ||
255 | |||
256 | 84 | CompileTimeValue LogicalAndExprNode::getCompileTimeValue() const { | |
257 |
2/2✓ Branch 3 → 4 taken 82 times.
✓ Branch 3 → 6 taken 2 times.
|
84 | if (operands.size() == 1) |
258 | 82 | return operands.front()->getCompileTimeValue(); | |
259 | |||
260 | // Check if all expressions evaluate to 'true' | ||
261 |
1/2✓ Branch 17 → 8 taken 4 times.
✗ Branch 17 → 18 not taken.
|
4 | for (const BitwiseOrExprNode *op : operands) { |
262 |
2/4✓ Branch 9 → 10 taken 4 times.
✗ Branch 9 → 21 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 4 times.
|
4 | assert(op->hasCompileTimeValue()); |
263 | // If one operand evaluates to 'false' the whole expression is 'false' | ||
264 |
3/4✓ Branch 12 → 13 taken 4 times.
✗ Branch 12 → 20 not taken.
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 15 taken 2 times.
|
4 | if (const CompileTimeValue opCompileTimeValue = op->getCompileTimeValue(); !opCompileTimeValue.boolValue) |
265 | 2 | return CompileTimeValue{.boolValue = false}; | |
266 | } | ||
267 | |||
268 | // Return 'false' | ||
269 | ✗ | return CompileTimeValue{.boolValue = false}; | |
270 | } | ||
271 | |||
272 | 10706 | bool BitwiseOrExprNode::hasCompileTimeValue() const { | |
273 | 21412 | return std::ranges::all_of(operands, [](const BitwiseXorExprNode *node) { return node->hasCompileTimeValue(); }); | |
274 | } | ||
275 | |||
276 | 86 | CompileTimeValue BitwiseOrExprNode::getCompileTimeValue() const { | |
277 |
1/2✓ Branch 3 → 4 taken 86 times.
✗ Branch 3 → 7 not taken.
|
86 | if (operands.size() == 1) |
278 |
1/2✓ Branch 5 → 6 taken 86 times.
✗ Branch 5 → 23 not taken.
|
86 | return operands.front()->getCompileTimeValue(); |
279 | |||
280 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
281 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
282 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
283 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
284 | ✗ | result.longValue |= opCompileTimeValue.longValue; | |
285 | } | ||
286 | |||
287 | ✗ | return result; | |
288 | } | ||
289 | |||
290 | 10706 | bool BitwiseXorExprNode::hasCompileTimeValue() const { | |
291 | 21412 | return std::ranges::all_of(operands, [](const BitwiseAndExprNode *node) { return node->hasCompileTimeValue(); }); | |
292 | } | ||
293 | |||
294 | 86 | CompileTimeValue BitwiseXorExprNode::getCompileTimeValue() const { | |
295 |
1/2✓ Branch 3 → 4 taken 86 times.
✗ Branch 3 → 7 not taken.
|
86 | if (operands.size() == 1) |
296 |
1/2✓ Branch 5 → 6 taken 86 times.
✗ Branch 5 → 23 not taken.
|
86 | return operands.front()->getCompileTimeValue(); |
297 | |||
298 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
299 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
300 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
301 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
302 | ✗ | result.longValue ^= opCompileTimeValue.longValue; | |
303 | } | ||
304 | |||
305 | ✗ | return result; | |
306 | } | ||
307 | |||
308 | 10706 | bool BitwiseAndExprNode::hasCompileTimeValue() const { | |
309 | 21412 | return std::ranges::all_of(operands, [](const EqualityExprNode *node) { return node->hasCompileTimeValue(); }); | |
310 | } | ||
311 | |||
312 | 86 | CompileTimeValue BitwiseAndExprNode::getCompileTimeValue() const { | |
313 |
1/2✓ Branch 3 → 4 taken 86 times.
✗ Branch 3 → 7 not taken.
|
86 | if (operands.size() == 1) |
314 |
1/2✓ Branch 5 → 6 taken 86 times.
✗ Branch 5 → 23 not taken.
|
86 | return operands.front()->getCompileTimeValue(); |
315 | |||
316 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
317 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
318 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
319 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
320 | ✗ | result.longValue &= opCompileTimeValue.longValue; | |
321 | } | ||
322 | |||
323 | ✗ | return result; | |
324 | } | ||
325 | |||
326 | 10706 | bool EqualityExprNode::hasCompileTimeValue() const { | |
327 | 21422 | return std::ranges::all_of(operands, [](const RelationalExprNode *node) { return node->hasCompileTimeValue(); }); | |
328 | } | ||
329 | |||
330 | 86 | CompileTimeValue EqualityExprNode::getCompileTimeValue() const { | |
331 |
2/2✓ Branch 3 → 4 taken 76 times.
✓ Branch 3 → 7 taken 10 times.
|
86 | if (operands.size() == 1) |
332 |
1/2✓ Branch 5 → 6 taken 76 times.
✗ Branch 5 → 34 not taken.
|
76 | return operands.front()->getCompileTimeValue(); |
333 | |||
334 |
2/4✓ Branch 7 → 8 taken 10 times.
✗ Branch 7 → 34 not taken.
✓ Branch 8 → 9 taken 10 times.
✗ Branch 8 → 34 not taken.
|
10 | const CompileTimeValue op0Value = operands.at(0)->getCompileTimeValue(); |
335 |
2/4✓ Branch 9 → 10 taken 10 times.
✗ Branch 9 → 34 not taken.
✓ Branch 10 → 11 taken 10 times.
✗ Branch 10 → 34 not taken.
|
10 | const CompileTimeValue op1Value = operands.at(1)->getCompileTimeValue(); |
336 |
2/2✓ Branch 11 → 12 taken 6 times.
✓ Branch 11 → 13 taken 4 times.
|
10 | if (op == EqualityOp::OP_EQUAL) |
337 | 6 | return CompileTimeValue{.boolValue = op0Value.longValue == op1Value.longValue}; | |
338 |
1/2✓ Branch 13 → 14 taken 4 times.
✗ Branch 13 → 15 not taken.
|
4 | if (op == EqualityOp::OP_NOT_EQUAL) |
339 | 4 | return CompileTimeValue{.boolValue = op0Value.longValue != op1Value.longValue}; | |
340 | |||
341 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "EqualityExprNode::getCompileTimeValue()"); | |
342 | } | ||
343 | |||
344 | 10716 | bool RelationalExprNode::hasCompileTimeValue() const { | |
345 | 21433 | return std::ranges::all_of(operands, [](const ShiftExprNode *node) { return node->hasCompileTimeValue(); }); | |
346 | } | ||
347 | |||
348 | 96 | CompileTimeValue RelationalExprNode::getCompileTimeValue() const { | |
349 |
2/2✓ Branch 3 → 4 taken 95 times.
✓ Branch 3 → 7 taken 1 time.
|
96 | if (operands.size() == 1) |
350 |
1/2✓ Branch 5 → 6 taken 95 times.
✗ Branch 5 → 38 not taken.
|
95 | return operands.front()->getCompileTimeValue(); |
351 | |||
352 |
2/4✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 38 not taken.
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 38 not taken.
|
1 | const CompileTimeValue op0Value = operands.at(0)->getCompileTimeValue(); |
353 |
2/4✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 38 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 38 not taken.
|
1 | const CompileTimeValue op1Value = operands.at(1)->getCompileTimeValue(); |
354 |
1/2✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 1 time.
|
1 | if (op == RelationalOp::OP_LESS) |
355 | ✗ | return CompileTimeValue{.boolValue = op0Value.longValue < op1Value.longValue}; | |
356 |
1/2✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 1 time.
|
1 | if (op == RelationalOp::OP_GREATER) |
357 | ✗ | return CompileTimeValue{.boolValue = op0Value.longValue > op1Value.longValue}; | |
358 |
1/2✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 17 not taken.
|
1 | if (op == RelationalOp::OP_LESS_EQUAL) |
359 | 1 | return CompileTimeValue{.boolValue = op0Value.longValue <= op1Value.longValue}; | |
360 | ✗ | if (op == RelationalOp::OP_GREATER_EQUAL) | |
361 | ✗ | return CompileTimeValue{.boolValue = op0Value.longValue >= op1Value.longValue}; | |
362 | |||
363 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "RelationalExprNode::getCompileTimeValue()"); | |
364 | } | ||
365 | |||
366 | 10717 | bool ShiftExprNode::hasCompileTimeValue() const { | |
367 | 21434 | return std::ranges::all_of(operands, [](const AdditiveExprNode *node) { return node->hasCompileTimeValue(); }); | |
368 | } | ||
369 | |||
370 | 97 | CompileTimeValue ShiftExprNode::getCompileTimeValue() const { | |
371 |
1/2✓ Branch 3 → 4 taken 97 times.
✗ Branch 3 → 7 not taken.
|
97 | if (operands.size() == 1) |
372 |
1/2✓ Branch 5 → 6 taken 97 times.
✗ Branch 5 → 49 not taken.
|
97 | return operands.front()->getCompileTimeValue(); |
373 | |||
374 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
375 | ✗ | OpQueue opQueueCopy = opQueue; | |
376 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
377 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
378 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
379 | ✗ | const ShiftOp op = opQueueCopy.front().first; | |
380 | ✗ | opQueueCopy.pop(); | |
381 | ✗ | if (op == ShiftOp::OP_SHIFT_LEFT) | |
382 | ✗ | result.longValue <<= opCompileTimeValue.longValue; | |
383 | ✗ | else if (op == ShiftOp::OP_SHIFT_RIGHT) | |
384 | ✗ | result.longValue >>= opCompileTimeValue.longValue; | |
385 | else | ||
386 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "ShiftExprNode::getCompileTimeValue()"); | |
387 | } | ||
388 | ✗ | return result; | |
389 | ✗ | } | |
390 | |||
391 | 10717 | bool AdditiveExprNode::hasCompileTimeValue() const { | |
392 | 21434 | return std::ranges::all_of(operands, [](const MultiplicativeExprNode *node) { return node->hasCompileTimeValue(); }); | |
393 | } | ||
394 | |||
395 | 97 | CompileTimeValue AdditiveExprNode::getCompileTimeValue() const { | |
396 |
1/2✓ Branch 3 → 4 taken 97 times.
✗ Branch 3 → 7 not taken.
|
97 | if (operands.size() == 1) |
397 |
1/2✓ Branch 5 → 6 taken 97 times.
✗ Branch 5 → 49 not taken.
|
97 | return operands.front()->getCompileTimeValue(); |
398 | |||
399 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
400 | ✗ | OpQueue opQueueCopy = opQueue; | |
401 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
402 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
403 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
404 | ✗ | const AdditiveOp op = opQueueCopy.front().first; | |
405 | ✗ | opQueueCopy.pop(); | |
406 | ✗ | if (op == AdditiveOp::OP_PLUS) | |
407 | ✗ | result.longValue += opCompileTimeValue.longValue; | |
408 | ✗ | else if (op == AdditiveOp::OP_MINUS) | |
409 | ✗ | result.longValue -= opCompileTimeValue.longValue; | |
410 | else | ||
411 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "AdditiveExprNode::getCompileTimeValue()"); | |
412 | } | ||
413 | ✗ | return result; | |
414 | ✗ | } | |
415 | |||
416 | 10717 | bool MultiplicativeExprNode::hasCompileTimeValue() const { | |
417 | 21434 | return std::ranges::all_of(operands, [](const CastExprNode *node) { return node->hasCompileTimeValue(); }); | |
418 | } | ||
419 | |||
420 | 97 | CompileTimeValue MultiplicativeExprNode::getCompileTimeValue() const { | |
421 |
1/2✓ Branch 3 → 4 taken 97 times.
✗ Branch 3 → 7 not taken.
|
97 | if (operands.size() == 1) |
422 |
1/2✓ Branch 5 → 6 taken 97 times.
✗ Branch 5 → 70 not taken.
|
97 | return operands.front()->getCompileTimeValue(); |
423 | |||
424 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
425 | ✗ | OpQueue opQueueCopy = opQueue; | |
426 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
427 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
428 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
429 | ✗ | const MultiplicativeOp op = opQueueCopy.front().first; | |
430 | ✗ | opQueueCopy.pop(); | |
431 | ✗ | if (op == MultiplicativeOp::OP_MUL) { | |
432 | ✗ | result.longValue *= opCompileTimeValue.longValue; | |
433 | ✗ | } else if (op == MultiplicativeOp::OP_DIV) { | |
434 | ✗ | if (opCompileTimeValue.longValue == 0) | |
435 | ✗ | throw SemanticError(operands.at(i), DIVISION_BY_ZERO, "Dividing by zero is not allowed."); | |
436 | ✗ | result.longValue /= opCompileTimeValue.longValue; | |
437 | ✗ | } else if (op == MultiplicativeOp::OP_REM) { | |
438 | ✗ | result.longValue %= opCompileTimeValue.longValue; | |
439 | } else { | ||
440 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "MultiplicativeExprNode::getCompileTimeValue()"); | |
441 | } | ||
442 | } | ||
443 | ✗ | return result; | |
444 | ✗ | } | |
445 | |||
446 | 10717 | bool CastExprNode::hasCompileTimeValue() const { | |
447 |
2/2✓ Branch 2 → 3 taken 371 times.
✓ Branch 2 → 5 taken 10346 times.
|
10717 | return isCast ? assignExpr->hasCompileTimeValue() : prefixUnaryExpr->hasCompileTimeValue(); |
448 | } | ||
449 | |||
450 | 97 | CompileTimeValue CastExprNode::getCompileTimeValue() const { | |
451 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 97 times.
|
97 | return isCast ? assignExpr->getCompileTimeValue() : prefixUnaryExpr->getCompileTimeValue(); |
452 | } | ||
453 | |||
454 | 10702 | bool PrefixUnaryExprNode::hasCompileTimeValue() const { // NOLINT(*-no-recursion) | |
455 |
2/2✓ Branch 2 → 3 taken 10330 times.
✓ Branch 2 → 5 taken 372 times.
|
10702 | if (postfixUnaryExpr) |
456 | 10330 | return postfixUnaryExpr->hasCompileTimeValue(); | |
457 | |||
458 |
3/4✓ Branch 6 → 7 taken 364 times.
✓ Branch 6 → 11 taken 8 times.
✓ Branch 7 → 8 taken 364 times.
✗ Branch 7 → 11 not taken.
|
372 | const bool isSupported = op == PrefixUnaryOp::OP_NONE || op == PrefixUnaryOp::OP_MINUS || op == PrefixUnaryOp::OP_PLUS_PLUS || |
459 |
4/6✓ Branch 5 → 6 taken 372 times.
✗ Branch 5 → 11 not taken.
✓ Branch 8 → 9 taken 364 times.
✗ Branch 8 → 11 not taken.
✓ Branch 9 → 10 taken 16 times.
✓ Branch 9 → 11 taken 348 times.
|
760 | op == PrefixUnaryOp::OP_MINUS_MINUS || op == PrefixUnaryOp::OP_NOT || |
460 |
1/2✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 16 times.
|
16 | op == PrefixUnaryOp::OP_BITWISE_NOT; |
461 |
3/4✓ Branch 13 → 14 taken 356 times.
✓ Branch 13 → 17 taken 16 times.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 356 times.
|
372 | return isSupported && prefixUnaryExpr->hasCompileTimeValue(); |
462 | } | ||
463 | |||
464 | 97 | CompileTimeValue PrefixUnaryExprNode::getCompileTimeValue() const { // NOLINT(*-no-recursion) | |
465 |
1/2✓ Branch 2 → 3 taken 97 times.
✗ Branch 2 → 5 not taken.
|
97 | if (postfixUnaryExpr) |
466 |
1/2✓ Branch 3 → 4 taken 97 times.
✗ Branch 3 → 35 not taken.
|
97 | return postfixUnaryExpr->getCompileTimeValue(); |
467 | |||
468 | ✗ | CompileTimeValue opValue = prefixUnaryExpr->getCompileTimeValue(); | |
469 | ✗ | if (op == PrefixUnaryOp::OP_MINUS) | |
470 | ✗ | return CompileTimeValue{.longValue = -opValue.longValue}; | |
471 | ✗ | if (op == PrefixUnaryOp::OP_PLUS_PLUS) | |
472 | ✗ | return CompileTimeValue{.longValue = ++opValue.longValue}; | |
473 | ✗ | if (op == PrefixUnaryOp::OP_MINUS_MINUS) | |
474 | ✗ | return CompileTimeValue{.longValue = --opValue.longValue}; | |
475 | ✗ | if (op == PrefixUnaryOp::OP_NOT) | |
476 | ✗ | return CompileTimeValue{.boolValue = !opValue.boolValue}; | |
477 | ✗ | if (op == PrefixUnaryOp::OP_BITWISE_NOT) | |
478 | ✗ | return CompileTimeValue{.longValue = ~opValue.longValue}; | |
479 | |||
480 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "PrefixUnaryExprNode::getCompileTimeValue()"); | |
481 | } | ||
482 | |||
483 | 10330 | bool PostfixUnaryExprNode::hasCompileTimeValue() const { // NOLINT(*-no-recursion) | |
484 |
2/2✓ Branch 2 → 3 taken 8038 times.
✓ Branch 2 → 5 taken 2292 times.
|
10330 | if (atomicExpr) |
485 | 8038 | return atomicExpr->hasCompileTimeValue(); | |
486 | |||
487 | 2292 | const bool isSupported = | |
488 |
3/6✓ Branch 5 → 6 taken 2292 times.
✗ Branch 5 → 8 not taken.
✓ Branch 6 → 7 taken 2292 times.
✗ Branch 6 → 8 not taken.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 2292 times.
|
2292 | op == PostfixUnaryOp::OP_NONE || op == PostfixUnaryOp::OP_PLUS_PLUS || op == PostfixUnaryOp::OP_MINUS_MINUS; |
489 |
1/4✗ Branch 10 → 11 not taken.
✓ Branch 10 → 14 taken 2292 times.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
|
2292 | return isSupported && postfixUnaryExpr->hasCompileTimeValue(); |
490 | } | ||
491 | |||
492 | 97 | CompileTimeValue PostfixUnaryExprNode::getCompileTimeValue() const { // NOLINT(*-no-recursion) | |
493 |
1/2✓ Branch 2 → 3 taken 97 times.
✗ Branch 2 → 5 not taken.
|
97 | if (atomicExpr) |
494 |
1/2✓ Branch 3 → 4 taken 97 times.
✗ Branch 3 → 29 not taken.
|
97 | return atomicExpr->getCompileTimeValue(); |
495 | |||
496 | ✗ | CompileTimeValue opValue = postfixUnaryExpr->getCompileTimeValue(); | |
497 | ✗ | if (op == PostfixUnaryOp::OP_PLUS_PLUS) | |
498 | ✗ | return CompileTimeValue{.longValue = opValue.longValue++}; | |
499 | ✗ | if (op == PostfixUnaryOp::OP_MINUS_MINUS) | |
500 | ✗ | return CompileTimeValue{.longValue = opValue.longValue--}; | |
501 | |||
502 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "PostfixUnaryExprNode::getCompileTimeValue()"); | |
503 | } | ||
504 | |||
505 | /** | ||
506 | * Check if right above the closest assign expression ancestor is a statement node | ||
507 | * | ||
508 | * @return Has return value receiver or not | ||
509 | */ | ||
510 | 9797 | bool FctCallNode::hasReturnValueReceiver() const { | |
511 | 9797 | const ASTNode *node = parent; | |
512 |
2/2✓ Branch 10 → 3 taken 149200 times.
✓ Branch 10 → 11 taken 7486 times.
|
156686 | while (!node->isAssignExpr()) { |
513 | // As soon as we have a node with more than one child, we know that the return value is used | ||
514 |
3/4✓ Branch 3 → 4 taken 149200 times.
✗ Branch 3 → 23 not taken.
✓ Branch 6 → 7 taken 2311 times.
✓ Branch 6 → 8 taken 146889 times.
|
149200 | if (node->getChildren().size() > 1) |
515 | 2311 | return true; | |
516 | 146889 | node = node->parent; | |
517 | } | ||
518 | // Also check the condition of the assign expression | ||
519 |
6/12✓ Branch 11 → 12 taken 7486 times.
✗ Branch 11 → 24 not taken.
✓ Branch 13 → 14 taken 7486 times.
✗ Branch 13 → 16 not taken.
✓ Branch 14 → 15 taken 7486 times.
✗ Branch 14 → 24 not taken.
✓ Branch 15 → 16 taken 7252 times.
✓ Branch 15 → 17 taken 234 times.
✓ Branch 19 → 20 taken 7486 times.
✗ Branch 19 → 21 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
|
7486 | return node->getChildren().size() > 1 || !node->parent->isExprStmt(); |
520 | } | ||
521 | |||
522 | 12 | bool LambdaFuncNode::returnsOnAllControlPaths(bool *overrideUnreachable) const { | |
523 | 12 | return body->returnsOnAllControlPaths(overrideUnreachable); | |
524 | } | ||
525 | |||
526 | 38 | bool LambdaProcNode::returnsOnAllControlPaths(bool *overrideUnreachable) const { | |
527 | 38 | return body->returnsOnAllControlPaths(overrideUnreachable); | |
528 | } | ||
529 | |||
530 | 1703 | void DataTypeNode::setFieldTypeRecursive() { // NOLINT(*-no-recursion) | |
531 | // Set the current node to field type | ||
532 | 1703 | isFieldType = true; | |
533 | // Do the same for all template nodes | ||
534 |
4/4✓ Branch 2 → 3 taken 785 times.
✓ Branch 2 → 12 taken 918 times.
✓ Branch 3 → 4 taken 181 times.
✓ Branch 3 → 12 taken 604 times.
|
1703 | if (const CustomDataTypeNode *customType = baseDataType->customDataType; customType != nullptr && customType->templateTypeLst) |
535 |
2/2✓ Branch 10 → 6 taken 252 times.
✓ Branch 10 → 11 taken 181 times.
|
433 | for (DataTypeNode *templateNode : customType->templateTypeLst->dataTypes) |
536 |
1/2✓ Branch 7 → 8 taken 252 times.
✗ Branch 7 → 13 not taken.
|
252 | templateNode->setFieldTypeRecursive(); |
537 | 1703 | } | |
538 | |||
539 | } // namespace spice::compiler | ||
540 |