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 | 763 | std::string ASTNode::getErrorMessage() const { | |
16 | 763 | antlr4::CharStream *inputStream = codeLoc.sourceFile->antlrCtx.inputStream.get(); | |
17 | 763 | const antlr4::misc::Interval &sourceInterval = codeLoc.sourceInterval; | |
18 | 763 | 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 763 times.
✗ Branch 1 (3→77) not taken.
✓ Branch 2 (6→7) taken 19 times.
✓ Branch 3 (6→8) taken 744 times.
|
763 | 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 | 763 | size_t markerIndentation = 0; | |
25 |
2/2✓ Branch 0 (20→9) taken 8176 times.
✓ Branch 1 (20→21) taken 185 times.
|
8361 | for (; markerIndentation < ERROR_MESSAGE_CONTEXT; markerIndentation++) { |
26 | 8176 | extSourceInterval.a--; | |
27 |
9/12✓ Branch 0 (9→10) taken 8161 times.
✓ Branch 1 (9→13) taken 15 times.
✓ Branch 2 (10→11) taken 8161 times.
✗ Branch 3 (10→78) not taken.
✓ Branch 4 (12→13) taken 563 times.
✓ Branch 5 (12→14) taken 7598 times.
✓ Branch 6 (15→16) taken 8161 times.
✓ Branch 7 (15→17) taken 15 times.
✓ Branch 8 (17→18) taken 578 times.
✓ Branch 9 (17→19) taken 7598 times.
✗ Branch 10 (78→79) not taken.
✗ Branch 11 (78→80) not taken.
|
8176 | if (extSourceInterval.a < 0 || inputStream->getText(extSourceInterval).find('\n') != std::string::npos) { |
28 | 578 | extSourceInterval.a++; | |
29 | 578 | break; | |
30 | } | ||
31 | } | ||
32 |
2/2✓ Branch 0 (34→22) taken 2206 times.
✓ Branch 1 (34→35) taken 8 times.
|
2214 | for (size_t suffixContext = 0; suffixContext < ERROR_MESSAGE_CONTEXT; suffixContext++) { |
33 | 2206 | extSourceInterval.b++; | |
34 |
4/6✓ Branch 0 (22→23) taken 2206 times.
✗ Branch 1 (22→82) not taken.
✓ Branch 2 (23→24) taken 2206 times.
✗ Branch 3 (23→27) not taken.
✓ Branch 4 (26→27) taken 755 times.
✓ Branch 5 (26→28) taken 1451 times.
|
4412 | if (static_cast<size_t>(extSourceInterval.b) > inputStream->size() || |
35 |
4/8✓ Branch 0 (24→25) taken 2206 times.
✗ Branch 1 (24→82) not taken.
✓ Branch 2 (29→30) taken 2206 times.
✗ Branch 3 (29→31) not taken.
✓ Branch 4 (31→32) taken 755 times.
✓ Branch 5 (31→33) taken 1451 times.
✗ Branch 6 (82→83) not taken.
✗ Branch 7 (82→84) not taken.
|
4412 | inputStream->getText(extSourceInterval).find('\n') != std::string::npos) { |
36 | 755 | extSourceInterval.b--; | |
37 | 755 | break; | |
38 | } | ||
39 | } | ||
40 | |||
41 | // Trim start | ||
42 |
3/4✓ Branch 0 (37→38) taken 4335 times.
✗ Branch 1 (37→86) not taken.
✓ Branch 2 (40→36) taken 3572 times.
✓ Branch 3 (40→41) taken 763 times.
|
4335 | while (inputStream->getText(extSourceInterval)[0] == ' ') { |
43 | 3572 | extSourceInterval.a++; | |
44 | 3572 | markerIndentation--; | |
45 | } | ||
46 | |||
47 | // Trim end | ||
48 |
3/4✓ Branch 0 (41→42) taken 763 times.
✗ Branch 1 (41→87) not taken.
✓ Branch 2 (45→46) taken 19 times.
✓ Branch 3 (45→47) taken 744 times.
|
763 | if (inputStream->getText(extSourceInterval)[extSourceInterval.length() - 1] == '\n') |
49 | 19 | extSourceInterval.b--; | |
50 | |||
51 | 763 | const std::string lineNumberStr = std::to_string(codeLoc.line); | |
52 | 763 | markerIndentation += lineNumberStr.length() + 2; | |
53 | |||
54 | // Build error message | ||
55 |
1/2✓ Branch 0 (49→50) taken 763 times.
✗ Branch 1 (49→107) not taken.
|
763 | std::stringstream ss; |
56 |
5/10✓ Branch 0 (50→51) taken 763 times.
✗ Branch 1 (50→105) not taken.
✓ Branch 2 (51→52) taken 763 times.
✗ Branch 3 (51→105) not taken.
✓ Branch 4 (52→53) taken 763 times.
✗ Branch 5 (52→90) not taken.
✓ Branch 6 (53→54) taken 763 times.
✗ Branch 7 (53→88) not taken.
✓ Branch 8 (54→55) taken 763 times.
✗ Branch 9 (54→88) not taken.
|
763 | ss << lineNumberStr << " " << inputStream->getText(extSourceInterval) << "\n"; |
57 |
2/4✓ Branch 0 (58→59) taken 763 times.
✗ Branch 1 (58→93) not taken.
✓ Branch 2 (59→60) taken 763 times.
✗ Branch 3 (59→91) not taken.
|
1526 | ss << std::string(markerIndentation, ' '); |
58 |
2/4✓ Branch 0 (67→68) taken 763 times.
✗ Branch 1 (67→99) not taken.
✓ Branch 2 (68→69) taken 763 times.
✗ Branch 3 (68→97) not taken.
|
763 | ss << std::string(std::min(sourceInterval.length(), extSourceInterval.length()), '^'); |
59 |
1/2✓ Branch 0 (71→72) taken 763 times.
✗ Branch 1 (71→105) not taken.
|
1526 | return ss.str(); |
60 | 763 | } | |
61 | |||
62 | 26790 | const StmtLstNode *ASTNode::getNextOuterStmtLst() const { // NOLINT(*-no-recursion) | |
63 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 26790 times.
|
26790 | assert(parent != nullptr && "Could not find next outer statement list"); |
64 |
2/2✓ Branch 0 (5→6) taken 16093 times.
✓ Branch 1 (5→14) taken 10697 times.
|
42883 | return isStmtLst() ? spice_pointer_cast<const StmtLstNode *>(this) : parent->getNextOuterStmtLst(); |
65 | } | ||
66 | |||
67 | 354 | bool MainFctDefNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
68 | 354 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
69 | } | ||
70 | |||
71 | 8954 | bool FctDefBaseNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
72 | 8954 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
73 | } | ||
74 | |||
75 | 46 | CompileTimeValue GlobalVarDefNode::getCompileTimeValue() const { return constant->getCompileTimeValue(); } | |
76 | |||
77 | 850 | 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 |
5/8✓ Branch 0 (2→3) taken 850 times.
✗ Branch 1 (2→15) not taken.
✓ Branch 2 (3→4) taken 1 times.
✓ Branch 3 (3→7) taken 849 times.
✓ Branch 4 (4→5) taken 1 times.
✗ Branch 5 (4→15) not taken.
✗ Branch 6 (5→6) not taken.
✓ Branch 7 (5→7) taken 1 times.
|
850 | const bool loopConditionAlwaysTrue = condAssign->hasCompileTimeValue() && condAssign->getCompileTimeValue().boolValue; |
81 |
1/4✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→12) taken 850 times.
✗ Branch 2 (10→11) not taken.
✗ Branch 3 (10→12) not taken.
|
850 | return loopConditionAlwaysTrue && body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
82 | } | ||
83 | |||
84 | 559 | 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 |
6/8✓ Branch 0 (2→3) taken 559 times.
✗ Branch 1 (2→15) not taken.
✓ Branch 2 (3→4) taken 4 times.
✓ Branch 3 (3→7) taken 555 times.
✓ Branch 4 (4→5) taken 4 times.
✗ Branch 5 (4→15) not taken.
✓ Branch 6 (5→6) taken 3 times.
✓ Branch 7 (5→7) taken 1 times.
|
559 | const bool loopConditionAlwaysTrue = condition->hasCompileTimeValue() && condition->getCompileTimeValue().boolValue; |
88 |
3/4✓ Branch 0 (8→9) taken 3 times.
✓ Branch 1 (8→12) taken 556 times.
✗ Branch 2 (10→11) not taken.
✓ Branch 3 (10→12) taken 3 times.
|
559 | 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 | 2796 | bool IfStmtNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { // NOLINT(misc-no-recursion) | |
97 | // If the condition always evaluates to 'true' the then block must return | ||
98 |
8/10✓ Branch 0 (2→3) taken 2796 times.
✗ Branch 1 (2→33) not taken.
✓ Branch 2 (3→4) taken 12 times.
✓ Branch 3 (3→7) taken 2784 times.
✓ Branch 4 (4→5) taken 12 times.
✗ Branch 5 (4→33) not taken.
✓ Branch 6 (5→6) taken 4 times.
✓ Branch 7 (5→7) taken 8 times.
✓ Branch 8 (8→9) taken 4 times.
✓ Branch 9 (8→11) taken 2792 times.
|
2796 | 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 |
7/10✓ Branch 0 (11→12) taken 2792 times.
✗ Branch 1 (11→34) not taken.
✓ Branch 2 (12→13) taken 8 times.
✓ Branch 3 (12→16) taken 2784 times.
✓ Branch 4 (13→14) taken 8 times.
✗ Branch 5 (13→34) not taken.
✓ Branch 6 (14→15) taken 8 times.
✗ Branch 7 (14→16) not taken.
✓ Branch 8 (17→18) taken 8 times.
✓ Branch 9 (17→24) taken 2784 times.
|
2792 | if (condition->hasCompileTimeValue() && !condition->getCompileTimeValue().boolValue) |
103 |
3/4✓ Branch 0 (18→19) taken 2 times.
✓ Branch 1 (18→22) taken 6 times.
✗ Branch 2 (20→21) not taken.
✓ Branch 3 (20→22) taken 2 times.
|
8 | 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 2085 times.
✓ Branch 1 (25→30) taken 699 times.
✓ Branch 2 (26→27) taken 30 times.
✓ Branch 3 (26→30) taken 2055 times.
|
2814 | return thenBody->returnsOnAllControlPaths(doSetPredecessorsUnreachable) && elseStmt != nullptr && |
107 |
1/2✓ Branch 0 (28→29) taken 30 times.
✗ Branch 1 (28→30) not taken.
|
2814 | elseStmt->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
108 | } | ||
109 | |||
110 | 32 | bool ElseStmtNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { // NOLINT(misc-no-recursion) | |
111 |
2/2✓ Branch 0 (2→3) taken 10 times.
✓ Branch 1 (2→5) taken 22 times.
|
32 | if (isElseIf) |
112 | 10 | return ifStmt->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
113 | 22 | 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 | 14052 | bool StmtLstNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
132 | // An empty statement list does not return at all | ||
133 |
2/2✓ Branch 0 (3→4) taken 29 times.
✓ Branch 1 (3→5) taken 14023 times.
|
14052 | if (statements.empty()) |
134 | 29 | return false; | |
135 | // A statement list returns on all control paths, if the one direct child statement returns on all control paths | ||
136 | 14023 | bool returnsOnAllControlPaths = false; | |
137 |
2/2✓ Branch 0 (18→7) taken 27202 times.
✓ Branch 1 (18→19) taken 14023 times.
|
41225 | for (StmtNode *child : statements) { |
138 |
1/2✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 27202 times.
|
27202 | assert(child != nullptr); |
139 | |||
140 | // Prevent marking instructions as unreachable if doSetPredecessorsUnreachable is set to false | ||
141 |
4/4✓ Branch 0 (10→11) taken 621 times.
✓ Branch 1 (10→13) taken 26581 times.
✓ Branch 2 (11→12) taken 7 times.
✓ Branch 3 (11→13) taken 614 times.
|
27202 | if (returnsOnAllControlPaths && *doSetPredecessorsUnreachable) |
142 | 7 | child->unreachable = true; | |
143 | |||
144 |
3/4✓ Branch 0 (13→14) taken 27202 times.
✗ Branch 1 (13→21) not taken.
✓ Branch 2 (14→15) taken 8650 times.
✓ Branch 3 (14→16) taken 18552 times.
|
27202 | if (child->returnsOnAllControlPaths(doSetPredecessorsUnreachable)) |
145 | 8650 | returnsOnAllControlPaths = true; | |
146 | } | ||
147 | 14023 | return returnsOnAllControlPaths; | |
148 | } | ||
149 | |||
150 | 2314 | 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 2314 times.
|
2314 | assert(ATTR_CONFIGS.contains(key)); |
152 | |||
153 | 2314 | std::vector<const CompileTimeValue *> attributeValues; | |
154 |
2/2✓ Branch 0 (19→7) taken 3648 times.
✓ Branch 1 (19→20) taken 2314 times.
|
5962 | for (const AttrNode *attrNode : attributes) { |
155 | // Skip attributes with different keys | ||
156 |
2/2✓ Branch 0 (9→10) taken 2754 times.
✓ Branch 1 (9→11) taken 894 times.
|
3648 | if (attrNode->key != key) |
157 | 2754 | continue; | |
158 | |||
159 | // Found a matching attribute | ||
160 | 894 | const CompileTimeValue *value = attrNode->getValue(); | |
161 |
2/2✓ Branch 0 (12→13) taken 57 times.
✓ Branch 1 (12→15) taken 837 times.
|
894 | 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 837 times.
✗ Branch 1 (15→23) not taken.
|
837 | attributeValues.push_back(value); |
167 | } | ||
168 | } | ||
169 | |||
170 | 2314 | return attributeValues; | |
171 | ✗ | } | |
172 | |||
173 | 1435 | const CompileTimeValue *AttrLstNode::getAttrValueByName(const std::string &key) const { | |
174 |
1/2✓ Branch 0 (2→3) taken 1435 times.
✗ Branch 1 (2→12) not taken.
|
1435 | const std::vector<const CompileTimeValue *> attrs = getAttrValuesByName(key); |
175 |
2/2✓ Branch 0 (4→5) taken 970 times.
✓ Branch 1 (4→6) taken 465 times.
|
2870 | return attrs.empty() ? nullptr : attrs.back(); |
176 | 1435 | } | |
177 | |||
178 | 1207 | bool AttrLstNode::hasAttr(const std::string &key) const { | |
179 | 3283 | return std::ranges::any_of(attributes, [&](const AttrNode *attr) { return attr->key == key; }); | |
180 | } | ||
181 | |||
182 |
2/2✓ Branch 0 (2→3) taken 837 times.
✓ Branch 1 (2→4) taken 57 times.
|
894 | const CompileTimeValue *AttrNode::getValue() const { return value ? &value->compileTimeValue : nullptr; } |
183 | |||
184 | 633 | 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 |
6/8✓ Branch 0 (2→3) taken 633 times.
✗ Branch 1 (2→11) not taken.
✓ Branch 2 (3→4) taken 4 times.
✓ Branch 3 (3→7) taken 629 times.
✓ Branch 4 (4→5) taken 4 times.
✗ Branch 5 (4→11) not taken.
✓ Branch 6 (5→6) taken 3 times.
✓ Branch 7 (5→7) taken 1 times.
|
633 | return assignExpr->hasCompileTimeValue() && !assignExpr->getCompileTimeValue().boolValue; |
187 | } | ||
188 | |||
189 | 10912 | bool AssignExprNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
190 | // If it's a ternary, do the default thing | ||
191 |
2/2✓ Branch 0 (2→3) taken 6245 times.
✓ Branch 1 (2→5) taken 4667 times.
|
10912 | if (op == AssignOp::OP_NONE) |
192 | 6245 | 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 4662 times.
✓ Branch 1 (5→7) taken 5 times.
|
4667 | const AtomicExprNode* atomicExpr = lhs->postfixUnaryExpr ? lhs->postfixUnaryExpr->atomicExpr : nullptr; |
196 |
6/6✓ Branch 0 (8→9) taken 893 times.
✓ Branch 1 (8→12) taken 3774 times.
✓ Branch 2 (10→11) taken 377 times.
✓ Branch 3 (10→12) taken 516 times.
✓ Branch 4 (13→14) taken 377 times.
✓ Branch 5 (13→15) taken 4290 times.
|
4667 | 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 | 377 | *doSetPredecessorsUnreachable = false; | |
200 | 377 | return true; | |
201 | } | ||
202 | |||
203 | 4290 | return false; | |
204 | } | ||
205 | |||
206 | 8494 | bool TernaryExprNode::hasCompileTimeValue() const { | |
207 |
4/4✓ Branch 0 (2→3) taken 7 times.
✓ Branch 1 (2→5) taken 8487 times.
✓ Branch 2 (4→5) taken 4 times.
✓ Branch 3 (4→6) taken 3 times.
|
8494 | const bool trueExprHasCompileTimeValue = !trueExpr || trueExpr->hasCompileTimeValue(); |
208 |
4/4✓ Branch 0 (7→8) taken 7 times.
✓ Branch 1 (7→10) taken 8487 times.
✓ Branch 2 (9→10) taken 5 times.
✓ Branch 3 (9→11) taken 2 times.
|
8494 | const bool falseExprHasCompileTimeValue = !falseExpr || falseExpr->hasCompileTimeValue(); |
209 |
4/6✓ Branch 0 (13→14) taken 310 times.
✓ Branch 1 (13→17) taken 8184 times.
✓ Branch 2 (14→15) taken 310 times.
✗ Branch 3 (14→17) not taken.
✓ Branch 4 (15→16) taken 310 times.
✗ Branch 5 (15→17) not taken.
|
8494 | return condition->hasCompileTimeValue() && trueExprHasCompileTimeValue && falseExprHasCompileTimeValue; |
210 | } | ||
211 | |||
212 | 80 | CompileTimeValue TernaryExprNode::getCompileTimeValue() const { | |
213 |
2/4✓ Branch 0 (2→3) taken 80 times.
✗ Branch 1 (2→5) not taken.
✓ Branch 2 (3→4) taken 80 times.
✗ Branch 3 (3→5) not taken.
|
80 | if (!trueExpr && !falseExpr) |
214 | 80 | return condition->getCompileTimeValue(); | |
215 | |||
216 | // If the condition has no compile time value, we do not need to evaluate the true and false values | ||
217 | ✗ | if (!condition->hasCompileTimeValue()) | |
218 | ✗ | return {}; | |
219 | |||
220 | // Check if condition always evaluates to 'true' | ||
221 | ✗ | if (condition->getCompileTimeValue().boolValue) { | |
222 | ✗ | const LogicalOrExprNode *trueValue = isShortened ? condition : trueExpr; | |
223 | ✗ | return trueValue->getCompileTimeValue(); | |
224 | } | ||
225 | ✗ | return falseExpr->getCompileTimeValue(); | |
226 | } | ||
227 | |||
228 | 8842 | bool LogicalOrExprNode::hasCompileTimeValue() const { | |
229 | 17686 | return std::ranges::all_of(operands, [](const LogicalAndExprNode *node) { return node->hasCompileTimeValue(); }); | |
230 | } | ||
231 | |||
232 | 80 | CompileTimeValue LogicalOrExprNode::getCompileTimeValue() const { | |
233 |
2/2✓ Branch 0 (3→4) taken 78 times.
✓ Branch 1 (3→6) taken 2 times.
|
80 | if (operands.size() == 1) |
234 | 78 | return operands.front()->getCompileTimeValue(); | |
235 | |||
236 | // Check if one expression evaluates to 'true' | ||
237 |
2/2✓ Branch 0 (17→8) taken 4 times.
✓ Branch 1 (17→18) taken 2 times.
|
6 | for (const LogicalAndExprNode *op : operands) { |
238 |
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()); |
239 | // If one operand evaluates to 'true' the whole expression is 'true' | ||
240 |
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) |
241 | ✗ | return CompileTimeValue{.boolValue = true}; | |
242 | } | ||
243 | |||
244 | // Return 'false' | ||
245 | 2 | return CompileTimeValue{.boolValue = false}; | |
246 | } | ||
247 | |||
248 | 8848 | bool LogicalAndExprNode::hasCompileTimeValue() const { | |
249 | 17698 | return std::ranges::all_of(operands, [](const BitwiseOrExprNode *node) { return node->hasCompileTimeValue(); }); | |
250 | } | ||
251 | |||
252 | 82 | CompileTimeValue LogicalAndExprNode::getCompileTimeValue() const { | |
253 |
2/2✓ Branch 0 (3→4) taken 80 times.
✓ Branch 1 (3→6) taken 2 times.
|
82 | if (operands.size() == 1) |
254 | 80 | return operands.front()->getCompileTimeValue(); | |
255 | |||
256 | // Check if all expressions evaluate to 'true' | ||
257 |
1/2✓ Branch 0 (17→8) taken 4 times.
✗ Branch 1 (17→18) not taken.
|
4 | for (const BitwiseOrExprNode *op : operands) { |
258 |
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()); |
259 | // If one operand evaluates to 'false' the whole expression is 'false' | ||
260 |
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) |
261 | 2 | return CompileTimeValue{.boolValue = false}; | |
262 | } | ||
263 | |||
264 | // Return 'false' | ||
265 | ✗ | return CompileTimeValue{.boolValue = false}; | |
266 | } | ||
267 | |||
268 | 8854 | bool BitwiseOrExprNode::hasCompileTimeValue() const { | |
269 | 17708 | return std::ranges::all_of(operands, [](const BitwiseXorExprNode *node) { return node->hasCompileTimeValue(); }); | |
270 | } | ||
271 | |||
272 | 84 | CompileTimeValue BitwiseOrExprNode::getCompileTimeValue() const { | |
273 |
1/2✓ Branch 0 (3→4) taken 84 times.
✗ Branch 1 (3→7) not taken.
|
84 | if (operands.size() == 1) |
274 |
1/2✓ Branch 0 (5→6) taken 84 times.
✗ Branch 1 (5→23) not taken.
|
84 | return operands.front()->getCompileTimeValue(); |
275 | |||
276 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
277 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
278 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
279 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
280 | ✗ | result.longValue |= opCompileTimeValue.longValue; | |
281 | } | ||
282 | |||
283 | ✗ | return result; | |
284 | } | ||
285 | |||
286 | 8854 | bool BitwiseXorExprNode::hasCompileTimeValue() const { | |
287 | 17708 | return std::ranges::all_of(operands, [](const BitwiseAndExprNode *node) { return node->hasCompileTimeValue(); }); | |
288 | } | ||
289 | |||
290 | 84 | CompileTimeValue BitwiseXorExprNode::getCompileTimeValue() const { | |
291 |
1/2✓ Branch 0 (3→4) taken 84 times.
✗ Branch 1 (3→7) not taken.
|
84 | if (operands.size() == 1) |
292 |
1/2✓ Branch 0 (5→6) taken 84 times.
✗ Branch 1 (5→23) not taken.
|
84 | return operands.front()->getCompileTimeValue(); |
293 | |||
294 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
295 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
296 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
297 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
298 | ✗ | result.longValue ^= opCompileTimeValue.longValue; | |
299 | } | ||
300 | |||
301 | ✗ | return result; | |
302 | } | ||
303 | |||
304 | 8854 | bool BitwiseAndExprNode::hasCompileTimeValue() const { | |
305 | 17708 | return std::ranges::all_of(operands, [](const EqualityExprNode *node) { return node->hasCompileTimeValue(); }); | |
306 | } | ||
307 | |||
308 | 84 | CompileTimeValue BitwiseAndExprNode::getCompileTimeValue() const { | |
309 |
1/2✓ Branch 0 (3→4) taken 84 times.
✗ Branch 1 (3→7) not taken.
|
84 | if (operands.size() == 1) |
310 |
1/2✓ Branch 0 (5→6) taken 84 times.
✗ Branch 1 (5→23) not taken.
|
84 | return operands.front()->getCompileTimeValue(); |
311 | |||
312 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
313 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
314 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
315 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
316 | ✗ | result.longValue &= opCompileTimeValue.longValue; | |
317 | } | ||
318 | |||
319 | ✗ | return result; | |
320 | } | ||
321 | |||
322 | 8854 | bool EqualityExprNode::hasCompileTimeValue() const { | |
323 | 17715 | return std::ranges::all_of(operands, [](const RelationalExprNode *node) { return node->hasCompileTimeValue(); }); | |
324 | } | ||
325 | |||
326 | 84 | CompileTimeValue EqualityExprNode::getCompileTimeValue() const { | |
327 |
2/2✓ Branch 0 (3→4) taken 77 times.
✓ Branch 1 (3→7) taken 7 times.
|
84 | if (operands.size() == 1) |
328 |
1/2✓ Branch 0 (5→6) taken 77 times.
✗ Branch 1 (5→34) not taken.
|
77 | return operands.front()->getCompileTimeValue(); |
329 | |||
330 |
2/4✓ Branch 0 (7→8) taken 7 times.
✗ Branch 1 (7→34) not taken.
✓ Branch 2 (8→9) taken 7 times.
✗ Branch 3 (8→34) not taken.
|
7 | const CompileTimeValue op0Value = operands.at(0)->getCompileTimeValue(); |
331 |
2/4✓ Branch 0 (9→10) taken 7 times.
✗ Branch 1 (9→34) not taken.
✓ Branch 2 (10→11) taken 7 times.
✗ Branch 3 (10→34) not taken.
|
7 | const CompileTimeValue op1Value = operands.at(1)->getCompileTimeValue(); |
332 |
2/2✓ Branch 0 (11→12) taken 2 times.
✓ Branch 1 (11→13) taken 5 times.
|
7 | if (op == EqualityOp::OP_EQUAL) |
333 | 2 | return CompileTimeValue{.boolValue = op0Value.longValue == op1Value.longValue}; | |
334 |
1/2✓ Branch 0 (13→14) taken 5 times.
✗ Branch 1 (13→15) not taken.
|
5 | if (op == EqualityOp::OP_NOT_EQUAL) |
335 | 5 | return CompileTimeValue{.boolValue = op0Value.longValue != op1Value.longValue}; | |
336 | |||
337 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "EqualityExprNode::getCompileTimeValue()"); | |
338 | } | ||
339 | |||
340 | 8861 | bool RelationalExprNode::hasCompileTimeValue() const { | |
341 | 17723 | return std::ranges::all_of(operands, [](const ShiftExprNode *node) { return node->hasCompileTimeValue(); }); | |
342 | } | ||
343 | |||
344 | 91 | CompileTimeValue RelationalExprNode::getCompileTimeValue() const { | |
345 |
2/2✓ Branch 0 (3→4) taken 90 times.
✓ Branch 1 (3→7) taken 1 times.
|
91 | if (operands.size() == 1) |
346 |
1/2✓ Branch 0 (5→6) taken 90 times.
✗ Branch 1 (5→38) not taken.
|
90 | return operands.front()->getCompileTimeValue(); |
347 | |||
348 |
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(); |
349 |
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(); |
350 |
1/2✗ Branch 0 (11→12) not taken.
✓ Branch 1 (11→13) taken 1 times.
|
1 | if (op == RelationalOp::OP_LESS) |
351 | ✗ | return CompileTimeValue{.boolValue = op0Value.longValue < op1Value.longValue}; | |
352 |
1/2✗ Branch 0 (13→14) not taken.
✓ Branch 1 (13→15) taken 1 times.
|
1 | if (op == RelationalOp::OP_GREATER) |
353 | ✗ | return CompileTimeValue{.boolValue = op0Value.longValue > op1Value.longValue}; | |
354 |
1/2✓ Branch 0 (15→16) taken 1 times.
✗ Branch 1 (15→17) not taken.
|
1 | if (op == RelationalOp::OP_LESS_EQUAL) |
355 | 1 | return CompileTimeValue{.boolValue = op0Value.longValue <= op1Value.longValue}; | |
356 | ✗ | if (op == RelationalOp::OP_GREATER_EQUAL) | |
357 | ✗ | return CompileTimeValue{.boolValue = op0Value.longValue >= op1Value.longValue}; | |
358 | |||
359 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "RelationalExprNode::getCompileTimeValue()"); | |
360 | } | ||
361 | |||
362 | 8862 | bool ShiftExprNode::hasCompileTimeValue() const { | |
363 | 17724 | return std::ranges::all_of(operands, [](const AdditiveExprNode *node) { return node->hasCompileTimeValue(); }); | |
364 | } | ||
365 | |||
366 | 92 | CompileTimeValue ShiftExprNode::getCompileTimeValue() const { | |
367 |
1/2✓ Branch 0 (3→4) taken 92 times.
✗ Branch 1 (3→7) not taken.
|
92 | if (operands.size() == 1) |
368 |
1/2✓ Branch 0 (5→6) taken 92 times.
✗ Branch 1 (5→49) not taken.
|
92 | return operands.front()->getCompileTimeValue(); |
369 | |||
370 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
371 | ✗ | OpQueue opQueueCopy = opQueue; | |
372 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
373 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
374 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
375 | ✗ | const ShiftOp op = opQueueCopy.front().first; | |
376 | ✗ | opQueueCopy.pop(); | |
377 | ✗ | if (op == ShiftOp::OP_SHIFT_LEFT) | |
378 | ✗ | result.longValue <<= opCompileTimeValue.longValue; | |
379 | ✗ | else if (op == ShiftOp::OP_SHIFT_RIGHT) | |
380 | ✗ | result.longValue >>= opCompileTimeValue.longValue; | |
381 | else | ||
382 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "ShiftExprNode::getCompileTimeValue()"); | |
383 | } | ||
384 | ✗ | return result; | |
385 | ✗ | } | |
386 | |||
387 | 8862 | bool AdditiveExprNode::hasCompileTimeValue() const { | |
388 | 17724 | return std::ranges::all_of(operands, [](const MultiplicativeExprNode *node) { return node->hasCompileTimeValue(); }); | |
389 | } | ||
390 | |||
391 | 92 | CompileTimeValue AdditiveExprNode::getCompileTimeValue() const { | |
392 |
1/2✓ Branch 0 (3→4) taken 92 times.
✗ Branch 1 (3→7) not taken.
|
92 | if (operands.size() == 1) |
393 |
1/2✓ Branch 0 (5→6) taken 92 times.
✗ Branch 1 (5→49) not taken.
|
92 | return operands.front()->getCompileTimeValue(); |
394 | |||
395 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
396 | ✗ | OpQueue opQueueCopy = opQueue; | |
397 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
398 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
399 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
400 | ✗ | const AdditiveOp op = opQueueCopy.front().first; | |
401 | ✗ | opQueueCopy.pop(); | |
402 | ✗ | if (op == AdditiveOp::OP_PLUS) | |
403 | ✗ | result.longValue += opCompileTimeValue.longValue; | |
404 | ✗ | else if (op == AdditiveOp::OP_MINUS) | |
405 | ✗ | result.longValue -= opCompileTimeValue.longValue; | |
406 | else | ||
407 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "AdditiveExprNode::getCompileTimeValue()"); | |
408 | } | ||
409 | ✗ | return result; | |
410 | ✗ | } | |
411 | |||
412 | 8862 | bool MultiplicativeExprNode::hasCompileTimeValue() const { | |
413 | 17724 | return std::ranges::all_of(operands, [](const CastExprNode *node) { return node->hasCompileTimeValue(); }); | |
414 | } | ||
415 | |||
416 | 92 | CompileTimeValue MultiplicativeExprNode::getCompileTimeValue() const { | |
417 |
1/2✓ Branch 0 (3→4) taken 92 times.
✗ Branch 1 (3→7) not taken.
|
92 | if (operands.size() == 1) |
418 |
1/2✓ Branch 0 (5→6) taken 92 times.
✗ Branch 1 (5→70) not taken.
|
92 | return operands.front()->getCompileTimeValue(); |
419 | |||
420 | ✗ | CompileTimeValue result = operands.front()->getCompileTimeValue(); | |
421 | ✗ | OpQueue opQueueCopy = opQueue; | |
422 | ✗ | for (size_t i = 1; i < operands.size(); i++) { | |
423 | ✗ | assert(operands.at(i)->hasCompileTimeValue()); | |
424 | ✗ | const CompileTimeValue opCompileTimeValue = operands.at(i)->getCompileTimeValue(); | |
425 | ✗ | const MultiplicativeOp op = opQueueCopy.front().first; | |
426 | ✗ | opQueueCopy.pop(); | |
427 | ✗ | if (op == MultiplicativeOp::OP_MUL) { | |
428 | ✗ | result.longValue *= opCompileTimeValue.longValue; | |
429 | ✗ | } else if (op == MultiplicativeOp::OP_DIV) { | |
430 | ✗ | if (opCompileTimeValue.longValue == 0) | |
431 | ✗ | throw SemanticError(operands.at(i), DIVISION_BY_ZERO, "Dividing by zero is not allowed."); | |
432 | ✗ | result.longValue /= opCompileTimeValue.longValue; | |
433 | ✗ | } else if (op == MultiplicativeOp::OP_REM) { | |
434 | ✗ | result.longValue %= opCompileTimeValue.longValue; | |
435 | } else { | ||
436 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "MultiplicativeExprNode::getCompileTimeValue()"); | |
437 | } | ||
438 | } | ||
439 | ✗ | return result; | |
440 | ✗ | } | |
441 | |||
442 | 8862 | bool CastExprNode::hasCompileTimeValue() const { return prefixUnaryExpr->hasCompileTimeValue(); } | |
443 | |||
444 | 92 | CompileTimeValue CastExprNode::getCompileTimeValue() const { return prefixUnaryExpr->getCompileTimeValue(); } | |
445 | |||
446 | 9134 | bool PrefixUnaryExprNode::hasCompileTimeValue() const { // NOLINT(*-no-recursion) | |
447 |
2/2✓ Branch 0 (2→3) taken 8838 times.
✓ Branch 1 (2→5) taken 296 times.
|
9134 | if (postfixUnaryExpr) |
448 | 8838 | return postfixUnaryExpr->hasCompileTimeValue(); | |
449 | |||
450 |
3/4✓ Branch 0 (6→7) taken 288 times.
✓ Branch 1 (6→11) taken 8 times.
✓ Branch 2 (7→8) taken 288 times.
✗ Branch 3 (7→11) not taken.
|
296 | const bool isSupported = op == PrefixUnaryOp::OP_NONE || op == PrefixUnaryOp::OP_MINUS || op == PrefixUnaryOp::OP_PLUS_PLUS || |
451 |
4/6✓ Branch 0 (5→6) taken 296 times.
✗ Branch 1 (5→11) not taken.
✓ Branch 2 (8→9) taken 288 times.
✗ Branch 3 (8→11) not taken.
✓ Branch 4 (9→10) taken 24 times.
✓ Branch 5 (9→11) taken 264 times.
|
616 | op == PrefixUnaryOp::OP_MINUS_MINUS || op == PrefixUnaryOp::OP_NOT || |
452 |
1/2✗ Branch 0 (10→11) not taken.
✓ Branch 1 (10→12) taken 24 times.
|
24 | op == PrefixUnaryOp::OP_BITWISE_NOT; |
453 |
3/4✓ Branch 0 (13→14) taken 272 times.
✓ Branch 1 (13→17) taken 24 times.
✗ Branch 2 (15→16) not taken.
✓ Branch 3 (15→17) taken 272 times.
|
296 | return isSupported && prefixUnaryExpr->hasCompileTimeValue(); |
454 | } | ||
455 | |||
456 | 92 | CompileTimeValue PrefixUnaryExprNode::getCompileTimeValue() const { // NOLINT(*-no-recursion) | |
457 |
1/2✓ Branch 0 (2→3) taken 92 times.
✗ Branch 1 (2→5) not taken.
|
92 | if (postfixUnaryExpr) |
458 |
1/2✓ Branch 0 (3→4) taken 92 times.
✗ Branch 1 (3→35) not taken.
|
92 | return postfixUnaryExpr->getCompileTimeValue(); |
459 | |||
460 | ✗ | CompileTimeValue opValue = prefixUnaryExpr->getCompileTimeValue(); | |
461 | ✗ | if (op == PrefixUnaryOp::OP_MINUS) | |
462 | ✗ | return CompileTimeValue{.longValue = -opValue.longValue}; | |
463 | ✗ | if (op == PrefixUnaryOp::OP_PLUS_PLUS) | |
464 | ✗ | return CompileTimeValue{.longValue = ++opValue.longValue}; | |
465 | ✗ | if (op == PrefixUnaryOp::OP_MINUS_MINUS) | |
466 | ✗ | return CompileTimeValue{.longValue = --opValue.longValue}; | |
467 | ✗ | if (op == PrefixUnaryOp::OP_NOT) | |
468 | ✗ | return CompileTimeValue{.boolValue = !opValue.boolValue}; | |
469 | ✗ | if (op == PrefixUnaryOp::OP_BITWISE_NOT) | |
470 | ✗ | return CompileTimeValue{.longValue = ~opValue.longValue}; | |
471 | |||
472 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "PrefixUnaryExprNode::getCompileTimeValue()"); | |
473 | } | ||
474 | |||
475 | 8838 | bool PostfixUnaryExprNode::hasCompileTimeValue() const { // NOLINT(*-no-recursion) | |
476 |
2/2✓ Branch 0 (2→3) taken 6914 times.
✓ Branch 1 (2→5) taken 1924 times.
|
8838 | if (atomicExpr) |
477 | 6914 | return atomicExpr->hasCompileTimeValue(); | |
478 | |||
479 | 1924 | const bool isSupported = | |
480 |
3/6✓ Branch 0 (5→6) taken 1924 times.
✗ Branch 1 (5→8) not taken.
✓ Branch 2 (6→7) taken 1924 times.
✗ Branch 3 (6→8) not taken.
✗ Branch 4 (7→8) not taken.
✓ Branch 5 (7→9) taken 1924 times.
|
1924 | op == PostfixUnaryOp::OP_NONE || op == PostfixUnaryOp::OP_PLUS_PLUS || op == PostfixUnaryOp::OP_MINUS_MINUS; |
481 |
1/4✗ Branch 0 (10→11) not taken.
✓ Branch 1 (10→14) taken 1924 times.
✗ Branch 2 (12→13) not taken.
✗ Branch 3 (12→14) not taken.
|
1924 | return isSupported && postfixUnaryExpr->hasCompileTimeValue(); |
482 | } | ||
483 | |||
484 | 92 | CompileTimeValue PostfixUnaryExprNode::getCompileTimeValue() const { // NOLINT(*-no-recursion) | |
485 |
1/2✓ Branch 0 (2→3) taken 92 times.
✗ Branch 1 (2→5) not taken.
|
92 | if (atomicExpr) |
486 |
1/2✓ Branch 0 (3→4) taken 92 times.
✗ Branch 1 (3→29) not taken.
|
92 | return atomicExpr->getCompileTimeValue(); |
487 | |||
488 | ✗ | CompileTimeValue opValue = postfixUnaryExpr->getCompileTimeValue(); | |
489 | ✗ | if (op == PostfixUnaryOp::OP_PLUS_PLUS) | |
490 | ✗ | return CompileTimeValue{.longValue = opValue.longValue++}; | |
491 | ✗ | if (op == PostfixUnaryOp::OP_MINUS_MINUS) | |
492 | ✗ | return CompileTimeValue{.longValue = opValue.longValue--}; | |
493 | |||
494 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "PostfixUnaryExprNode::getCompileTimeValue()"); | |
495 | } | ||
496 | |||
497 | /** | ||
498 | * Check if right above the closest assign expression ancestor is a statement node | ||
499 | * | ||
500 | * @return Has return value receiver or not | ||
501 | */ | ||
502 | 8481 | bool FctCallNode::hasReturnValueReceiver() const { | |
503 | 8481 | const ASTNode *node = parent; | |
504 |
2/2✓ Branch 0 (10→3) taken 126928 times.
✓ Branch 1 (10→11) taken 6231 times.
|
133159 | while (!node->isAssignExpr()) { |
505 | // As soon as we have a node with more than one child, we know that the return value is used | ||
506 |
3/4✓ Branch 0 (3→4) taken 126928 times.
✗ Branch 1 (3→23) not taken.
✓ Branch 2 (6→7) taken 2250 times.
✓ Branch 3 (6→8) taken 124678 times.
|
126928 | if (node->getChildren().size() > 1) |
507 | 2250 | return true; | |
508 | 124678 | node = node->parent; | |
509 | } | ||
510 | // Also check the condition of the assign expression | ||
511 |
6/12✓ Branch 0 (11→12) taken 6231 times.
✗ Branch 1 (11→24) not taken.
✓ Branch 2 (13→14) taken 6231 times.
✗ Branch 3 (13→16) not taken.
✓ Branch 4 (14→15) taken 6231 times.
✗ Branch 5 (14→24) not taken.
✓ Branch 6 (15→16) taken 6090 times.
✓ Branch 7 (15→17) taken 141 times.
✓ Branch 8 (19→20) taken 6231 times.
✗ Branch 9 (19→21) not taken.
✗ Branch 10 (24→25) not taken.
✗ Branch 11 (24→26) not taken.
|
6231 | return node->getChildren().size() > 1 || !node->parent->isExprStmt(); |
512 | } | ||
513 | |||
514 | 12 | bool LambdaFuncNode::returnsOnAllControlPaths(bool *overrideUnreachable) const { | |
515 | 12 | return body->returnsOnAllControlPaths(overrideUnreachable); | |
516 | } | ||
517 | |||
518 | 38 | bool LambdaProcNode::returnsOnAllControlPaths(bool *overrideUnreachable) const { | |
519 | 38 | return body->returnsOnAllControlPaths(overrideUnreachable); | |
520 | } | ||
521 | |||
522 | 1429 | void DataTypeNode::setFieldTypeRecursive() { // NOLINT(*-no-recursion) | |
523 | // Set the current node to field type | ||
524 | 1429 | isFieldType = true; | |
525 | // Do the same for all template nodes | ||
526 |
4/4✓ Branch 0 (2→3) taken 591 times.
✓ Branch 1 (2→12) taken 838 times.
✓ Branch 2 (3→4) taken 119 times.
✓ Branch 3 (3→12) taken 472 times.
|
1429 | if (const CustomDataTypeNode *customType = baseDataType->customDataType; customType != nullptr && customType->templateTypeLst) |
527 |
2/2✓ Branch 0 (10→6) taken 157 times.
✓ Branch 1 (10→11) taken 119 times.
|
276 | for (DataTypeNode *templateNode : customType->templateTypeLst->dataTypes) |
528 |
1/2✓ Branch 0 (7→8) taken 157 times.
✗ Branch 1 (7→13) not taken.
|
157 | templateNode->setFieldTypeRecursive(); |
529 | 1429 | } | |
530 | |||
531 | } // namespace spice::compiler | ||
532 |