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 | 784 | std::string ASTNode::getErrorMessage() const { | |
16 | 784 | antlr4::CharStream *inputStream = codeLoc.sourceFile->antlrCtx.inputStream.get(); | |
17 | 784 | const antlr4::misc::Interval &sourceInterval = codeLoc.sourceInterval; | |
18 | 784 | 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 784 times.
✗ Branch 1 (3→77) not taken.
✓ Branch 2 (6→7) taken 19 times.
✓ Branch 3 (6→8) taken 765 times.
|
784 | 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 | 784 | size_t markerIndentation = 0; | |
25 |
2/2✓ Branch 0 (20→9) taken 8397 times.
✓ Branch 1 (20→21) taken 189 times.
|
8586 | for (; markerIndentation < ERROR_MESSAGE_CONTEXT; markerIndentation++) { |
26 | 8397 | extSourceInterval.a--; | |
27 |
9/12✓ Branch 0 (9→10) taken 8382 times.
✓ Branch 1 (9→13) taken 15 times.
✓ Branch 2 (10→11) taken 8382 times.
✗ Branch 3 (10→78) not taken.
✓ Branch 4 (12→13) taken 580 times.
✓ Branch 5 (12→14) taken 7802 times.
✓ Branch 6 (15→16) taken 8382 times.
✓ Branch 7 (15→17) taken 15 times.
✓ Branch 8 (17→18) taken 595 times.
✓ Branch 9 (17→19) taken 7802 times.
✗ Branch 10 (78→79) not taken.
✗ Branch 11 (78→80) not taken.
|
8397 | if (extSourceInterval.a < 0 || inputStream->getText(extSourceInterval).find('\n') != std::string::npos) { |
28 | 595 | extSourceInterval.a++; | |
29 | 595 | break; | |
30 | } | ||
31 | } | ||
32 |
2/2✓ Branch 0 (34→22) taken 2255 times.
✓ Branch 1 (34→35) taken 8 times.
|
2263 | for (size_t suffixContext = 0; suffixContext < ERROR_MESSAGE_CONTEXT; suffixContext++) { |
33 | 2255 | extSourceInterval.b++; | |
34 |
4/6✓ Branch 0 (22→23) taken 2255 times.
✗ Branch 1 (22→82) not taken.
✓ Branch 2 (23→24) taken 2255 times.
✗ Branch 3 (23→27) not taken.
✓ Branch 4 (26→27) taken 776 times.
✓ Branch 5 (26→28) taken 1479 times.
|
4510 | if (static_cast<size_t>(extSourceInterval.b) > inputStream->size() || |
35 |
4/8✓ Branch 0 (24→25) taken 2255 times.
✗ Branch 1 (24→82) not taken.
✓ Branch 2 (29→30) taken 2255 times.
✗ Branch 3 (29→31) not taken.
✓ Branch 4 (31→32) taken 776 times.
✓ Branch 5 (31→33) taken 1479 times.
✗ Branch 6 (82→83) not taken.
✗ Branch 7 (82→84) not taken.
|
4510 | inputStream->getText(extSourceInterval).find('\n') != std::string::npos) { |
36 | 776 | extSourceInterval.b--; | |
37 | 776 | break; | |
38 | } | ||
39 | } | ||
40 | |||
41 | // Trim start | ||
42 |
3/4✓ Branch 0 (37→38) taken 4476 times.
✗ Branch 1 (37→86) not taken.
✓ Branch 2 (40→36) taken 3692 times.
✓ Branch 3 (40→41) taken 784 times.
|
4476 | while (inputStream->getText(extSourceInterval)[0] == ' ') { |
43 | 3692 | extSourceInterval.a++; | |
44 | 3692 | markerIndentation--; | |
45 | } | ||
46 | |||
47 | // Trim end | ||
48 |
3/4✓ Branch 0 (41→42) taken 784 times.
✗ Branch 1 (41→87) not taken.
✓ Branch 2 (45→46) taken 19 times.
✓ Branch 3 (45→47) taken 765 times.
|
784 | if (inputStream->getText(extSourceInterval)[extSourceInterval.length() - 1] == '\n') |
49 | 19 | extSourceInterval.b--; | |
50 | |||
51 | 784 | const std::string lineNumberStr = std::to_string(codeLoc.line); | |
52 | 784 | markerIndentation += lineNumberStr.length() + 2; | |
53 | |||
54 | // Build error message | ||
55 |
1/2✓ Branch 0 (49→50) taken 784 times.
✗ Branch 1 (49→107) not taken.
|
784 | std::stringstream ss; |
56 |
5/10✓ Branch 0 (50→51) taken 784 times.
✗ Branch 1 (50→105) not taken.
✓ Branch 2 (51→52) taken 784 times.
✗ Branch 3 (51→105) not taken.
✓ Branch 4 (52→53) taken 784 times.
✗ Branch 5 (52→90) not taken.
✓ Branch 6 (53→54) taken 784 times.
✗ Branch 7 (53→88) not taken.
✓ Branch 8 (54→55) taken 784 times.
✗ Branch 9 (54→88) not taken.
|
784 | ss << lineNumberStr << " " << inputStream->getText(extSourceInterval) << "\n"; |
57 |
2/4✓ Branch 0 (58→59) taken 784 times.
✗ Branch 1 (58→93) not taken.
✓ Branch 2 (59→60) taken 784 times.
✗ Branch 3 (59→91) not taken.
|
1568 | ss << std::string(markerIndentation, ' '); |
58 |
2/4✓ Branch 0 (67→68) taken 784 times.
✗ Branch 1 (67→99) not taken.
✓ Branch 2 (68→69) taken 784 times.
✗ Branch 3 (68→97) not taken.
|
784 | ss << std::string(std::min(sourceInterval.length(), extSourceInterval.length()), '^'); |
59 |
1/2✓ Branch 0 (71→72) taken 784 times.
✗ Branch 1 (71→105) not taken.
|
1568 | return ss.str(); |
60 | 784 | } | |
61 | |||
62 | 27728 | const StmtLstNode *ASTNode::getNextOuterStmtLst() const { // NOLINT(*-no-recursion) | |
63 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 27728 times.
|
27728 | assert(parent != nullptr && "Could not find next outer statement list"); |
64 |
2/2✓ Branch 0 (5→6) taken 16632 times.
✓ Branch 1 (5→14) taken 11096 times.
|
44360 | return isStmtLst() ? spice_pointer_cast<const StmtLstNode *>(this) : parent->getNextOuterStmtLst(); |
65 | } | ||
66 | |||
67 | 360 | bool MainFctDefNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
68 | 360 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
69 | } | ||
70 | |||
71 | 9625 | bool FctDefBaseNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
72 | 9625 | return body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); | |
73 | } | ||
74 | |||
75 | 46 | CompileTimeValue GlobalVarDefNode::getCompileTimeValue() const { return constant->getCompileTimeValue(); } | |
76 | |||
77 | 1051 | 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 1050 times.
✗ Branch 2 (5→6) not taken.
✓ Branch 3 (5→7) taken 1 times.
|
1051 | const bool loopConditionAlwaysTrue = condAssign->hasCompileTimeValue() && condAssign->getCompileTimeValue().boolValue; |
81 |
1/4✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→12) taken 1051 times.
✗ Branch 2 (10→11) not taken.
✗ Branch 3 (10→12) not taken.
|
1051 | return loopConditionAlwaysTrue && body->returnsOnAllControlPaths(doSetPredecessorsUnreachable); |
82 | } | ||
83 | |||
84 | 666 | 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 662 times.
✓ Branch 2 (5→6) taken 4 times.
✗ Branch 3 (5→7) not taken.
|
666 | const bool loopConditionAlwaysTrue = condition->hasCompileTimeValue() && condition->getCompileTimeValue().boolValue; |
88 |
3/4✓ Branch 0 (8→9) taken 4 times.
✓ Branch 1 (8→12) taken 662 times.
✗ Branch 2 (10→11) not taken.
✓ Branch 3 (10→12) taken 4 times.
|
666 | 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 | 2991 | 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 2978 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 2987 times.
|
2991 | 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 2978 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 2978 times.
|
2987 | 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 2246 times.
✓ Branch 1 (25→30) taken 732 times.
✓ Branch 2 (26→27) taken 30 times.
✓ Branch 3 (26→30) taken 2216 times.
|
3008 | return thenBody->returnsOnAllControlPaths(doSetPredecessorsUnreachable) && elseStmt != nullptr && |
107 |
1/2✓ Branch 0 (28→29) taken 30 times.
✗ Branch 1 (28→30) not taken.
|
3008 | 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 | 15227 | 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 15197 times.
|
15227 | 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 | 15197 | bool returnsOnAllControlPaths = false; | |
137 |
2/2✓ Branch 0 (18→7) taken 29417 times.
✓ Branch 1 (18→19) taken 15197 times.
|
44614 | for (StmtNode *child : statements) { |
138 |
1/2✗ Branch 0 (8→9) not taken.
✓ Branch 1 (8→10) taken 29417 times.
|
29417 | assert(child != nullptr); |
139 | |||
140 | // Prevent marking instructions as unreachable if doSetPredecessorsUnreachable is set to false | ||
141 |
4/4✓ Branch 0 (10→11) taken 655 times.
✓ Branch 1 (10→13) taken 28762 times.
✓ Branch 2 (11→12) taken 7 times.
✓ Branch 3 (11→13) taken 648 times.
|
29417 | if (returnsOnAllControlPaths && *doSetPredecessorsUnreachable) |
142 | 7 | child->unreachable = true; | |
143 | |||
144 |
3/4✓ Branch 0 (13→14) taken 29417 times.
✗ Branch 1 (13→21) not taken.
✓ Branch 2 (14→15) taken 9045 times.
✓ Branch 3 (14→16) taken 20372 times.
|
29417 | if (child->returnsOnAllControlPaths(doSetPredecessorsUnreachable)) |
145 | 9045 | returnsOnAllControlPaths = true; | |
146 | } | ||
147 | 15197 | return returnsOnAllControlPaths; | |
148 | } | ||
149 | |||
150 | 2267 | 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 2267 times.
|
2267 | assert(ATTR_CONFIGS.contains(key)); |
152 | |||
153 | 2267 | std::vector<const CompileTimeValue *> attributeValues; | |
154 |
2/2✓ Branch 0 (19→7) taken 3601 times.
✓ Branch 1 (19→20) taken 2267 times.
|
5868 | for (const AttrNode *attrNode : attributes) { |
155 | // Skip attributes with different keys | ||
156 |
2/2✓ Branch 0 (9→10) taken 2697 times.
✓ Branch 1 (9→11) taken 904 times.
|
3601 | if (attrNode->key != key) |
157 | 2697 | continue; | |
158 | |||
159 | // Found a matching attribute | ||
160 | 904 | const CompileTimeValue *value = attrNode->getValue(); | |
161 |
2/2✓ Branch 0 (12→13) taken 57 times.
✓ Branch 1 (12→15) taken 847 times.
|
904 | 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 847 times.
✗ Branch 1 (15→23) not taken.
|
847 | attributeValues.push_back(value); |
167 | } | ||
168 | } | ||
169 | |||
170 | 2267 | return attributeValues; | |
171 | ✗ | } | |
172 | |||
173 | 1367 | const CompileTimeValue *AttrLstNode::getAttrValueByName(const std::string &key) const { | |
174 |
1/2✓ Branch 0 (2→3) taken 1367 times.
✗ Branch 1 (2→12) not taken.
|
1367 | const std::vector<const CompileTimeValue *> attrs = getAttrValuesByName(key); |
175 |
2/2✓ Branch 0 (4→5) taken 892 times.
✓ Branch 1 (4→6) taken 475 times.
|
2734 | return attrs.empty() ? nullptr : attrs.back(); |
176 | 1367 | } | |
177 | |||
178 | 1197 | bool AttrLstNode::hasAttr(const std::string &key) const { | |
179 | 3263 | return std::ranges::any_of(attributes, [&](const AttrNode *attr) { return attr->key == key; }); | |
180 | } | ||
181 | |||
182 |
2/2✓ Branch 0 (2→3) taken 847 times.
✓ Branch 1 (2→4) taken 57 times.
|
904 | const CompileTimeValue *AttrNode::getValue() const { return value ? &value->compileTimeValue : nullptr; } |
183 | |||
184 | 661 | 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 657 times.
✓ Branch 2 (5→6) taken 3 times.
✓ Branch 3 (5→7) taken 1 times.
|
661 | return assignExpr->hasCompileTimeValue() && !assignExpr->getCompileTimeValue().boolValue; |
187 | } | ||
188 | |||
189 | 11898 | bool AssignExprNode::returnsOnAllControlPaths(bool *doSetPredecessorsUnreachable) const { | |
190 | // If it's a ternary, do the default thing | ||
191 |
2/2✓ Branch 0 (2→3) taken 6899 times.
✓ Branch 1 (2→5) taken 4999 times.
|
11898 | if (op == AssignOp::OP_NONE) |
192 | 6899 | 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 4994 times.
✓ Branch 1 (5→7) taken 5 times.
|
4999 | const AtomicExprNode *atomicExpr = lhs->postfixUnaryExpr ? lhs->postfixUnaryExpr->atomicExpr : nullptr; |
196 |
6/6✓ Branch 0 (8→9) taken 936 times.
✓ Branch 1 (8→12) taken 4063 times.
✓ Branch 2 (10→11) taken 397 times.
✓ Branch 3 (10→12) taken 539 times.
✓ Branch 4 (13→14) taken 397 times.
✓ Branch 5 (13→15) taken 4602 times.
|
4999 | 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 | 397 | *doSetPredecessorsUnreachable = false; | |
200 | 397 | return true; | |
201 | } | ||
202 | |||
203 | 4602 | return false; | |
204 | } | ||
205 | |||
206 | 9245 | bool TernaryExprNode::hasCompileTimeValue() const { | |
207 |
4/4✓ Branch 0 (2→3) taken 7 times.
✓ Branch 1 (2→5) taken 9238 times.
✓ Branch 2 (4→5) taken 4 times.
✓ Branch 3 (4→6) taken 3 times.
|
9245 | const bool trueExprHasCompileTimeValue = !trueExpr || trueExpr->hasCompileTimeValue(); |
208 |
4/4✓ Branch 0 (7→8) taken 7 times.
✓ Branch 1 (7→10) taken 9238 times.
✓ Branch 2 (9→10) taken 5 times.
✓ Branch 3 (9→11) taken 2 times.
|
9245 | const bool falseExprHasCompileTimeValue = !falseExpr || falseExpr->hasCompileTimeValue(); |
209 |
4/6✓ Branch 0 (13→14) taken 211 times.
✓ Branch 1 (13→17) taken 9034 times.
✓ Branch 2 (14→15) taken 211 times.
✗ Branch 3 (14→17) not taken.
✓ Branch 4 (15→16) taken 211 times.
✗ Branch 5 (15→17) not taken.
|
9245 | return condition->hasCompileTimeValue() && trueExprHasCompileTimeValue && falseExprHasCompileTimeValue; |
210 | } | ||
211 | |||
212 | 82 | CompileTimeValue TernaryExprNode::getCompileTimeValue() const { | |
213 |
2/4✓ Branch 0 (2→3) taken 82 times.
✗ Branch 1 (2→5) not taken.
✓ Branch 2 (3→4) taken 82 times.
✗ Branch 3 (3→5) not taken.
|
82 | if (!trueExpr && !falseExpr) |
214 | 82 | 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 | 9646 | bool LogicalOrExprNode::hasCompileTimeValue() const { | |
229 | 19294 | return std::ranges::all_of(operands, [](const LogicalAndExprNode *node) { return node->hasCompileTimeValue(); }); | |
230 | } | ||
231 | |||
232 | 82 | CompileTimeValue LogicalOrExprNode::getCompileTimeValue() const { | |
233 |
2/2✓ Branch 0 (3→4) taken 80 times.
✓ Branch 1 (3→6) taken 2 times.
|
82 | if (operands.size() == 1) |
234 | 80 | 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 | 9652 | bool LogicalAndExprNode::hasCompileTimeValue() const { | |
249 | 19306 | return std::ranges::all_of(operands, [](const BitwiseOrExprNode *node) { return node->hasCompileTimeValue(); }); | |
250 | } | ||
251 | |||
252 | 84 | CompileTimeValue LogicalAndExprNode::getCompileTimeValue() const { | |
253 |
2/2✓ Branch 0 (3→4) taken 82 times.
✓ Branch 1 (3→6) taken 2 times.
|
84 | if (operands.size() == 1) |
254 | 82 | 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 | 9658 | bool BitwiseOrExprNode::hasCompileTimeValue() const { | |
269 | 19316 | return std::ranges::all_of(operands, [](const BitwiseXorExprNode *node) { return node->hasCompileTimeValue(); }); | |
270 | } | ||
271 | |||
272 | 86 | CompileTimeValue BitwiseOrExprNode::getCompileTimeValue() const { | |
273 |
1/2✓ Branch 0 (3→4) taken 86 times.
✗ Branch 1 (3→7) not taken.
|
86 | if (operands.size() == 1) |
274 |
1/2✓ Branch 0 (5→6) taken 86 times.
✗ Branch 1 (5→23) not taken.
|
86 | 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 | 9658 | bool BitwiseXorExprNode::hasCompileTimeValue() const { | |
287 | 19316 | return std::ranges::all_of(operands, [](const BitwiseAndExprNode *node) { return node->hasCompileTimeValue(); }); | |
288 | } | ||
289 | |||
290 | 86 | CompileTimeValue BitwiseXorExprNode::getCompileTimeValue() const { | |
291 |
1/2✓ Branch 0 (3→4) taken 86 times.
✗ Branch 1 (3→7) not taken.
|
86 | if (operands.size() == 1) |
292 |
1/2✓ Branch 0 (5→6) taken 86 times.
✗ Branch 1 (5→23) not taken.
|
86 | 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 | 9658 | bool BitwiseAndExprNode::hasCompileTimeValue() const { | |
305 | 19316 | return std::ranges::all_of(operands, [](const EqualityExprNode *node) { return node->hasCompileTimeValue(); }); | |
306 | } | ||
307 | |||
308 | 86 | CompileTimeValue BitwiseAndExprNode::getCompileTimeValue() const { | |
309 |
1/2✓ Branch 0 (3→4) taken 86 times.
✗ Branch 1 (3→7) not taken.
|
86 | if (operands.size() == 1) |
310 |
1/2✓ Branch 0 (5→6) taken 86 times.
✗ Branch 1 (5→23) not taken.
|
86 | 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 | 9658 | bool EqualityExprNode::hasCompileTimeValue() const { | |
323 | 19326 | return std::ranges::all_of(operands, [](const RelationalExprNode *node) { return node->hasCompileTimeValue(); }); | |
324 | } | ||
325 | |||
326 | 86 | CompileTimeValue EqualityExprNode::getCompileTimeValue() const { | |
327 |
2/2✓ Branch 0 (3→4) taken 76 times.
✓ Branch 1 (3→7) taken 10 times.
|
86 | if (operands.size() == 1) |
328 |
1/2✓ Branch 0 (5→6) taken 76 times.
✗ Branch 1 (5→34) not taken.
|
76 | return operands.front()->getCompileTimeValue(); |
329 | |||
330 |
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(); |
331 |
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(); |
332 |
2/2✓ Branch 0 (11→12) taken 6 times.
✓ Branch 1 (11→13) taken 4 times.
|
10 | if (op == EqualityOp::OP_EQUAL) |
333 | 6 | return CompileTimeValue{.boolValue = op0Value.longValue == op1Value.longValue}; | |
334 |
1/2✓ Branch 0 (13→14) taken 4 times.
✗ Branch 1 (13→15) not taken.
|
4 | if (op == EqualityOp::OP_NOT_EQUAL) |
335 | 4 | return CompileTimeValue{.boolValue = op0Value.longValue != op1Value.longValue}; | |
336 | |||
337 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "EqualityExprNode::getCompileTimeValue()"); | |
338 | } | ||
339 | |||
340 | 9668 | bool RelationalExprNode::hasCompileTimeValue() const { | |
341 | 19337 | return std::ranges::all_of(operands, [](const ShiftExprNode *node) { return node->hasCompileTimeValue(); }); | |
342 | } | ||
343 | |||
344 | 96 | CompileTimeValue RelationalExprNode::getCompileTimeValue() const { | |
345 |
2/2✓ Branch 0 (3→4) taken 95 times.
✓ Branch 1 (3→7) taken 1 times.
|
96 | if (operands.size() == 1) |
346 |
1/2✓ Branch 0 (5→6) taken 95 times.
✗ Branch 1 (5→38) not taken.
|
95 | 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 | 9669 | bool ShiftExprNode::hasCompileTimeValue() const { | |
363 | 19338 | return std::ranges::all_of(operands, [](const AdditiveExprNode *node) { return node->hasCompileTimeValue(); }); | |
364 | } | ||
365 | |||
366 | 97 | CompileTimeValue ShiftExprNode::getCompileTimeValue() const { | |
367 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (3→7) not taken.
|
97 | if (operands.size() == 1) |
368 |
1/2✓ Branch 0 (5→6) taken 97 times.
✗ Branch 1 (5→49) not taken.
|
97 | 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 | 9669 | bool AdditiveExprNode::hasCompileTimeValue() const { | |
388 | 19338 | return std::ranges::all_of(operands, [](const MultiplicativeExprNode *node) { return node->hasCompileTimeValue(); }); | |
389 | } | ||
390 | |||
391 | 97 | CompileTimeValue AdditiveExprNode::getCompileTimeValue() const { | |
392 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (3→7) not taken.
|
97 | if (operands.size() == 1) |
393 |
1/2✓ Branch 0 (5→6) taken 97 times.
✗ Branch 1 (5→49) not taken.
|
97 | 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 | 9669 | bool MultiplicativeExprNode::hasCompileTimeValue() const { | |
413 | 19338 | return std::ranges::all_of(operands, [](const CastExprNode *node) { return node->hasCompileTimeValue(); }); | |
414 | } | ||
415 | |||
416 | 97 | CompileTimeValue MultiplicativeExprNode::getCompileTimeValue() const { | |
417 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (3→7) not taken.
|
97 | if (operands.size() == 1) |
418 |
1/2✓ Branch 0 (5→6) taken 97 times.
✗ Branch 1 (5→70) not taken.
|
97 | 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 | 9669 | bool CastExprNode::hasCompileTimeValue() const { | |
443 |
2/2✓ Branch 0 (2→3) taken 351 times.
✓ Branch 1 (2→5) taken 9318 times.
|
9669 | return isCast ? assignExpr->hasCompileTimeValue() : prefixUnaryExpr->hasCompileTimeValue(); |
444 | } | ||
445 | |||
446 | 97 | CompileTimeValue CastExprNode::getCompileTimeValue() const { | |
447 |
1/2✗ Branch 0 (2→3) not taken.
✓ Branch 1 (2→4) taken 97 times.
|
97 | return isCast ? assignExpr->getCompileTimeValue() : prefixUnaryExpr->getCompileTimeValue(); |
448 | } | ||
449 | |||
450 | 9602 | bool PrefixUnaryExprNode::hasCompileTimeValue() const { // NOLINT(*-no-recursion) | |
451 |
2/2✓ Branch 0 (2→3) taken 9302 times.
✓ Branch 1 (2→5) taken 300 times.
|
9602 | if (postfixUnaryExpr) |
452 | 9302 | return postfixUnaryExpr->hasCompileTimeValue(); | |
453 | |||
454 |
3/4✓ Branch 0 (6→7) taken 292 times.
✓ Branch 1 (6→11) taken 8 times.
✓ Branch 2 (7→8) taken 292 times.
✗ Branch 3 (7→11) not taken.
|
300 | const bool isSupported = op == PrefixUnaryOp::OP_NONE || op == PrefixUnaryOp::OP_MINUS || op == PrefixUnaryOp::OP_PLUS_PLUS || |
455 |
4/6✓ Branch 0 (5→6) taken 300 times.
✗ Branch 1 (5→11) not taken.
✓ Branch 2 (8→9) taken 292 times.
✗ Branch 3 (8→11) not taken.
✓ Branch 4 (9→10) taken 16 times.
✓ Branch 5 (9→11) taken 276 times.
|
616 | op == PrefixUnaryOp::OP_MINUS_MINUS || op == PrefixUnaryOp::OP_NOT || |
456 |
1/2✗ Branch 0 (10→11) not taken.
✓ Branch 1 (10→12) taken 16 times.
|
16 | op == PrefixUnaryOp::OP_BITWISE_NOT; |
457 |
3/4✓ Branch 0 (13→14) taken 284 times.
✓ Branch 1 (13→17) taken 16 times.
✗ Branch 2 (15→16) not taken.
✓ Branch 3 (15→17) taken 284 times.
|
300 | return isSupported && prefixUnaryExpr->hasCompileTimeValue(); |
458 | } | ||
459 | |||
460 | 97 | CompileTimeValue PrefixUnaryExprNode::getCompileTimeValue() const { // NOLINT(*-no-recursion) | |
461 |
1/2✓ Branch 0 (2→3) taken 97 times.
✗ Branch 1 (2→5) not taken.
|
97 | if (postfixUnaryExpr) |
462 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (3→35) not taken.
|
97 | return postfixUnaryExpr->getCompileTimeValue(); |
463 | |||
464 | ✗ | CompileTimeValue opValue = prefixUnaryExpr->getCompileTimeValue(); | |
465 | ✗ | if (op == PrefixUnaryOp::OP_MINUS) | |
466 | ✗ | return CompileTimeValue{.longValue = -opValue.longValue}; | |
467 | ✗ | if (op == PrefixUnaryOp::OP_PLUS_PLUS) | |
468 | ✗ | return CompileTimeValue{.longValue = ++opValue.longValue}; | |
469 | ✗ | if (op == PrefixUnaryOp::OP_MINUS_MINUS) | |
470 | ✗ | return CompileTimeValue{.longValue = --opValue.longValue}; | |
471 | ✗ | if (op == PrefixUnaryOp::OP_NOT) | |
472 | ✗ | return CompileTimeValue{.boolValue = !opValue.boolValue}; | |
473 | ✗ | if (op == PrefixUnaryOp::OP_BITWISE_NOT) | |
474 | ✗ | return CompileTimeValue{.longValue = ~opValue.longValue}; | |
475 | |||
476 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "PrefixUnaryExprNode::getCompileTimeValue()"); | |
477 | } | ||
478 | |||
479 | 9302 | bool PostfixUnaryExprNode::hasCompileTimeValue() const { // NOLINT(*-no-recursion) | |
480 |
2/2✓ Branch 0 (2→3) taken 7224 times.
✓ Branch 1 (2→5) taken 2078 times.
|
9302 | if (atomicExpr) |
481 | 7224 | return atomicExpr->hasCompileTimeValue(); | |
482 | |||
483 | 2078 | const bool isSupported = | |
484 |
3/6✓ Branch 0 (5→6) taken 2078 times.
✗ Branch 1 (5→8) not taken.
✓ Branch 2 (6→7) taken 2078 times.
✗ Branch 3 (6→8) not taken.
✗ Branch 4 (7→8) not taken.
✓ Branch 5 (7→9) taken 2078 times.
|
2078 | op == PostfixUnaryOp::OP_NONE || op == PostfixUnaryOp::OP_PLUS_PLUS || op == PostfixUnaryOp::OP_MINUS_MINUS; |
485 |
1/4✗ Branch 0 (10→11) not taken.
✓ Branch 1 (10→14) taken 2078 times.
✗ Branch 2 (12→13) not taken.
✗ Branch 3 (12→14) not taken.
|
2078 | return isSupported && postfixUnaryExpr->hasCompileTimeValue(); |
486 | } | ||
487 | |||
488 | 97 | CompileTimeValue PostfixUnaryExprNode::getCompileTimeValue() const { // NOLINT(*-no-recursion) | |
489 |
1/2✓ Branch 0 (2→3) taken 97 times.
✗ Branch 1 (2→5) not taken.
|
97 | if (atomicExpr) |
490 |
1/2✓ Branch 0 (3→4) taken 97 times.
✗ Branch 1 (3→29) not taken.
|
97 | return atomicExpr->getCompileTimeValue(); |
491 | |||
492 | ✗ | CompileTimeValue opValue = postfixUnaryExpr->getCompileTimeValue(); | |
493 | ✗ | if (op == PostfixUnaryOp::OP_PLUS_PLUS) | |
494 | ✗ | return CompileTimeValue{.longValue = opValue.longValue++}; | |
495 | ✗ | if (op == PostfixUnaryOp::OP_MINUS_MINUS) | |
496 | ✗ | return CompileTimeValue{.longValue = opValue.longValue--}; | |
497 | |||
498 | ✗ | throw CompilerError(UNHANDLED_BRANCH, "PostfixUnaryExprNode::getCompileTimeValue()"); | |
499 | } | ||
500 | |||
501 | /** | ||
502 | * Check if right above the closest assign expression ancestor is a statement node | ||
503 | * | ||
504 | * @return Has return value receiver or not | ||
505 | */ | ||
506 | 8772 | bool FctCallNode::hasReturnValueReceiver() const { | |
507 | 8772 | const ASTNode *node = parent; | |
508 |
2/2✓ Branch 0 (10→3) taken 133296 times.
✓ Branch 1 (10→11) taken 6631 times.
|
139927 | while (!node->isAssignExpr()) { |
509 | // As soon as we have a node with more than one child, we know that the return value is used | ||
510 |
3/4✓ Branch 0 (3→4) taken 133296 times.
✗ Branch 1 (3→23) not taken.
✓ Branch 2 (6→7) taken 2141 times.
✓ Branch 3 (6→8) taken 131155 times.
|
133296 | if (node->getChildren().size() > 1) |
511 | 2141 | return true; | |
512 | 131155 | node = node->parent; | |
513 | } | ||
514 | // Also check the condition of the assign expression | ||
515 |
6/12✓ Branch 0 (11→12) taken 6631 times.
✗ Branch 1 (11→24) not taken.
✓ Branch 2 (13→14) taken 6631 times.
✗ Branch 3 (13→16) not taken.
✓ Branch 4 (14→15) taken 6631 times.
✗ Branch 5 (14→24) not taken.
✓ Branch 6 (15→16) taken 6483 times.
✓ Branch 7 (15→17) taken 148 times.
✓ Branch 8 (19→20) taken 6631 times.
✗ Branch 9 (19→21) not taken.
✗ Branch 10 (24→25) not taken.
✗ Branch 11 (24→26) not taken.
|
6631 | return node->getChildren().size() > 1 || !node->parent->isExprStmt(); |
516 | } | ||
517 | |||
518 | 12 | bool LambdaFuncNode::returnsOnAllControlPaths(bool *overrideUnreachable) const { | |
519 | 12 | return body->returnsOnAllControlPaths(overrideUnreachable); | |
520 | } | ||
521 | |||
522 | 38 | bool LambdaProcNode::returnsOnAllControlPaths(bool *overrideUnreachable) const { | |
523 | 38 | return body->returnsOnAllControlPaths(overrideUnreachable); | |
524 | } | ||
525 | |||
526 | 1486 | void DataTypeNode::setFieldTypeRecursive() { // NOLINT(*-no-recursion) | |
527 | // Set the current node to field type | ||
528 | 1486 | isFieldType = true; | |
529 | // Do the same for all template nodes | ||
530 |
4/4✓ Branch 0 (2→3) taken 628 times.
✓ Branch 1 (2→12) taken 858 times.
✓ Branch 2 (3→4) taken 131 times.
✓ Branch 3 (3→12) taken 497 times.
|
1486 | if (const CustomDataTypeNode *customType = baseDataType->customDataType; customType != nullptr && customType->templateTypeLst) |
531 |
2/2✓ Branch 0 (10→6) taken 174 times.
✓ Branch 1 (10→11) taken 131 times.
|
305 | for (DataTypeNode *templateNode : customType->templateTypeLst->dataTypes) |
532 |
1/2✓ Branch 0 (7→8) taken 174 times.
✗ Branch 1 (7→13) not taken.
|
174 | templateNode->setFieldTypeRecursive(); |
533 | 1486 | } | |
534 | |||
535 | } // namespace spice::compiler | ||
536 |