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 | 788 | std::string ASTNode::getErrorMessage() const { | |
16 | 788 | antlr4::CharStream *inputStream = codeLoc.sourceFile->antlrCtx.inputStream.get(); | |
17 | 788 | const antlr4::misc::Interval &sourceInterval = codeLoc.sourceInterval; | |
18 | 788 | antlr4::misc::Interval extSourceInterval(sourceInterval); | |
19 | |||
20 | // If we have a multi-line interval, only use the first line | ||
21 |
3/4✓ Branch 0 (3→4) taken 788 times.
✗ Branch 1 (3→77) not taken.
✓ Branch 2 (6→7) taken 19 times.
✓ Branch 3 (6→8) taken 769 times.
|
788 | 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 | 788 | size_t markerIndentation = 0; | |
25 |
2/2✓ Branch 0 (20→9) taken 8452 times.
✓ Branch 1 (20→21) taken 191 times.
|
8643 | for (; markerIndentation < ERROR_MESSAGE_CONTEXT; markerIndentation++) { |
26 | 8452 | extSourceInterval.a--; | |
27 |
9/12✓ Branch 0 (9→10) taken 8438 times.
✓ Branch 1 (9→13) taken 14 times.
✓ Branch 2 (10→11) taken 8438 times.
✗ Branch 3 (10→78) not taken.
✓ Branch 4 (12→13) taken 583 times.
✓ Branch 5 (12→14) taken 7855 times.
✓ Branch 6 (15→16) taken 8438 times.
✓ Branch 7 (15→17) taken 14 times.
✓ Branch 8 (17→18) taken 597 times.
✓ Branch 9 (17→19) taken 7855 times.
✗ Branch 10 (78→79) not taken.
✗ Branch 11 (78→80) not taken.
|
8452 | if (extSourceInterval.a < 0 || inputStream->getText(extSourceInterval).find('\n') != std::string::npos) { |
28 | 597 | extSourceInterval.a++; | |
29 | 597 | break; | |
30 | } | ||
31 | } | ||
32 |
2/2✓ Branch 0 (34→22) taken 2256 times.
✓ Branch 1 (34→35) taken 8 times.
|
2264 | for (size_t suffixContext = 0; suffixContext < ERROR_MESSAGE_CONTEXT; suffixContext++) { |
33 | 2256 | extSourceInterval.b++; | |
34 |
4/6✓ Branch 0 (22→23) taken 2256 times.
✗ Branch 1 (22→82) not taken.
✓ Branch 2 (23→24) taken 2256 times.
✗ Branch 3 (23→27) not taken.
✓ Branch 4 (26→27) taken 780 times.
✓ Branch 5 (26→28) taken 1476 times.
|
4512 | if (static_cast<size_t>(extSourceInterval.b) > inputStream->size() || |
35 |
4/8✓ Branch 0 (24→25) taken 2256 times.
✗ Branch 1 (24→82) not taken.
✓ Branch 2 (29→30) taken 2256 times.
✗ Branch 3 (29→31) not taken.
✓ Branch 4 (31→32) taken 780 times.
✓ Branch 5 (31→33) taken 1476 times.
✗ Branch 6 (82→83) not taken.
✗ Branch 7 (82→84) not taken.
|
4512 | inputStream->getText(extSourceInterval).find('\n') != std::string::npos) { |
36 | 780 | extSourceInterval.b--; | |
37 | 780 | break; | |
38 | } | ||
39 | } | ||
40 | |||
41 | // Trim start | ||
42 |
3/4✓ Branch 0 (37→38) taken 4500 times.
✗ Branch 1 (37→86) not taken.
✓ Branch 2 (40→36) taken 3712 times.
✓ Branch 3 (40→41) taken 788 times.
|
4500 | while (inputStream->getText(extSourceInterval)[0] == ' ') { |
43 | 3712 | extSourceInterval.a++; | |
44 | 3712 | markerIndentation--; | |
45 | } | ||
46 | |||
47 | // Trim end | ||
48 |
3/4✓ Branch 0 (41→42) taken 788 times.
✗ Branch 1 (41→87) not taken.
✓ Branch 2 (45→46) taken 19 times.
✓ Branch 3 (45→47) taken 769 times.
|
788 | if (inputStream->getText(extSourceInterval)[extSourceInterval.length() - 1] == '\n') |
49 | 19 | extSourceInterval.b--; | |
50 | |||
51 | 788 | const std::string lineNumberStr = std::to_string(codeLoc.line); | |
52 | 788 | markerIndentation += lineNumberStr.length() + 2; | |
53 | |||
54 | // Build error message | ||
55 |
1/2✓ Branch 0 (49→50) taken 788 times.
✗ Branch 1 (49→107) not taken.
|
788 | std::stringstream ss; |
56 |
5/10✓ Branch 0 (50→51) taken 788 times.
✗ Branch 1 (50→105) not taken.
✓ Branch 2 (51→52) taken 788 times.
✗ Branch 3 (51→105) not taken.
✓ Branch 4 (52→53) taken 788 times.
✗ Branch 5 (52→90) not taken.
✓ Branch 6 (53→54) taken 788 times.
✗ Branch 7 (53→88) not taken.
✓ Branch 8 (54→55) taken 788 times.
✗ Branch 9 (54→88) not taken.
|
788 | ss << lineNumberStr << " " << inputStream->getText(extSourceInterval) << "\n"; |
57 |
2/4✓ Branch 0 (58→59) taken 788 times.
✗ Branch 1 (58→93) not taken.
✓ Branch 2 (59→60) taken 788 times.
✗ Branch 3 (59→91) not taken.
|
1576 | ss << std::string(markerIndentation, ' '); |
58 |
2/4✓ Branch 0 (67→68) taken 788 times.
✗ Branch 1 (67→99) not taken.
✓ Branch 2 (68→69) taken 788 times.
✗ Branch 3 (68→97) not taken.
|
788 | ss << std::string(std::min(sourceInterval.length(), extSourceInterval.length()), '^'); |
59 |
1/2✓ Branch 0 (71→72) taken 788 times.
✗ Branch 1 (71→105) not taken.
|
1576 | return ss.str(); |
60 | 788 | } | |
61 | |||
62 | 28130 | const StmtLstNode *ASTNode::getNextOuterStmtLst() const { // NOLINT(*-no-recursion) | |
63 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 28130 times.
|
28130 | assert(parent != nullptr && "Could not find next outer statement list"); |
64 |
2/2✓ Branch 0 (5→6) taken 16939 times.
✓ Branch 1 (5→14) taken 11191 times.
|
45069 | return isStmtLst() ? spice_pointer_cast<const StmtLstNode *>(this) : parent->getNextOuterStmtLst(); |
65 | } | ||
66 | |||
67 | 362 | bool MainFctDefNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
68 | 362 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
69 | } | ||
70 | |||
71 | 9787 | bool FctDefBaseNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
72 | 9787 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
73 | } | ||
74 | |||
75 | 46 | CompileTimeValue GlobalVarDefNode::getCompileTimeValue() const { return constant->getCompileTimeValue(); } | |
76 | |||
77 | 1062 | 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 0 (3→4) taken 1 times.
✓ Branch 1 (3→7) taken 1061 times.
✗ Branch 2 (5→6) not taken.
✓ Branch 3 (5→7) taken 1 times.
|
1062 | const bool loopConditionAlwaysTrue = condAssign->hasCompileTimeValue() && condAssign->getCompileTimeValue().boolValue; |
81 |
1/4✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→12) taken 1062 times.
✗ Branch 2 (10→11) not taken.
✗ Branch 3 (10→12) not taken.
|
1062 | return loopConditionAlwaysTrue && body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
82 | } | ||
83 | |||
84 | 675 | 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 0 (3→4) taken 4 times.
✓ Branch 1 (3→7) taken 671 times.
✓ Branch 2 (5→6) taken 4 times.
✗ Branch 3 (5→7) not taken.
|
675 | const bool loopConditionAlwaysTrue = condition->hasCompileTimeValue() && condition->getCompileTimeValue().boolValue; |
88 |
3/4✓ Branch 0 (8→9) taken 4 times.
✓ Branch 1 (8→12) taken 671 times.
✗ Branch 2 (10→11) not taken.
✓ Branch 3 (10→12) taken 4 times.
|
675 | 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 | 3026 | 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 0 (3→4) taken 13 times.
✓ Branch 1 (3→7) taken 3013 times.
✓ Branch 2 (5→6) taken 4 times.
✓ Branch 3 (5→7) taken 9 times.
✓ Branch 4 (8→9) taken 4 times.
✓ Branch 5 (8→11) taken 3022 times.
|
3026 | 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 0 (12→13) taken 9 times.
✓ Branch 1 (12→16) taken 3013 times.
✓ Branch 2 (14→15) taken 9 times.
✗ Branch 3 (14→16) not taken.
✓ Branch 4 (17→18) taken 9 times.
✓ Branch 5 (17→24) taken 3013 times.
|
3022 | if (condition->hasCompileTimeValue() && !condition->getCompileTimeValue().boolValue) |
103 |
3/4✓ Branch 0 (18→19) taken 4 times.
✓ Branch 1 (18→22) taken 5 times.
✗ Branch 2 (20→21) not taken.
✓ Branch 3 (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 0 (25→26) taken 2267 times.
✓ Branch 1 (25→30) taken 746 times.
✓ Branch 2 (26→27) taken 30 times.
✓ Branch 3 (26→30) taken 2237 times.
|
3043 | return thenBody->returnsOnAllControlPaths(doSetPredecessorsUnreachable) && elseStmt != nullptr && |
107 |
1/2✓ Branch 0 (28→29) taken 30 times.
✗ Branch 1 (28→30) not taken.
|
3043 | elseStmt->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
108 | } | ||
109 | |||
110 | 34 | bool ElseStmtNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { // NOLINT(misc-no-recursion) | |
111 |
2/2✓ Branch 0 (2→3) taken 11 times.
✓ Branch 1 (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 0 (2→3) taken 12 times.
✗ Branch 1 (2→15) not taken.
|
12 | const bool allCaseBranchesReturn = std::ranges::all_of(caseBranches, pred); |
119 |
4/6✓ Branch 0 (3→4) taken 6 times.
✓ Branch 1 (3→6) taken 6 times.
✓ Branch 2 (4→5) taken 6 times.
✗ Branch 3 (4→15) not taken.
✓ Branch 4 (5→6) taken 6 times.
✗ Branch 5 (5→7) not taken.
|
12 | const bool defaultBranchReturns = !defaultBranch || defaultBranch->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
120 |
3/4✓ Branch 0 (8→9) taken 9 times.
✓ Branch 1 (8→11) taken 3 times.
✓ Branch 2 (9→10) taken 9 times.
✗ Branch 3 (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 | 15448 | bool StmtLstNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
132 | // An empty statement list does not return at all | ||
133 |
2/2✓ Branch 0 (3→4) taken 30 times.
✓ Branch 1 (3→5) taken 15418 times.
|
15448 | if (statements.empty()) |
134 | 30 | return false; | |
135 | // A statement list returns on all control paths, if the one direct child statement returns on all control paths | ||
136 | 15418 | bool returnsOnAllControlPaths = false; | |
137 |
2/2✓ Branch 0 (18→7) taken 29823 times.
✓ Branch 1 (18→19) taken 15418 times.
|
45241 | for (StmtNode *child : statements) { |
138 |
1/2✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 29823 times.
|
29823 | assert(child != nullptr); |
139 | |||
140 | // Prevent marking instructions as unreachable if doSetPredecessorsUnreachable is set to false | ||
141 |
4/4✓ Branch 0 (10→11) taken 679 times.
✓ Branch 1 (10→13) taken 29144 times.
✓ Branch 2 (11→12) taken 7 times.
✓ Branch 3 (11→13) taken 672 times.
|
29823 | if (returnsOnAllControlPaths && *doSetPredecessorsUnreachable) |
142 | 7 | child->unreachable = true; | |
143 | |||
144 |
3/4✓ Branch 0 (13→14) taken 29823 times.
✗ Branch 1 (13→21) not taken.
✓ Branch 2 (14→15) taken 9179 times.
✓ Branch 3 (14→16) taken 20644 times.
|
29823 | if (child->returnsOnAllControlPaths(doSetPredecessorsUnreachable)) |
145 | 9179 | returnsOnAllControlPaths = true; | |
146 | } | ||
147 | 15418 | return returnsOnAllControlPaths; | |
148 | } | ||
149 | |||
150 | 2288 | std::vector<const CompileTimeValue *> AttrLstNode::getAttrValuesByName(const std::string &key) const { | |
151 |
1/2✗ Branch 0 (3→4) not taken.
✓ Branch 1 (3→5) taken 2288 times.
|
2288 | assert(ATTR_CONFIGS.contains(key)); |
152 | |||
153 | 2288 | std::vector<const CompileTimeValue *> attributeValues; | |
154 |
2/2✓ Branch 0 (19→7) taken 3622 times.
✓ Branch 1 (19→20) taken 2288 times.
|
5910 | for (const AttrNode *attrNode : attributes) { |
155 | // Skip attributes with different keys | ||
156 |
2/2✓ Branch 0 (9→10) taken 2715 times.
✓ Branch 1 (9→11) taken 907 times.
|
3622 | if (attrNode->key != key) |
157 | 2715 | continue; | |
158 | |||
159 | // Found a matching attribute | ||
160 | 907 | const CompileTimeValue *value = attrNode->getValue(); | |
161 |
2/2✓ Branch 0 (12→13) taken 57 times.
✓ Branch 1 (12→15) taken 850 times.
|
907 | if (!value) { |
162 | // If the attribute has no value, we use the default value | ||
163 |
1/2✓ Branch 0 (13→14) taken 57 times.
✗ Branch 1 (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 0 (15→16) taken 850 times.
✗ Branch 1 (15→23) not taken.
|
850 | attributeValues.push_back(value); |
167 | } | ||
168 | } | ||
169 | |||
170 | 2288 | return attributeValues; | |
171 | ✗ | } | |
172 | |||
173 | 1379 | const CompileTimeValue *AttrLstNode::getAttrValueByName(const std::string &key) const { | |
174 |
1/2✓ Branch 0 (2→3) taken 1379 times.
✗ Branch 1 (2→12) not taken.
|
1379 | const std::vector<const CompileTimeValue *> attrs = getAttrValuesByName(key); |
175 |
2/2✓ Branch 0 (4→5) taken 901 times.
✓ Branch 1 (4→6) taken 478 times.
|
2758 | return attrs.empty() ? nullptr : attrs.back(); |
176 | 1379 | } | |
177 | |||
178 | 1210 | bool AttrLstNode::hasAttr(const std::string &key) const { | |
179 | 3289 | return std::ranges::any_of(attributes, [&](const AttrNode *attr) { return attr->key == key; }); | |
180 | } | ||
181 | |||
182 |
2/2✓ Branch 0 (2→3) taken 850 times.
✓ Branch 1 (2→4) taken 57 times.
|
907 | const CompileTimeValue *AttrNode::getValue() const { return value ? &value->compileTimeValue : nullptr; } |
183 | |||
184 | 686 | 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 0 (3→4) taken 4 times.
✓ Branch 1 (3→7) taken 682 times.
✓ Branch 2 (5→6) taken 3 times.
✓ Branch 3 (5→7) taken 1 times.
|
686 | return assignExpr->hasCompileTimeValue() && !assignExpr->getCompileTimeValue().boolValue; |
187 | } | ||
188 | |||
189 | 12087 | bool AssignExprNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
190 | // If it's a ternary, do the default thing | ||
191 |
2/2✓ Branch 0 (2→3) taken 7013 times.
✓ Branch 1 (2→5) taken 5074 times.
|
12087 | if (op == AssignOp::OP_NONE) |
192 | 7013 | 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 0 (5→6) taken 5069 times.
✓ Branch 1 (5→7) taken 5 times.
|
5074 | const AtomicExprNode *atomicExpr = lhs->postfixUnaryExpr ? lhs->postfixUnaryExpr->atomicExpr : nullptr; |
196 |
6/6✓ Branch 0 (8→9) taken 964 times.
✓ Branch 1 (8→12) taken 4110 times.
✓ Branch 2 (10→11) taken 419 times.
✓ Branch 3 (10→12) taken 545 times.
✓ Branch 4 (13→14) taken 419 times.
✓ Branch 5 (13→15) taken 4655 times.
|
5074 | 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 | 419 | *doSetPredecessorsUnreachable = false; | |
200 | 419 | return true; | |
201 | } | ||
202 | |||
203 | 4655 | return false; | |
204 | } | ||
205 | |||
206 | 9368 | bool TernaryExprNode::hasCompileTimeValue() const { | |
207 |
4/4✓ Branch 0 (2→3) taken 7 times.
✓ Branch 1 (2→5) taken 9361 times.
✓ Branch 2 (4→5) taken 4 times.
✓ Branch 3 (4→6) taken 3 times.
|
9368 | const bool trueExprHasCompileTimeValue = !trueExpr || trueExpr->hasCompileTimeValue(); |
208 |
4/4✓ Branch 0 (7→8) taken 7 times.
✓ Branch 1 (7→10) taken 9361 times.
✓ Branch 2 (9→10) taken 5 times.
✓ Branch 3 (9→11) taken 2 times.
|
9368 | const bool falseExprHasCompileTimeValue = !falseExpr || falseExpr->hasCompileTimeValue(); |
209 |
4/6✓ Branch 0 (13→14) taken 213 times.
✓ Branch 1 (13→17) taken 9155 times.
✓ Branch 2 (14→15) taken 213 times.
✗ Branch 3 (14→17) not taken.
✓ Branch 4 (15→16) taken 213 times.
✗ Branch 5 (15→17) not taken.
|
9368 | return condition->hasCompileTimeValue() && trueExprHasCompileTimeValue && falseExprHasCompileTimeValue; |
210 | } | ||
211 | |||
212 | 82 | CompileTimeValue TernaryExprNode::getCompileTimeValue() const { | |
213 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 82 times.
|
82 | assert(condition != nullptr); |
214 |
2/4✓ Branch 0 (4→5) taken 82 times.
✗ Branch 1 (4→7) not taken.
✓ Branch 2 (5→6) taken 82 times.
✗ Branch 3 (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 | 9773 | bool LogicalOrExprNode::hasCompileTimeValue() const { | |
233 | 19548 | return std::ranges::all_of(operands, [](const LogicalAndExprNode *node) { return node->hasCompileTimeValue(); }); | |
234 | } | ||
235 | |||
236 | 82 | CompileTimeValue LogicalOrExprNode::getCompileTimeValue() const { | |
237 |
2/2✓ Branch 0 (3→4) taken 80 times.
✓ Branch 1 (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 0 (17→8) taken 4 times.
✓ Branch 1 (17→18) taken 2 times.
|
6 | for (const LogicalAndExprNode *op : operands) { |
242 |
2/4✓ Branch 0 (9→10) taken 4 times.
✗ Branch 1 (9→21) not taken.
✗ Branch 2 (10→11) not taken.
✓ Branch 3 (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 0 (12→13) taken 4 times.
✗ Branch 1 (12→20) not taken.
✗ Branch 2 (13→14) not taken.
✓ Branch 3 (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 | 9779 | bool LogicalAndExprNode::hasCompileTimeValue() const { | |
253 | 19560 | return std::ranges::all_of(operands, [](const BitwiseOrExprNode *node) { return node->hasCompileTimeValue(); }); | |
254 | } | ||
255 | |||
256 | 84 | CompileTimeValue LogicalAndExprNode::getCompileTimeValue() const { | |
257 |
2/2✓ Branch 0 (3→4) taken 82 times.
✓ Branch 1 (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 0 (17→8) taken 4 times.
✗ Branch 1 (17→18) not taken.
|
4 | for (const BitwiseOrExprNode *op : operands) { |
262 |
2/4✓ Branch 0 (9→10) taken 4 times.
✗ Branch 1 (9→21) not taken.
✗ Branch 2 (10→11) not taken.
✓ Branch 3 (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 0 (12→13) taken 4 times.
✗ Branch 1 (12→20) not taken.
✓ Branch 2 (13→14) taken 2 times.
✓ Branch 3 (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 | 9785 | bool BitwiseOrExprNode::hasCompileTimeValue() const { | |
273 | 19570 | return std::ranges::all_of(operands, [](const BitwiseXorExprNode *node) { return node->hasCompileTimeValue(); }); | |
274 | } | ||
275 | |||
276 | 86 | CompileTimeValue BitwiseOrExprNode::getCompileTimeValue() const { | |
277 |
1/2✓ Branch 0 (3→4) taken 86 times.
✗ Branch 1 (3→7) not taken.
|
86 | if (operands.size() == 1) |
278 |
1/2✓ Branch 0 (5→6) taken 86 times.
✗ Branch 1 (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 | 9785 | bool BitwiseXorExprNode::hasCompileTimeValue() const { | |
291 | 19570 | return std::ranges::all_of(operands, [](const BitwiseAndExprNode *node) { return node->hasCompileTimeValue(); }); | |
292 | } | ||
293 | |||
294 | 86 | CompileTimeValue BitwiseXorExprNode::getCompileTimeValue() const { | |
295 |
1/2✓ Branch 0 (3→4) taken 86 times.
✗ Branch 1 (3→7) not taken.
|
86 | if (operands.size() == 1) |
296 |
1/2✓ Branch 0 (5→6) taken 86 times.
✗ Branch 1 (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 | 9785 | bool BitwiseAndExprNode::hasCompileTimeValue() const { | |
309 | 19570 | return std::ranges::all_of(operands, [](const EqualityExprNode *node) { return node->hasCompileTimeValue(); }); | |
310 | } | ||
311 | |||
312 | 86 | CompileTimeValue BitwiseAndExprNode::getCompileTimeValue() const { | |
313 |
1/2✓ Branch 0 (3→4) taken 86 times.
✗ Branch 1 (3→7) not taken.
|
86 | if (operands.size() == 1) |
314 |
1/2✓ Branch 0 (5→6) taken 86 times.
✗ Branch 1 (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 | 9785 | bool EqualityExprNode::hasCompileTimeValue() const { | |
327 | 19580 | return std::ranges::all_of(operands, [](const RelationalExprNode *node) { return node->hasCompileTimeValue(); }); | |
328 | } | ||
329 | |||
330 | 86 | CompileTimeValue EqualityExprNode::getCompileTimeValue() const { | |
331 |
2/2✓ Branch 0 (3→4) taken 76 times.
✓ Branch 1 (3→7) taken 10 times.
|
86 | if (operands.size() == 1) |
332 |
1/2✓ Branch 0 (5→6) taken 76 times.
✗ Branch 1 (5→34) not taken.
|
76 | return operands.front()->getCompileTimeValue(); |
333 | |||
334 |
2/4✓ Branch 0 (7→8) taken 10 times.
✗ Branch 1 (7→34) not taken.
✓ Branch 2 (8→9) taken 10 times.
✗ Branch 3 (8→34) not taken.
|
10 | const CompileTimeValue op0Value = operands.at(0)->getCompileTimeValue(); |
335 |
2/4✓ Branch 0 (9→10) taken 10 times.
✗ Branch 1 (9→34) not taken.
✓ Branch 2 (10→11) taken 10 times.
✗ Branch 3 (10→34) not taken.
|
10 | const CompileTimeValue op1Value = operands.at(1)->getCompileTimeValue(); |
336 |
2/2✓ Branch 0 (11→12) taken 6 times.
✓ Branch 1 (11→13) taken 4 times.
|
10 | if (op == EqualityOp::OP_EQUAL) |
337 | 6 | return CompileTimeValue{.boolValue = op0Value.longValue == op1Value.longValue}; | |
338 |
1/2✓ Branch 0 (13→14) taken 4 times.
✗ Branch 1 (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 | 9795 | bool RelationalExprNode::hasCompileTimeValue() const { | |
345 | 19591 | return std::ranges::all_of(operands, [](const ShiftExprNode *node) { return node->hasCompileTimeValue(); }); | |
346 | } | ||
347 | |||
348 | 96 | CompileTimeValue RelationalExprNode::getCompileTimeValue() const { | |
349 |
2/2✓ Branch 0 (3→4) taken 95 times.
✓ Branch 1 (3→7) taken 1 times.
|
96 | if (operands.size() == 1) |
350 |
1/2✓ Branch 0 (5→6) taken 95 times.
✗ Branch 1 (5→38) not taken.
|
95 | return operands.front()->getCompileTimeValue(); |
351 | |||
352 |
2/4✓ Branch 0 (7→8) taken 1 times.
✗ Branch 1 (7→38) not taken.
✓ Branch 2 (8→9) taken 1 times.
✗ Branch 3 (8→38) not taken.
|
1 | const CompileTimeValue op0Value = operands.at(0)->getCompileTimeValue(); |
353 |
2/4✓ Branch 0 (9→10) taken 1 times.
✗ Branch 1 (9→38) not taken.
✓ Branch 2 (10→11) taken 1 times.
✗ Branch 3 (10→38) not taken.
|
1 | const CompileTimeValue op1Value = operands.at(1)->getCompileTimeValue(); |
354 |
1/2✗ Branch 0 (11→12) not taken.
✓ Branch 1 (11→13) taken 1 times.
|
1 | if (op == RelationalOp::OP_LESS) |
355 | ✗ | return CompileTimeValue{.boolValue = op0Value.longValue < op1Value.longValue}; | |
356 |
1/2✗ Branch 0 (13→14) not taken.
✓ Branch 1 (13→15) taken 1 times.
|
1 | if (op == RelationalOp::OP_GREATER) |
357 | ✗ | return CompileTimeValue{.boolValue = op0Value.longValue > op1Value.longValue}; | |
358 |
1/2✓ Branch 0 (15→16) taken 1 times.
✗ Branch 1 (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 | 9796 | bool ShiftExprNode::hasCompileTimeValue() const { | |
367 | 19592 | return std::ranges::all_of(operands, [](const AdditiveExprNode *node) { return node->hasCompileTimeValue(); }); | |
368 | } | ||
369 | |||
370 | 97 | CompileTimeValue ShiftExprNode::getCompileTimeValue() const { | |
371 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (3→7) not taken.
|
97 | if (operands.size() == 1) |
372 |
1/2✓ Branch 0 (5→6) taken 97 times.
✗ Branch 1 (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 | 9796 | bool AdditiveExprNode::hasCompileTimeValue() const { | |
392 | 19592 | return std::ranges::all_of(operands, [](const MultiplicativeExprNode *node) { return node->hasCompileTimeValue(); }); | |
393 | } | ||
394 | |||
395 | 97 | CompileTimeValue AdditiveExprNode::getCompileTimeValue() const { | |
396 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (3→7) not taken.
|
97 | if (operands.size() == 1) |
397 |
1/2✓ Branch 0 (5→6) taken 97 times.
✗ Branch 1 (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 | 9796 | bool MultiplicativeExprNode::hasCompileTimeValue() const { | |
417 | 19592 | return std::ranges::all_of(operands, [](const CastExprNode *node) { return node->hasCompileTimeValue(); }); | |
418 | } | ||
419 | |||
420 | 97 | CompileTimeValue MultiplicativeExprNode::getCompileTimeValue() const { | |
421 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (3→7) not taken.
|
97 | if (operands.size() == 1) |
422 |
1/2✓ Branch 0 (5→6) taken 97 times.
✗ Branch 1 (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 | 9796 | bool CastExprNode::hasCompileTimeValue() const { | |
447 |
2/2✓ Branch 0 (2→3) taken 355 times.
✓ Branch 1 (2→5) taken 9441 times.
|
9796 | return isCast ? assignExpr->hasCompileTimeValue() : prefixUnaryExpr->hasCompileTimeValue(); |
448 | } | ||
449 | |||
450 | 97 | CompileTimeValue CastExprNode::getCompileTimeValue() const { | |
451 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 97 times.
|
97 | return isCast ? assignExpr->getCompileTimeValue() : prefixUnaryExpr->getCompileTimeValue(); |
452 | } | ||
453 | |||
454 | 9759 | bool PrefixUnaryExprNode::hasCompileTimeValue() const { // NOLINT(*-no-recursion) | |
455 |
2/2✓ Branch 0 (2→3) taken 9425 times.
✓ Branch 1 (2→5) taken 334 times.
|
9759 | if (postfixUnaryExpr) |
456 | 9425 | return postfixUnaryExpr->hasCompileTimeValue(); | |
457 | |||
458 |
3/4✓ Branch 0 (6→7) taken 326 times.
✓ Branch 1 (6→11) taken 8 times.
✓ Branch 2 (7→8) taken 326 times.
✗ Branch 3 (7→11) not taken.
|
334 | const bool isSupported = op == PrefixUnaryOp::OP_NONE || op == PrefixUnaryOp::OP_MINUS || op == PrefixUnaryOp::OP_PLUS_PLUS || |
459 |
4/6✓ Branch 0 (5→6) taken 334 times.
✗ Branch 1 (5→11) not taken.
✓ Branch 2 (8→9) taken 326 times.
✗ Branch 3 (8→11) not taken.
✓ Branch 4 (9→10) taken 16 times.
✓ Branch 5 (9→11) taken 310 times.
|
684 | op == PrefixUnaryOp::OP_MINUS_MINUS || op == PrefixUnaryOp::OP_NOT || |
460 |
1/2✗ Branch 0 (10→11) not taken.
✓ Branch 1 (10→12) taken 16 times.
|
16 | op == PrefixUnaryOp::OP_BITWISE_NOT; |
461 |
3/4✓ Branch 0 (13→14) taken 318 times.
✓ Branch 1 (13→17) taken 16 times.
✗ Branch 2 (15→16) not taken.
✓ Branch 3 (15→17) taken 318 times.
|
334 | return isSupported && prefixUnaryExpr->hasCompileTimeValue(); |
462 | } | ||
463 | |||
464 | 97 | CompileTimeValue PrefixUnaryExprNode::getCompileTimeValue() const { // NOLINT(*-no-recursion) | |
465 |
1/2✓ Branch 0 (2→3) taken 97 times.
✗ Branch 1 (2→5) not taken.
|
97 | if (postfixUnaryExpr) |
466 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (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 | 9425 | bool PostfixUnaryExprNode::hasCompileTimeValue() const { // NOLINT(*-no-recursion) | |
484 |
2/2✓ Branch 0 (2→3) taken 7299 times.
✓ Branch 1 (2→5) taken 2126 times.
|
9425 | if (atomicExpr) |
485 | 7299 | return atomicExpr->hasCompileTimeValue(); | |
486 | |||
487 | 2126 | const bool isSupported = | |
488 |
3/6✓ Branch 0 (5→6) taken 2126 times.
✗ Branch 1 (5→8) not taken.
✓ Branch 2 (6→7) taken 2126 times.
✗ Branch 3 (6→8) not taken.
✗ Branch 4 (7→8) not taken.
✓ Branch 5 (7→9) taken 2126 times.
|
2126 | op == PostfixUnaryOp::OP_NONE || op == PostfixUnaryOp::OP_PLUS_PLUS || op == PostfixUnaryOp::OP_MINUS_MINUS; |
489 |
1/4✗ Branch 0 (10→11) not taken.
✓ Branch 1 (10→14) taken 2126 times.
✗ Branch 2 (12→13) not taken.
✗ Branch 3 (12→14) not taken.
|
2126 | return isSupported && postfixUnaryExpr->hasCompileTimeValue(); |
490 | } | ||
491 | |||
492 | 97 | CompileTimeValue PostfixUnaryExprNode::getCompileTimeValue() const { // NOLINT(*-no-recursion) | |
493 |
1/2✓ Branch 0 (2→3) taken 97 times.
✗ Branch 1 (2→5) not taken.
|
97 | if (atomicExpr) |
494 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (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 | 8978 | bool FctCallNode::hasReturnValueReceiver() const { | |
511 | 8978 | const ASTNode *node = parent; | |
512 |
2/2✓ Branch 0 (10→3) taken 136447 times.
✓ Branch 1 (10→11) taken 6800 times.
|
143247 | 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 0 (3→4) taken 136447 times.
✗ Branch 1 (3→23) not taken.
✓ Branch 2 (6→7) taken 2178 times.
✓ Branch 3 (6→8) taken 134269 times.
|
136447 | if (node->getChildren().size() > 1) |
515 | 2178 | return true; | |
516 | 134269 | node = node->parent; | |
517 | } | ||
518 | // Also check the condition of the assign expression | ||
519 |
6/12✓ Branch 0 (11→12) taken 6800 times.
✗ Branch 1 (11→24) not taken.
✓ Branch 2 (13→14) taken 6800 times.
✗ Branch 3 (13→16) not taken.
✓ Branch 4 (14→15) taken 6800 times.
✗ Branch 5 (14→24) not taken.
✓ Branch 6 (15→16) taken 6637 times.
✓ Branch 7 (15→17) taken 163 times.
✓ Branch 8 (19→20) taken 6800 times.
✗ Branch 9 (19→21) not taken.
✗ Branch 10 (24→25) not taken.
✗ Branch 11 (24→26) not taken.
|
6800 | 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 | 1498 | void DataTypeNode::setFieldTypeRecursive() { // NOLINT(*-no-recursion) | |
531 | // Set the current node to field type | ||
532 | 1498 | isFieldType = true; | |
533 | // Do the same for all template nodes | ||
534 |
4/4✓ Branch 0 (2→3) taken 633 times.
✓ Branch 1 (2→12) taken 865 times.
✓ Branch 2 (3→4) taken 131 times.
✓ Branch 3 (3→12) taken 502 times.
|
1498 | if (const CustomDataTypeNode *customType = baseDataType->customDataType; customType != nullptr && customType->templateTypeLst) |
535 |
2/2✓ Branch 0 (10→6) taken 174 times.
✓ Branch 1 (10→11) taken 131 times.
|
305 | for (DataTypeNode *templateNode : customType->templateTypeLst->dataTypes) |
536 |
1/2✓ Branch 0 (7→8) taken 174 times.
✗ Branch 1 (7→13) not taken.
|
174 | templateNode->setFieldTypeRecursive(); |
537 | 1498 | } | |
538 | |||
539 | } // namespace spice::compiler | ||
540 |