GCC Code Coverage Report


Directory: ../
File: src/typechecker/OpRuleManager.cpp
Date: 2024-12-24 01:17:15
Exec Total Coverage
Lines: 393 416 94.5%
Functions: 51 51 100.0%
Branches: 649 1098 59.1%

Line Branch Exec Source
1 // Copyright (c) 2021-2024 ChilliBits. All rights reserved.
2
3 #include "OpRuleManager.h"
4
5 #include <SourceFile.h>
6 #include <ast/ASTNodes.h>
7 #include <global/GlobalResourceManager.h>
8 #include <global/RuntimeModuleManager.h>
9 #include <typechecker/MacroDefs.h>
10 #include <typechecker/TypeChecker.h>
11
12 namespace spice::compiler {
13
14 4327 OpRuleManager::OpRuleManager(TypeChecker *typeChecker)
15 4327 : typeChecker(typeChecker), resourceManager(typeChecker->resourceManager) {}
16
17 17496 QualType OpRuleManager::getAssignResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, bool isDecl,
18 bool isReturn, const char *errMsgPrefix) const {
19 // Retrieve types
20 17496 const QualType lhsType = lhs.type;
21 17496 const QualType rhsType = rhs.type;
22
23 // Skip type compatibility check if the lhs is of type dyn -> perform type inference
24
3/4
✓ Branch 1 taken 17496 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 65 times.
✓ Branch 4 taken 17431 times.
17496 if (lhsType.is(TY_DYN))
25 65 return rhsType;
26
27 // Check if we try to assign a constant value
28
2/2
✓ Branch 1 taken 17429 times.
✓ Branch 2 taken 2 times.
17431 ensureNoConstAssign(node, lhsType, isDecl, isReturn);
29
30 // Allow pointers and arrays of the same type straight away
31
8/10
✓ Branch 1 taken 17429 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2297 times.
✓ Branch 4 taken 15132 times.
✓ Branch 6 taken 2297 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2001 times.
✓ Branch 9 taken 296 times.
✓ Branch 10 taken 2001 times.
✓ Branch 11 taken 15428 times.
17429 if (lhsType.isOneOf({TY_PTR, TY_REF}) && lhsType.matches(rhsType, false, false, true)) {
32 // If we perform a heap x* = heap x* assignment, we need set the right hand side to MOVED
33
15/22
✓ Branch 0 taken 615 times.
✓ Branch 1 taken 1386 times.
✓ Branch 3 taken 615 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 454 times.
✓ Branch 6 taken 161 times.
✓ Branch 8 taken 454 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 377 times.
✓ Branch 11 taken 77 times.
✓ Branch 13 taken 377 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 377 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 377 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 377 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 377 times.
✗ Branch 24 not taken.
✓ Branch 25 taken 377 times.
✓ Branch 26 taken 1624 times.
2001 if (rhs.entry && lhsType.isPtr() && lhsType.isHeap() && rhsType.removeReferenceWrapper().isPtr() && rhsType.isHeap())
34
1/2
✓ Branch 1 taken 377 times.
✗ Branch 2 not taken.
377 rhs.entry->updateState(MOVED, node);
35 2001 return rhsType;
36 }
37 // Allow ref type to type of the same contained type straight away
38
3/4
✓ Branch 1 taken 15428 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 221 times.
✓ Branch 4 taken 15207 times.
15428 if (rhsType.isRef()) {
39 // If this is const ref, remove both: the reference and the constness
40
2/4
✓ Branch 1 taken 221 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 221 times.
✗ Branch 5 not taken.
221 const QualType rhsModified = rhsType.getContained().toNonConst();
41
4/6
✓ Branch 1 taken 221 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 221 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 219 times.
✓ Branch 7 taken 2 times.
221 if (lhsType.matches(rhsModified, false, !lhsType.isRef(), true)) {
42 // In case of a return expression, we perform temp stealing
43
9/10
✓ Branch 1 taken 219 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 129 times.
✓ Branch 4 taken 90 times.
✓ Branch 6 taken 117 times.
✓ Branch 7 taken 12 times.
✓ Branch 8 taken 115 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 115 times.
✓ Branch 11 taken 104 times.
219 if (rhsModified.is(TY_STRUCT) && !rhs.isTemporary() && !isReturn)
44
1/2
✓ Branch 1 taken 115 times.
✗ Branch 2 not taken.
115 typeChecker->implicitlyCallStructCopyCtor(rhs.entry, rhs.entry->declNode);
45 219 return lhsType;
46 }
47 }
48 // Allow arrays, structs, interfaces, functions, procedures of the same type straight away
49
8/10
✓ Branch 1 taken 15209 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 78 times.
✓ Branch 4 taken 15131 times.
✓ Branch 6 taken 78 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 71 times.
✓ Branch 9 taken 7 times.
✓ Branch 10 taken 71 times.
✓ Branch 11 taken 15138 times.
15209 if (lhsType.isOneOf({TY_ARRAY, TY_INTERFACE, TY_FUNCTION, TY_PROCEDURE}) && lhsType.matches(rhsType, false, true, true))
50 71 return rhsType;
51 // Allow struct of the same type straight away
52
8/10
✓ Branch 1 taken 15138 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1661 times.
✓ Branch 4 taken 13477 times.
✓ Branch 6 taken 1661 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1660 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 1660 times.
✓ Branch 11 taken 13478 times.
15138 if (lhsType.is(TY_STRUCT) && lhsType.matches(rhsType, false, true, true)) {
53 // In case of a return expression, we perform temp stealing
54
6/6
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 1609 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 45 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 1654 times.
1660 if (!rhs.isTemporary() && !isReturn)
55
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 typeChecker->implicitlyCallStructCopyCtor(rhs.entry, rhs.entry->declNode);
56 1660 return rhsType;
57 }
58
59 // Check common type combinations
60
2/2
✓ Branch 1 taken 13477 times.
✓ Branch 2 taken 1 times.
13478 const QualType resultType = getAssignResultTypeCommon(node, lhs, rhs, isDecl, isReturn);
61
3/4
✓ Branch 1 taken 13477 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 268 times.
✓ Branch 4 taken 13209 times.
13477 if (!resultType.is(TY_INVALID))
62 268 return resultType;
63
64 // Check primitive type combinations
65
2/2
✓ Branch 1 taken 13197 times.
✓ Branch 2 taken 12 times.
13209 return validateBinaryOperation(node, ASSIGN_OP_RULES, std::size(ASSIGN_OP_RULES), "=", lhsType, rhsType, true, errMsgPrefix);
66 }
67
68 245 QualType OpRuleManager::getFieldAssignResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, bool imm,
69 bool isDecl) const {
70 // Retrieve types
71 245 const QualType lhsType = lhs.type;
72 245 const QualType rhsType = rhs.type;
73
2/4
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 245 times.
245 assert(!lhsType.is(TY_DYN));
74
75 // Check if we try to assign a constant value
76
1/2
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
245 ensureNoConstAssign(node, lhsType, isDecl);
77
78 // Allow pointers, arrays and structs of the same type straight away
79
8/10
✓ Branch 1 taken 245 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 135 times.
✓ Branch 4 taken 110 times.
✓ Branch 6 taken 135 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 133 times.
✓ Branch 9 taken 2 times.
✓ Branch 10 taken 133 times.
✓ Branch 11 taken 112 times.
245 if (lhsType.isOneOf({TY_PTR, TY_ARRAY}) && lhsType == rhsType) {
80 // If we perform a heap x* = heap x* assignment, we need set the right hand side to MOVED
81
8/22
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 88 times.
✓ Branch 3 taken 45 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 43 times.
✓ Branch 6 taken 2 times.
✓ Branch 8 taken 43 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 43 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 133 times.
133 if (rhs.entry && lhsType.isPtr() && lhsType.isHeap() && rhsType.removeReferenceWrapper().isPtr() && rhsType.isHeap())
82 rhs.entry->updateState(MOVED, node);
83 133 return rhsType;
84 }
85 // Allow struct of the same type straight away
86
8/10
✓ Branch 1 taken 112 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 107 times.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 4 times.
✓ Branch 11 taken 108 times.
112 if (lhsType.is(TY_STRUCT) && lhsType.matches(rhsType, false, true, true)) {
87
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (!rhs.isTemporary())
88
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 typeChecker->implicitlyCallStructCopyCtor(rhs.entry, rhs.entry->declNode);
89 4 return rhsType;
90 }
91 // Allow ref type to type of the same contained type straight away
92
9/12
✓ Branch 1 taken 108 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 94 times.
✓ Branch 6 taken 14 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 14 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 times.
✓ Branch 12 taken 13 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 107 times.
108 if (rhsType.isRef() && lhsType.matches(rhsType.getContained(), false, false, true)) {
93 // In case of a return expression, we perform temp stealing
94
4/10
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
1 if (rhsType.getContained().is(TY_STRUCT) && !rhs.isTemporary())
95 typeChecker->implicitlyCallStructCopyCtor(rhs.entry, rhs.entry->declNode);
96 1 return lhsType;
97 }
98 // Allow const ref type to type of the same contained type straight away
99
9/14
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 94 times.
✓ Branch 6 taken 13 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 13 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 13 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 13 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 13 times.
✓ Branch 17 taken 94 times.
107 if (rhsType.isConstRef() && lhsType.matches(rhsType.getContained().toNonConst(), false, false, true))
100 13 return lhsType;
101 // Allow immediate value to const ref of the same contained type straight away
102
6/8
✓ Branch 1 taken 94 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 93 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 times.
✓ Branch 8 taken 93 times.
94 if (lhsType.isConstRef() && imm)
103 1 return rhsType;
104
105 // Check common type combinations
106
1/2
✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
93 const QualType resultType = getAssignResultTypeCommon(node, lhs, rhs, isDecl, false);
107
3/4
✓ Branch 1 taken 93 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 89 times.
93 if (!resultType.is(TY_INVALID))
108 4 return resultType;
109
110 // Check primitive type combinations
111
2/2
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 1 times.
89 return validateBinaryOperation(node, ASSIGN_OP_RULES, std::size(ASSIGN_OP_RULES), "=", lhsType, rhsType, true,
112 88 ERROR_FIELD_ASSIGN);
113 }
114
115 13571 QualType OpRuleManager::getAssignResultTypeCommon(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, bool isDecl,
116 bool isReturn) {
117 // Retrieve types
118 13571 const QualType lhsType = lhs.type;
119 13571 const QualType rhsType = rhs.type;
120
121 // Allow type to ref type of the same contained type straight away
122
9/12
✓ Branch 1 taken 13571 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 175 times.
✓ Branch 4 taken 13396 times.
✓ Branch 6 taken 175 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 175 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 172 times.
✓ Branch 12 taken 3 times.
✓ Branch 13 taken 172 times.
✓ Branch 14 taken 13399 times.
13571 if (lhsType.isRef() && lhsType.getContained().matches(rhsType, false, false, true)) {
123
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 43 times.
172 const bool isDeclOrReturn = isDecl || isReturn;
124
7/8
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 43 times.
✓ Branch 4 taken 129 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 times.
✓ Branch 7 taken 128 times.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 171 times.
172 if (isDeclOrReturn && !lhsType.canBind(rhsType, rhs.isTemporary()))
125
2/4
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
3 throw SemanticError(node, TEMP_TO_NON_CONST_REF, "Temporary values can only be bound to const reference variables/fields");
126 171 return lhsType;
127 }
128 // Allow dyn[] (empty array literal) to any array
129
8/10
✓ Branch 1 taken 13399 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 13396 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 13397 times.
13399 if (lhsType.isArray() && rhsType.isArrayOf(TY_DYN))
130 2 return lhsType;
131 // Allow char* = string
132
9/14
✓ Branch 1 taken 13397 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 13396 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 times.
✓ Branch 18 taken 13396 times.
13397 if (lhsType.isPtrTo(TY_CHAR) && rhsType.is(TY_STRING) && lhsType.getSpecifiers() == rhsType.getSpecifiers())
133 1 return lhsType;
134 // Allow array to pointer
135
12/18
✓ Branch 1 taken 13396 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 98 times.
✓ Branch 4 taken 13298 times.
✓ Branch 6 taken 98 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✓ Branch 9 taken 93 times.
✓ Branch 11 taken 5 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 5 times.
✗ Branch 15 not taken.
✓ Branch 17 taken 5 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 5 times.
✗ Branch 20 not taken.
✓ Branch 21 taken 5 times.
✓ Branch 22 taken 13391 times.
13396 if (lhsType.isPtr() && rhsType.isArray() && lhsType.getContained().matches(rhsType.getContained(), false, false, true))
136 5 return lhsType;
137 // Allow interface* = struct* or interface& = struct that implements this interface
138
1/2
✓ Branch 3 taken 13391 times.
✗ Branch 4 not taken.
13391 const bool sameChainDepth = Type::hasSameTypeChainDepth(lhsType.getType(), rhsType.getType());
139
10/14
✓ Branch 1 taken 13391 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 93 times.
✓ Branch 4 taken 13298 times.
✓ Branch 6 taken 93 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 92 times.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 92 times.
✓ Branch 13 taken 13299 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 3 times.
✓ Branch 16 taken 13296 times.
13391 const bool typesCompatible = (lhsType.isPtr() && rhsType.isPtr() && sameChainDepth) || lhsType.isRef();
140
9/12
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 13296 times.
✓ Branch 3 taken 95 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 5 times.
✓ Branch 6 taken 90 times.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 5 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 5 times.
✓ Branch 13 taken 13386 times.
13391 if (typesCompatible && lhsType.isBase(TY_INTERFACE) && rhsType.isBase(TY_STRUCT)) {
141 5 QualType lhsTypeCopy = lhsType;
142 5 QualType rhsTypeCopy = rhsType;
143
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 QualType::unwrapBoth(lhsTypeCopy, rhsTypeCopy);
144
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
5 if (lhsTypeCopy.matchesInterfaceImplementedByStruct(rhsTypeCopy))
145 5 return lhsType;
146 }
147 // Allow type* = heap type* straight away. This is used for initializing non-owning pointers to heap allocations
148
10/14
✓ Branch 1 taken 13386 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 89 times.
✓ Branch 4 taken 13297 times.
✓ Branch 6 taken 89 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 88 times.
✓ Branch 9 taken 1 times.
✓ Branch 11 taken 88 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 88 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 88 times.
✓ Branch 16 taken 13298 times.
13386 if (lhsType.isPtr() && rhsType.isHeap() && lhsType.matches(rhsType, false, true, true)) {
149 88 TypeSpecifiers rhsSpecifiers = rhsType.getSpecifiers();
150 88 rhsSpecifiers.isHeap = false;
151
2/4
✓ Branch 2 taken 88 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 88 times.
✗ Branch 5 not taken.
88 if (lhsType.getSpecifiers() == rhsSpecifiers)
152 88 return lhsType;
153 }
154
155 // Nothing matched
156
1/2
✓ Branch 1 taken 13298 times.
✗ Branch 2 not taken.
13298 return QualType(TY_INVALID);
157 }
158
159 213 ExprResult OpRuleManager::getPlusEqualResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
160 // Check is there is an overloaded operator function available
161
1/2
✓ Branch 1 taken 213 times.
✗ Branch 2 not taken.
213 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_PLUS_EQUAL, {lhs, rhs}, opIdx);
162
3/4
✓ Branch 1 taken 213 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 79 times.
✓ Branch 4 taken 134 times.
213 if (!resultType.type.is(TY_INVALID))
163 79 return resultType;
164
165 // Check if we try to assign a constant value
166
1/2
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
134 ensureNoConstAssign(node, lhs.type);
167
168 // Remove reference wrappers
169
1/2
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
134 const QualType lhsType = lhs.type.removeReferenceWrapper();
170
1/2
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
134 const QualType rhsType = rhs.type.removeReferenceWrapper();
171
172 // Check if this is an unsafe operation
173
7/10
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 133 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 133 times.
134 if (lhsType.isPtr() && rhsType.isOneOf({TY_INT, TY_LONG, TY_SHORT})) {
174
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ensureUnsafeAllowed(node, "+=", lhsType, rhsType);
175 1 return {lhs};
176 }
177
178
1/2
✓ Branch 1 taken 133 times.
✗ Branch 2 not taken.
133 return {validateBinaryOperation(node, PLUS_EQUAL_OP_RULES, std::size(PLUS_EQUAL_OP_RULES), "+=", lhsType, rhsType)};
179 }
180
181 27 ExprResult OpRuleManager::getMinusEqualResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
182 // Check is there is an overloaded operator function available
183
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
27 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_MINUS_EQUAL, {lhs, rhs}, opIdx);
184
3/4
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 20 times.
27 if (!resultType.type.is(TY_INVALID))
185 7 return resultType;
186
187 // Check if we try to assign a constant value
188
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 ensureNoConstAssign(node, lhs.type);
189
190 // Remove reference wrappers
191
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 const QualType lhsType = lhs.type.removeReferenceWrapper();
192
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 const QualType rhsType = rhs.type.removeReferenceWrapper();
193
194 // Check if this is an unsafe operation
195
7/10
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 19 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
✓ Branch 11 taken 19 times.
20 if (lhsType.isPtr() && rhsType.isOneOf({TY_INT, TY_LONG, TY_SHORT})) {
196
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ensureUnsafeAllowed(node, "-=", lhsType, rhsType);
197 1 return {lhs};
198 }
199
200
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 return {validateBinaryOperation(node, MINUS_EQUAL_OP_RULES, std::size(MINUS_EQUAL_OP_RULES), "-=", lhsType, rhsType)};
201 }
202
203 15 ExprResult OpRuleManager::getMulEqualResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
204 // Check is there is an overloaded operator function available
205
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_MUL_EQUAL, {lhs, rhs}, opIdx);
206
3/4
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 13 times.
15 if (!resultType.type.is(TY_INVALID))
207 2 return resultType;
208
209 // Check if we try to assign a constant value
210
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 ensureNoConstAssign(node, lhs.type);
211
212 // Remove reference wrappers
213
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 const QualType lhsType = lhs.type.removeReferenceWrapper();
214
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 const QualType rhsType = rhs.type.removeReferenceWrapper();
215
216
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 return {validateBinaryOperation(node, MUL_EQUAL_OP_RULES, std::size(MUL_EQUAL_OP_RULES), "*=", lhsType, rhsType)};
217 }
218
219 35 ExprResult OpRuleManager::getDivEqualResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
220 // Check is there is an overloaded operator function available
221
1/2
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
35 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_DIV_EQUAL, {lhs, rhs}, opIdx);
222
3/4
✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32 times.
✓ Branch 4 taken 3 times.
35 if (!resultType.type.is(TY_INVALID))
223 32 return resultType;
224
225 // Check if we try to assign a constant value
226
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 ensureNoConstAssign(node, lhs.type);
227
228 // Remove reference wrappers
229
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const QualType lhsType = lhs.type.removeReferenceWrapper();
230
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 const QualType rhsType = rhs.type.removeReferenceWrapper();
231
232
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 return {validateBinaryOperation(node, DIV_EQUAL_OP_RULES, std::size(DIV_EQUAL_OP_RULES), "/=", lhsType, rhsType)};
233 }
234
235 5 QualType OpRuleManager::getRemEqualResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
236 // Check if we try to assign a constant value
237
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 ensureNoConstAssign(node, lhs.type);
238
239 // Remove reference wrappers
240
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 const QualType lhsType = lhs.type.removeReferenceWrapper();
241
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 const QualType rhsType = rhs.type.removeReferenceWrapper();
242
243
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
10 return validateBinaryOperation(node, REM_EQUAL_OP_RULES, std::size(REM_EQUAL_OP_RULES), "%=", lhsType, rhsType);
244 }
245
246 1 QualType OpRuleManager::getSHLEqualResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
247 // Check if we try to assign a constant value
248
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ensureNoConstAssign(node, lhs.type);
249
250 // Remove reference wrappers
251
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType lhsType = lhs.type.removeReferenceWrapper();
252
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType rhsType = rhs.type.removeReferenceWrapper();
253
254
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return validateBinaryOperation(node, SHL_EQUAL_OP_RULES, std::size(SHL_EQUAL_OP_RULES), "<<=", lhsType, rhsType);
255 }
256
257 2 QualType OpRuleManager::getSHREqualResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
258 // Check if we try to assign a constant value
259
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 ensureNoConstAssign(node, lhs.type);
260
261 // Remove reference wrappers
262
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const QualType lhsType = lhs.type.removeReferenceWrapper();
263
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 const QualType rhsType = rhs.type.removeReferenceWrapper();
264
265
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
4 return validateBinaryOperation(node, SHR_EQUAL_OP_RULES, std::size(SHR_EQUAL_OP_RULES), ">>=", lhsType, rhsType);
266 }
267
268 1 QualType OpRuleManager::getAndEqualResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
269 // Check if we try to assign a constant value
270
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ensureNoConstAssign(node, lhs.type);
271
272 // Remove reference wrappers
273
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType lhsType = lhs.type.removeReferenceWrapper();
274
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType rhsType = rhs.type.removeReferenceWrapper();
275
276
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return validateBinaryOperation(node, AND_EQUAL_OP_RULES, std::size(AND_EQUAL_OP_RULES), "&=", lhsType, rhsType);
277 }
278
279 1 QualType OpRuleManager::getOrEqualResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
280 // Check if we try to assign a constant value
281
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ensureNoConstAssign(node, lhs.type);
282
283 // Remove reference wrappers
284
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType lhsType = lhs.type.removeReferenceWrapper();
285
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType rhsType = rhs.type.removeReferenceWrapper();
286
287
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return validateBinaryOperation(node, OR_EQUAL_OP_RULES, std::size(OR_EQUAL_OP_RULES), "|=", lhsType, rhsType);
288 }
289
290 231 QualType OpRuleManager::getXorEqualResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
291 // Check if we try to assign a constant value
292
1/2
✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
231 ensureNoConstAssign(node, lhs.type);
293
294 // Remove reference wrappers
295
1/2
✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
231 const QualType lhsType = lhs.type.removeReferenceWrapper();
296
1/2
✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
231 const QualType rhsType = rhs.type.removeReferenceWrapper();
297
298
1/2
✓ Branch 1 taken 231 times.
✗ Branch 2 not taken.
462 return validateBinaryOperation(node, XOR_EQUAL_OP_RULES, std::size(XOR_EQUAL_OP_RULES), "^=", lhsType, rhsType);
299 }
300
301 288 QualType OpRuleManager::getLogicalOrResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
302 // Remove reference wrappers
303
1/2
✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
288 const QualType lhsType = lhs.type.removeReferenceWrapper();
304
1/2
✓ Branch 1 taken 288 times.
✗ Branch 2 not taken.
288 const QualType rhsType = rhs.type.removeReferenceWrapper();
305
306
2/2
✓ Branch 1 taken 287 times.
✓ Branch 2 taken 1 times.
575 return validateBinaryOperation(node, LOGICAL_OR_OP_RULES, std::size(LOGICAL_OR_OP_RULES), "||", lhsType, rhsType);
307 }
308
309 65 QualType OpRuleManager::getLogicalAndResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
310 // Remove reference wrappers
311
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 const QualType lhsType = lhs.type.removeReferenceWrapper();
312
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
65 const QualType rhsType = rhs.type.removeReferenceWrapper();
313
314
1/2
✓ Branch 1 taken 65 times.
✗ Branch 2 not taken.
130 return validateBinaryOperation(node, LOGICAL_AND_OP_RULES, std::size(LOGICAL_AND_OP_RULES), "&&", lhsType, rhsType);
315 }
316
317 36 QualType OpRuleManager::getBitwiseOrResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
318 // Remove reference wrappers
319
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 const QualType lhsType = lhs.type.removeReferenceWrapper();
320
1/2
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
36 const QualType rhsType = rhs.type.removeReferenceWrapper();
321
322
2/2
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 1 times.
71 return validateBinaryOperation(node, BITWISE_OR_OP_RULES, std::size(BITWISE_OR_OP_RULES), "|", lhsType, rhsType);
323 }
324
325 7 QualType OpRuleManager::getBitwiseXorResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
326 // Remove reference wrappers
327
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 const QualType lhsType = lhs.type.removeReferenceWrapper();
328
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 const QualType rhsType = rhs.type.removeReferenceWrapper();
329
330
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
14 return validateBinaryOperation(node, BITWISE_XOR_OP_RULES, std::size(BITWISE_XOR_OP_RULES), "^", lhsType, rhsType);
331 }
332
333 33 QualType OpRuleManager::getBitwiseAndResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
334 // Remove reference wrappers
335
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 const QualType lhsType = lhs.type.removeReferenceWrapper();
336
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
33 const QualType rhsType = rhs.type.removeReferenceWrapper();
337
338
1/2
✓ Branch 1 taken 33 times.
✗ Branch 2 not taken.
66 return validateBinaryOperation(node, BITWISE_AND_OP_RULES, std::size(BITWISE_AND_OP_RULES), "&", lhsType, rhsType);
339 }
340
341 2379 ExprResult OpRuleManager::getEqualResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
342 // Check is there is an overloaded operator function available
343
1/2
✓ Branch 1 taken 2379 times.
✗ Branch 2 not taken.
2379 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_EQUAL, {lhs, rhs}, opIdx);
344
3/4
✓ Branch 1 taken 2379 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 357 times.
✓ Branch 4 taken 2022 times.
2379 if (!resultType.type.is(TY_INVALID))
345 357 return resultType;
346
347 // Remove reference wrappers
348
1/2
✓ Branch 1 taken 2022 times.
✗ Branch 2 not taken.
2022 const QualType lhsType = lhs.type.removeReferenceWrapper();
349
1/2
✓ Branch 1 taken 2022 times.
✗ Branch 2 not taken.
2022 const QualType rhsType = rhs.type.removeReferenceWrapper();
350
351 // Allow 'pointer == pointer' straight away
352
7/10
✓ Branch 1 taken 2022 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 593 times.
✓ Branch 4 taken 1429 times.
✓ Branch 6 taken 593 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 593 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 593 times.
✓ Branch 11 taken 1429 times.
2022 if (lhsType.isPtr() && rhsType.isPtr())
353
1/2
✓ Branch 1 taken 593 times.
✗ Branch 2 not taken.
593 return ExprResult(QualType(TY_BOOL));
354
355 // Allow 'pointer == int' straight away
356
3/10
✓ Branch 1 taken 1429 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1429 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1429 times.
1429 if (lhsType.isPtr() && rhsType.is(TY_INT))
357 return ExprResult(QualType(TY_BOOL));
358
359 // Allow 'string == char*' and vice versa straight away
360
8/18
✓ Branch 1 taken 1429 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 119 times.
✓ Branch 4 taken 1310 times.
✓ Branch 6 taken 119 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 119 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1429 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1429 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1429 times.
1429 if ((lhsType.is(TY_STRING) && rhsType.isPtrTo(TY_CHAR)) || (lhsType.isPtrTo(TY_CHAR) && rhsType.is(TY_STRING)))
361 return ExprResult(QualType(TY_BOOL));
362
363 // Check primitive type combinations
364
2/2
✓ Branch 1 taken 1428 times.
✓ Branch 2 taken 1 times.
1429 return ExprResult(validateBinaryOperation(node, EQUAL_OP_RULES, std::size(EQUAL_OP_RULES), "==", lhsType, rhsType));
365 }
366
367 1315 ExprResult OpRuleManager::getNotEqualResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
368 // Check is there is an overloaded operator function available
369
1/2
✓ Branch 1 taken 1315 times.
✗ Branch 2 not taken.
1315 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_NOT_EQUAL, {lhs, rhs}, opIdx);
370
3/4
✓ Branch 1 taken 1315 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 1305 times.
1315 if (!resultType.type.is(TY_INVALID))
371 10 return resultType;
372
373 // Remove reference wrappers
374
1/2
✓ Branch 1 taken 1305 times.
✗ Branch 2 not taken.
1305 const QualType lhsType = lhs.type.removeReferenceWrapper();
375
1/2
✓ Branch 1 taken 1305 times.
✗ Branch 2 not taken.
1305 const QualType rhsType = rhs.type.removeReferenceWrapper();
376
377 // Allow 'pointer != pointer' straight away
378
7/10
✓ Branch 1 taken 1305 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 146 times.
✓ Branch 4 taken 1159 times.
✓ Branch 6 taken 146 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 146 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 146 times.
✓ Branch 11 taken 1159 times.
1305 if (lhsType.isPtr() && rhsType.isPtr())
379
1/2
✓ Branch 1 taken 146 times.
✗ Branch 2 not taken.
146 return ExprResult(QualType(TY_BOOL));
380
381 // Allow 'pointer != int' straight away
382
3/10
✓ Branch 1 taken 1159 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1159 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1159 times.
1159 if (lhsType.isPtr() && rhsType.is(TY_INT))
383 return ExprResult(QualType(TY_BOOL));
384
385 // Allow 'string != char*' and vice versa straight away
386
8/18
✓ Branch 1 taken 1159 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 1148 times.
✓ Branch 6 taken 11 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 11 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1159 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1159 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 1159 times.
1159 if ((lhsType.is(TY_STRING) && rhsType.isPtrTo(TY_CHAR)) || (lhsType.isPtrTo(TY_CHAR) && rhsType.is(TY_STRING)))
387 return ExprResult(QualType(TY_BOOL));
388
389 // Check primitive type combinations
390
1/2
✓ Branch 1 taken 1159 times.
✗ Branch 2 not taken.
1159 return ExprResult(validateBinaryOperation(node, NOT_EQUAL_OP_RULES, std::size(NOT_EQUAL_OP_RULES), "!=", lhsType, rhsType));
391 }
392
393 1476 QualType OpRuleManager::getLessResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
394 // Remove reference wrappers
395
1/2
✓ Branch 1 taken 1476 times.
✗ Branch 2 not taken.
1476 const QualType lhsType = lhs.type.removeReferenceWrapper();
396
1/2
✓ Branch 1 taken 1476 times.
✗ Branch 2 not taken.
1476 const QualType rhsType = rhs.type.removeReferenceWrapper();
397
398
1/2
✓ Branch 1 taken 1476 times.
✗ Branch 2 not taken.
2952 return validateBinaryOperation(node, LESS_OP_RULES, std::size(LESS_OP_RULES), "<", lhsType, rhsType);
399 }
400
401 246 QualType OpRuleManager::getGreaterResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
402 // Remove reference wrappers
403
1/2
✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
246 const QualType lhsType = lhs.type.removeReferenceWrapper();
404
1/2
✓ Branch 1 taken 246 times.
✗ Branch 2 not taken.
246 const QualType rhsType = rhs.type.removeReferenceWrapper();
405
406
2/2
✓ Branch 1 taken 245 times.
✓ Branch 2 taken 1 times.
491 return validateBinaryOperation(node, GREATER_OP_RULES, std::size(GREATER_OP_RULES), ">", lhsType, rhsType);
407 }
408
409 263 QualType OpRuleManager::getLessEqualResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
410 // Remove reference wrappers
411
1/2
✓ Branch 1 taken 263 times.
✗ Branch 2 not taken.
263 const QualType lhsType = lhs.type.removeReferenceWrapper();
412
1/2
✓ Branch 1 taken 263 times.
✗ Branch 2 not taken.
263 const QualType rhsType = rhs.type.removeReferenceWrapper();
413
414
1/2
✓ Branch 1 taken 263 times.
✗ Branch 2 not taken.
526 return validateBinaryOperation(node, LESS_EQUAL_OP_RULES, std::size(LESS_EQUAL_OP_RULES), "<=", lhsType, rhsType);
415 }
416
417 564 QualType OpRuleManager::getGreaterEqualResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
418 // Remove reference wrappers
419
1/2
✓ Branch 1 taken 564 times.
✗ Branch 2 not taken.
564 const QualType lhsType = lhs.type.removeReferenceWrapper();
420
1/2
✓ Branch 1 taken 564 times.
✗ Branch 2 not taken.
564 const QualType rhsType = rhs.type.removeReferenceWrapper();
421
422
1/2
✓ Branch 1 taken 564 times.
✗ Branch 2 not taken.
1128 return validateBinaryOperation(node, GREATER_EQUAL_OP_RULES, std::size(GREATER_EQUAL_OP_RULES), ">=", lhsType, rhsType);
423 }
424
425 10 ExprResult OpRuleManager::getShiftLeftResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
426 // Check is there is an overloaded operator function available
427
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_SHL, {lhs, rhs}, opIdx);
428
3/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 9 times.
10 if (!resultType.type.is(TY_INVALID))
429 1 return resultType;
430
431 // Remove reference wrappers
432
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 const QualType lhsType = lhs.type.removeReferenceWrapper();
433
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 const QualType rhsType = rhs.type.removeReferenceWrapper();
434
435
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 return {validateBinaryOperation(node, SHIFT_LEFT_OP_RULES, std::size(SHIFT_LEFT_OP_RULES), "<<", lhsType, rhsType)};
436 }
437
438 7 ExprResult OpRuleManager::getShiftRightResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
439 // Check is there is an overloaded operator function available
440
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_SHR, {lhs, rhs}, opIdx);
441
3/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 6 times.
7 if (!resultType.type.is(TY_INVALID))
442 1 return resultType;
443
444 // Remove reference wrappers
445
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 const QualType lhsType = lhs.type.removeReferenceWrapper();
446
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 const QualType rhsType = rhs.type.removeReferenceWrapper();
447
448
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 return {validateBinaryOperation(node, SHIFT_RIGHT_OP_RULES, std::size(SHIFT_RIGHT_OP_RULES), ">>", lhsType, rhsType)};
449 }
450
451 2178 ExprResult OpRuleManager::getPlusResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
452 // Check is there is an overloaded operator function available
453
1/2
✓ Branch 1 taken 2178 times.
✗ Branch 2 not taken.
2178 const ExprResult result = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_PLUS, {lhs, rhs}, opIdx);
454
3/4
✓ Branch 1 taken 2178 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 46 times.
✓ Branch 4 taken 2132 times.
2178 if (!result.type.is(TY_INVALID))
455 46 return result;
456
457 // Remove reference wrappers
458
1/2
✓ Branch 1 taken 2132 times.
✗ Branch 2 not taken.
2132 const QualType lhsType = lhs.type.removeReferenceWrapper();
459
1/2
✓ Branch 1 taken 2132 times.
✗ Branch 2 not taken.
2132 const QualType rhsType = rhs.type.removeReferenceWrapper();
460
461 // Allow any* + <int/long/short>
462
7/10
✓ Branch 1 taken 2132 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 462 times.
✓ Branch 4 taken 1670 times.
✓ Branch 6 taken 462 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 462 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 462 times.
✓ Branch 11 taken 1670 times.
2132 if (lhsType.isPtr() && rhsType.isOneOf({TY_INT, TY_LONG, TY_SHORT})) {
463
1/2
✓ Branch 1 taken 462 times.
✗ Branch 2 not taken.
462 ensureUnsafeAllowed(node, "+", lhsType, rhsType);
464 462 return {lhsType};
465 }
466 // Allow <int/long/short> + any*
467
6/10
✓ Branch 1 taken 1670 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1635 times.
✓ Branch 4 taken 35 times.
✓ Branch 6 taken 1635 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1635 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1670 times.
1670 if (lhsType.isOneOf({TY_INT, TY_LONG, TY_SHORT}) && rhsType.isPtr()) {
468 ensureUnsafeAllowed(node, "+", lhsType, rhsType);
469 return {rhsType};
470 }
471
472
2/2
✓ Branch 1 taken 1669 times.
✓ Branch 2 taken 1 times.
1670 return {validateBinaryOperation(node, PLUS_OP_RULES, std::size(PLUS_OP_RULES), "+", lhsType, rhsType)};
473 }
474
475 1259 ExprResult OpRuleManager::getMinusResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
476 // Check is there is an overloaded operator function available
477
1/2
✓ Branch 1 taken 1259 times.
✗ Branch 2 not taken.
1259 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_MINUS, {lhs, rhs}, opIdx);
478
3/4
✓ Branch 1 taken 1259 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1258 times.
1259 if (!resultType.type.is(TY_INVALID))
479 1 return resultType;
480
481 // Remove reference wrappers
482
1/2
✓ Branch 1 taken 1258 times.
✗ Branch 2 not taken.
1258 const QualType lhsType = lhs.type.removeReferenceWrapper();
483
1/2
✓ Branch 1 taken 1258 times.
✗ Branch 2 not taken.
1258 const QualType rhsType = rhs.type.removeReferenceWrapper();
484
485 // Allow any* - <int/long/short>
486
3/10
✓ Branch 1 taken 1258 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1258 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1258 times.
1258 if (lhsType.isPtr() && rhsType.isOneOf({TY_INT, TY_LONG, TY_SHORT})) {
487 ensureUnsafeAllowed(node, "-", lhsType, rhsType);
488 return {lhs};
489 }
490 // Allow <int/long/short> - any*
491
6/10
✓ Branch 1 taken 1258 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1250 times.
✓ Branch 4 taken 8 times.
✓ Branch 6 taken 1250 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1250 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1258 times.
1258 if (lhsType.isOneOf({TY_INT, TY_LONG, TY_SHORT}) && rhsType.isPtr()) {
492 ensureUnsafeAllowed(node, "-", lhsType, rhsType);
493 return {rhs};
494 }
495
496
1/2
✓ Branch 1 taken 1258 times.
✗ Branch 2 not taken.
1258 return {validateBinaryOperation(node, MINUS_OP_RULES, std::size(MINUS_OP_RULES), "-", lhsType, rhsType)};
497 }
498
499 654 ExprResult OpRuleManager::getMulResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
500 // Check is there is an overloaded operator function available
501
1/2
✓ Branch 1 taken 654 times.
✗ Branch 2 not taken.
654 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_MUL, {lhs, rhs}, opIdx);
502
3/4
✓ Branch 1 taken 654 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 645 times.
654 if (!resultType.type.is(TY_INVALID))
503 9 return resultType;
504
505 // Remove reference wrappers
506
1/2
✓ Branch 1 taken 645 times.
✗ Branch 2 not taken.
645 const QualType lhsType = lhs.type.removeReferenceWrapper();
507
1/2
✓ Branch 1 taken 645 times.
✗ Branch 2 not taken.
645 const QualType rhsType = rhs.type.removeReferenceWrapper();
508
509
2/2
✓ Branch 1 taken 644 times.
✓ Branch 2 taken 1 times.
645 return {validateBinaryOperation(node, MUL_OP_RULES, std::size(MUL_OP_RULES), "*", lhsType, rhsType)};
510 }
511
512 205 ExprResult OpRuleManager::getDivResultType(ASTNode *node, const ExprResult &lhs, const ExprResult &rhs, size_t opIdx) {
513 // Check is there is an overloaded operator function available
514
1/2
✓ Branch 1 taken 205 times.
✗ Branch 2 not taken.
205 const ExprResult resultType = isOperatorOverloadingFctAvailable<2>(node, OP_FCT_DIV, {lhs, rhs}, opIdx);
515
3/4
✓ Branch 1 taken 205 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 202 times.
205 if (!resultType.type.is(TY_INVALID))
516 3 return resultType;
517
518 // Remove reference wrappers
519
1/2
✓ Branch 1 taken 202 times.
✗ Branch 2 not taken.
202 const QualType lhsType = lhs.type.removeReferenceWrapper();
520
1/2
✓ Branch 1 taken 202 times.
✗ Branch 2 not taken.
202 const QualType rhsType = rhs.type.removeReferenceWrapper();
521
522
1/2
✓ Branch 1 taken 202 times.
✗ Branch 2 not taken.
202 return {validateBinaryOperation(node, DIV_OP_RULES, std::size(DIV_OP_RULES), "/", lhsType, rhsType)};
523 }
524
525 9 ExprResult OpRuleManager::getRemResultType(const ASTNode *node, const ExprResult &lhs, const ExprResult &rhs) {
526 // Remove reference wrappers
527
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 const QualType lhsType = lhs.type.removeReferenceWrapper();
528
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 const QualType rhsType = rhs.type.removeReferenceWrapper();
529
530
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
18 return {validateBinaryOperation(node, REM_OP_RULES, std::size(REM_OP_RULES), "%", lhsType, rhsType)};
531 }
532
533 16 QualType OpRuleManager::getPrefixMinusResultType(const ASTNode *node, const ExprResult &lhs) {
534 // Remove reference wrappers
535
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 const QualType lhsType = lhs.type.removeReferenceWrapper();
536
537
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
32 return validateUnaryOperation(node, PREFIX_MINUS_OP_RULES, std::size(PREFIX_MINUS_OP_RULES), "-", lhsType);
538 }
539
540 28 QualType OpRuleManager::getPrefixPlusPlusResultType(const ASTNode *node, const ExprResult &lhs) const {
541 // Check if we try to assign a constant value
542
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 ensureNoConstAssign(node, lhs.type);
543
544 // Remove reference wrappers
545
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 const QualType lhsType = lhs.type.removeReferenceWrapper();
546
547 // Check if this is an unsafe operation
548
2/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
28 if (lhsType.isPtr()) {
549 ensureUnsafeAllowed(node, "++", lhsType);
550 return lhsType;
551 }
552
553
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 return validateUnaryOperation(node, PREFIX_PLUS_PLUS_OP_RULES, std::size(PREFIX_PLUS_PLUS_OP_RULES), "++", lhsType);
554 }
555
556 7 QualType OpRuleManager::getPrefixMinusMinusResultType(const ASTNode *node, const ExprResult &lhs) const {
557 // Check if we try to assign a constant value
558
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 ensureNoConstAssign(node, lhs.type);
559
560 // Remove reference wrappers
561
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 const QualType lhsType = lhs.type.removeReferenceWrapper();
562
563 // Check if this is an unsafe operation
564
2/4
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
7 if (lhsType.isPtr()) {
565 ensureUnsafeAllowed(node, "--", lhsType);
566 return lhsType;
567 }
568
569
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 times.
7 return validateUnaryOperation(node, PREFIX_MINUS_MINUS_OP_RULES, std::size(PREFIX_MINUS_MINUS_OP_RULES), "--", lhsType);
570 }
571
572 561 QualType OpRuleManager::getPrefixNotResultType(const ASTNode *node, const ExprResult &lhs) {
573 // Remove reference wrappers
574
1/2
✓ Branch 1 taken 561 times.
✗ Branch 2 not taken.
561 const QualType lhsType = lhs.type.removeReferenceWrapper();
575
576
1/2
✓ Branch 1 taken 561 times.
✗ Branch 2 not taken.
1122 return validateUnaryOperation(node, PREFIX_NOT_OP_RULES, std::size(PREFIX_NOT_OP_RULES), "!", lhsType);
577 }
578
579 1 QualType OpRuleManager::getPrefixBitwiseNotResultType(const ASTNode *node, const ExprResult &lhs) {
580 // Remove reference wrappers
581
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const QualType lhsType = lhs.type.removeReferenceWrapper();
582
583
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 return validateUnaryOperation(node, PREFIX_BITWISE_NOT_OP_RULES, std::size(PREFIX_BITWISE_NOT_OP_RULES), "~", lhsType);
584 }
585
586 162 QualType OpRuleManager::getPrefixMulResultType(const ASTNode *node, const ExprResult &lhs) {
587 // Remove reference wrappers
588
1/2
✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
162 const QualType lhsType = lhs.type.removeReferenceWrapper();
589
590
2/4
✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 162 times.
162 if (!lhsType.isPtr())
591 throw SemanticError(node, OPERATOR_WRONG_DATA_TYPE, "Cannot apply de-referencing operator on type " + lhsType.getName(true));
592
1/2
✓ Branch 1 taken 162 times.
✗ Branch 2 not taken.
324 return lhsType.getContained();
593 }
594
595 63 QualType OpRuleManager::getPrefixBitwiseAndResultType(const ASTNode *node, const ExprResult &lhs) {
596 // Remove reference wrappers
597
1/2
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
63 const QualType lhsType = lhs.type.removeReferenceWrapper();
598
599
1/2
✓ Branch 1 taken 63 times.
✗ Branch 2 not taken.
126 return lhsType.toPtr(node);
600 }
601
602 1353 ExprResult OpRuleManager::getPostfixPlusPlusResultType(ASTNode *node, const ExprResult &lhs, size_t opIdx) {
603 // Check is there is an overloaded operator function available
604
1/2
✓ Branch 1 taken 1353 times.
✗ Branch 2 not taken.
1353 const ExprResult resultType = isOperatorOverloadingFctAvailable<1>(node, OP_FCT_POSTFIX_PLUS_PLUS, {lhs}, opIdx);
605
3/4
✓ Branch 1 taken 1353 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 1344 times.
1353 if (!resultType.type.is(TY_INVALID))
606 9 return resultType;
607
608 // Check if we try to assign a constant value
609
1/2
✓ Branch 1 taken 1344 times.
✗ Branch 2 not taken.
1344 ensureNoConstAssign(node, lhs.type);
610
611 // Remove reference wrappers
612
1/2
✓ Branch 1 taken 1344 times.
✗ Branch 2 not taken.
1344 const QualType lhsType = lhs.type.removeReferenceWrapper();
613
614 // Check if this is an unsafe operation
615
3/4
✓ Branch 1 taken 1344 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1343 times.
1344 if (lhsType.isPtr()) {
616
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ensureUnsafeAllowed(node, "++", lhsType);
617 1 return {lhs};
618 }
619
620
2/2
✓ Branch 1 taken 1342 times.
✓ Branch 2 taken 1 times.
1343 return {validateUnaryOperation(node, POSTFIX_PLUS_PLUS_OP_RULES, std::size(POSTFIX_PLUS_PLUS_OP_RULES), "++", lhsType)};
621 }
622
623 270 ExprResult OpRuleManager::getPostfixMinusMinusResultType(ASTNode *node, const ExprResult &lhs, size_t opIdx) {
624 // Check is there is an overloaded operator function available
625
1/2
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
270 const ExprResult resultType = isOperatorOverloadingFctAvailable<1>(node, OP_FCT_POSTFIX_MINUS_MINUS, {lhs}, opIdx);
626
3/4
✓ Branch 1 taken 270 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 264 times.
270 if (!resultType.type.is(TY_INVALID))
627 6 return resultType;
628
629 // Check if we try to assign a constant value
630
1/2
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
264 ensureNoConstAssign(node, lhs.type);
631
632 // Remove reference wrappers
633
1/2
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
264 const QualType lhsType = lhs.type.removeReferenceWrapper();
634
635 // Check if this is an unsafe operation
636
3/4
✓ Branch 1 taken 264 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 263 times.
264 if (lhsType.isPtr()) {
637
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 ensureUnsafeAllowed(node, "--", lhsType);
638 1 return {lhs};
639 }
640
641
1/2
✓ Branch 1 taken 263 times.
✗ Branch 2 not taken.
263 return {validateUnaryOperation(node, POSTFIX_MINUS_MINUS_OP_RULES, std::size(POSTFIX_MINUS_MINUS_OP_RULES), "--", lhsType)};
642 }
643
644 2357 QualType OpRuleManager::getCastResultType(const ASTNode *node, QualType lhsType, const ExprResult &rhs) const {
645 // Remove reference wrappers
646
1/2
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
2357 lhsType = lhsType.removeReferenceWrapper();
647
1/2
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
2357 QualType rhsType = rhs.type.removeReferenceWrapper();
648
649 // Only allow to cast the 'heap' specifier away, if we are in unsafe mode
650
2/2
✓ Branch 2 taken 91 times.
✓ Branch 3 taken 2266 times.
2357 if (lhsType.getSpecifiers().isHeap != rhsType.getSpecifiers().isHeap)
651
1/2
✓ Branch 1 taken 91 times.
✗ Branch 2 not taken.
91 ensureUnsafeAllowed(node, "(cast)", lhsType, rhsType);
652
653 // Allow identity casts
654
3/4
✓ Branch 1 taken 2357 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1006 times.
✓ Branch 4 taken 1351 times.
2357 if (lhsType.matches(rhsType, false, true, true))
655 1006 return lhsType;
656 // Allow casts string -> char* and string -> char[]
657
12/16
✓ Branch 1 taken 1351 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 900 times.
✓ Branch 4 taken 451 times.
✓ Branch 6 taken 900 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 900 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 707 times.
✓ Branch 12 taken 193 times.
✓ Branch 14 taken 707 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 703 times.
✓ Branch 17 taken 4 times.
✓ Branch 18 taken 703 times.
✓ Branch 19 taken 648 times.
1351 if (lhsType.isOneOf({TY_PTR, TY_ARRAY}) && lhsType.getContained().is(TY_CHAR) && rhsType.is(TY_STRING))
658 703 return lhsType;
659 // Allow casts char* -> string and char[] -> string
660
10/16
✓ Branch 1 taken 648 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 77 times.
✓ Branch 4 taken 571 times.
✓ Branch 6 taken 77 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 77 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 77 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 77 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 77 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 77 times.
✓ Branch 19 taken 571 times.
648 if (lhsType.is(TY_STRING) && rhsType.isOneOf({TY_PTR, TY_ARRAY}) && rhsType.getContained().is(TY_CHAR))
661 77 return lhsType;
662 // Allow casts any* -> any*
663
7/10
✓ Branch 1 taken 571 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 197 times.
✓ Branch 4 taken 374 times.
✓ Branch 6 taken 197 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 197 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 197 times.
✓ Branch 11 taken 374 times.
571 if (lhsType.isOneOf({TY_PTR, TY_STRING}) && rhsType.isOneOf({TY_PTR, TY_STRING})) {
664
2/4
✓ Branch 1 taken 197 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 197 times.
✗ Branch 4 not taken.
197 if (lhsType != rhsType)
665
1/2
✓ Branch 1 taken 197 times.
✗ Branch 2 not taken.
197 ensureUnsafeAllowed(node, "(cast)", lhsType, rhsType);
666 197 return lhsType;
667 }
668 // Check primitive type combinations
669
1/2
✓ Branch 1 taken 374 times.
✗ Branch 2 not taken.
374 return validateBinaryOperation(node, CAST_OP_RULES, std::size(CAST_OP_RULES), "(cast)", lhsType, rhsType, true);
670 }
671
672 template <size_t N>
673 19840 ExprResult OpRuleManager::isOperatorOverloadingFctAvailable(ASTNode *node, const char *const fctName,
674 const std::array<ExprResult, N> &op, size_t opIdx) {
675 19840 Scope *calleeParentScope = nullptr;
676 19840 const Function *callee = nullptr;
677
7/10
✓ Branch 1 taken 9920 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9920 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9920 times.
✗ Branch 8 not taken.
✓ Branch 11 taken 27464 times.
✓ Branch 12 taken 563 times.
✓ Branch 15 taken 68581 times.
✓ Branch 16 taken 9357 times.
211930 for (const auto &sourceFile : typeChecker->resourceManager.sourceFiles | std::views::values) {
678 // Check if there is a registered operator function
679
4/6
✓ Branch 2 taken 68581 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 68581 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 40554 times.
✓ Branch 9 taken 28027 times.
411486 if (!sourceFile->getNameRegistryEntry(fctName))
680 81108 continue;
681
682 // Match callees in the global scope of this source file
683 56054 calleeParentScope = sourceFile->globalScope.get();
684
1/2
✓ Branch 1 taken 28027 times.
✗ Branch 2 not taken.
56054 const QualType thisType(TY_DYN);
685
1/2
✓ Branch 1 taken 28027 times.
✗ Branch 2 not taken.
56054 ArgList args(N);
686
1/2
✓ Branch 2 taken 28027 times.
✗ Branch 3 not taken.
56054 args[0] = {typeChecker->mapLocalTypeToImportedScopeType(calleeParentScope, op[0].type), op[0].isTemporary()};
687 if constexpr (N == 2)
688
1/2
✓ Branch 2 taken 26592 times.
✗ Branch 3 not taken.
53184 args[1] = {typeChecker->mapLocalTypeToImportedScopeType(calleeParentScope, op[1].type), op[1].isTemporary()};
689
2/4
✓ Branch 2 taken 28027 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 28027 times.
✗ Branch 6 not taken.
168162 callee = FunctionManager::match(typeChecker, calleeParentScope, fctName, thisType, args, {}, false, node);
690
2/2
✓ Branch 0 taken 563 times.
✓ Branch 1 taken 27464 times.
56054 if (callee)
691 1126 break;
692 }
693
694 // Return invalid type if the callee was not found
695
2/2
✓ Branch 0 taken 9357 times.
✓ Branch 1 taken 563 times.
19840 if (!callee)
696 18714 return ExprResult(QualType(TY_INVALID));
697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 563 times.
1126 assert(calleeParentScope != nullptr);
698
699 // Save the pointer to the operator function in the AST node
700 1126 std::vector<const Function *> &opFctPointers = typeChecker->getOpFctPointers(node);
701
2/2
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 544 times.
1126 if (opFctPointers.size() <= opIdx)
702
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
38 opFctPointers.resize(opIdx + 1, nullptr);
703 1126 opFctPointers.at(opIdx) = callee;
704
705 // Check if we need to request a re-visit, because the function body was not type-checked yet
706 1126 typeChecker->requestRevisitIfRequired(callee);
707
708 // Check if the called function has sufficient visibility
709
3/4
✓ Branch 0 taken 563 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 243 times.
✓ Branch 4 taken 320 times.
1126 const bool isImported = calleeParentScope != nullptr && calleeParentScope->isImportedBy(typeChecker->rootScope);
710 1126 const SymbolTableEntry *calleeEntry = callee->entry;
711
4/6
✓ Branch 0 taken 243 times.
✓ Branch 1 taken 320 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 243 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 563 times.
1126 if (isImported && !calleeEntry->getQualType().isPublic())
712 throw SemanticError(node, INSUFFICIENT_VISIBILITY,
713 "Overloaded operator '" + callee->getSignature() + "' has insufficient visibility");
714
715 // Procedures always have the return type 'bool'
716
2/2
✓ Branch 0 taken 134 times.
✓ Branch 1 taken 429 times.
1126 if (callee->isProcedure())
717 268 return ExprResult(QualType(TY_BOOL));
718
719 // Add anonymous symbol to keep track of de-allocation
720 858 SymbolTableEntry *anonymousSymbol = nullptr;
721
2/2
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 368 times.
858 if (callee->returnType.is(TY_STRUCT))
722 122 anonymousSymbol = typeChecker->currentScope->symbolTable.insertAnonymous(callee->returnType, node, opIdx);
723
724 858 return {typeChecker->mapImportedScopeTypeToLocalType(calleeParentScope, callee->returnType), anonymousSymbol};
725 }
726
727 2219 QualType OpRuleManager::validateUnaryOperation(const ASTNode *node, const UnaryOpRule opRules[], size_t opRulesSize,
728 const char *name, const QualType &lhs) {
729
2/2
✓ Branch 0 taken 5284 times.
✓ Branch 1 taken 2 times.
5286 for (size_t i = 0; i < opRulesSize; i++) {
730 5284 const UnaryOpRule &rule = opRules[i];
731
2/2
✓ Branch 2 taken 2217 times.
✓ Branch 3 taken 3067 times.
5284 if (std::get<0>(rule) == lhs.getSuperType())
732
1/2
✓ Branch 2 taken 2217 times.
✗ Branch 3 not taken.
2217 return QualType(std::get<1>(rule));
733 }
734
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 throw getExceptionUnary(node, name, lhs);
735 }
736
737 23446 QualType OpRuleManager::validateBinaryOperation(const ASTNode *node, const BinaryOpRule opRules[], size_t opRulesSize,
738 const char *name, const QualType &lhs, const QualType &rhs,
739 bool preserveSpecifiersFromLhs, const char *customMessagePrefix) {
740
2/2
✓ Branch 0 taken 216646 times.
✓ Branch 1 taken 19 times.
216665 for (size_t i = 0; i < opRulesSize; i++) {
741 216646 const BinaryOpRule &rule = opRules[i];
742
6/6
✓ Branch 2 taken 46808 times.
✓ Branch 3 taken 169838 times.
✓ Branch 6 taken 23427 times.
✓ Branch 7 taken 23381 times.
✓ Branch 8 taken 23427 times.
✓ Branch 9 taken 193219 times.
216646 if (std::get<0>(rule) == lhs.getSuperType() && std::get<1>(rule) == rhs.getSuperType()) {
743
1/2
✓ Branch 2 taken 23427 times.
✗ Branch 3 not taken.
23427 QualType resultType((std::get<2>(rule)));
744
2/2
✓ Branch 0 taken 13659 times.
✓ Branch 1 taken 9768 times.
23427 if (preserveSpecifiersFromLhs)
745 13659 resultType.setSpecifiers(lhs.getSpecifiers());
746 23427 return resultType;
747 }
748 }
749
1/2
✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
19 throw getExceptionBinary(node, name, lhs, rhs, customMessagePrefix);
750 }
751
752 2 SemanticError OpRuleManager::getExceptionUnary(const ASTNode *node, const char *name, const QualType &lhs) {
753
6/12
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 2 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
8 return {node, OPERATOR_WRONG_DATA_TYPE, "Cannot apply '" + std::string(name) + "' operator on type " + lhs.getName(true)};
754 }
755
756 19 SemanticError OpRuleManager::getExceptionBinary(const ASTNode *node, const char *name, const QualType &lhs, const QualType &rhs,
757 const char *messagePrefix) {
758 // Build error message
759
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 std::stringstream errorMsg;
760
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 15 times.
19 if (strlen(messagePrefix) != 0)
761
7/14
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 4 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 4 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 4 times.
✗ Branch 20 not taken.
4 errorMsg << messagePrefix << ". Expected " << lhs.getName(true) << " but got " << rhs.getName(true);
762 else
763
8/16
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 15 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 15 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 15 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 15 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 15 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 15 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 15 times.
✗ Branch 23 not taken.
15 errorMsg << "Cannot apply '" << name << "' operator on types " << lhs.getName(true) << " and " << rhs.getName(true);
764
765 // Return the exception
766
2/4
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
57 return {node, OPERATOR_WRONG_DATA_TYPE, errorMsg.str()};
767 19 }
768
769 2 void OpRuleManager::ensureUnsafeAllowed(const ASTNode *node, const char *name, const QualType &lhs) const {
770
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
2 if (typeChecker->currentScope->doesAllowUnsafeOperations())
771 2 return;
772 // Print error message
773 const std::string lhsName = lhs.getName(true);
774 const std::string errorMsg = "Cannot apply '" + std::string(name) + "' operator on type " + lhsName +
775 " as this is an unsafe operation. Please use unsafe blocks if you know what you are doing.";
776 SOFT_ERROR_VOID(node, UNSAFE_OPERATION_IN_SAFE_CONTEXT, errorMsg)
777 }
778
779 752 void OpRuleManager::ensureUnsafeAllowed(const ASTNode *node, const char *name, const QualType &lhs, const QualType &rhs) const {
780
3/4
✓ Branch 1 taken 752 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 751 times.
✓ Branch 4 taken 1 times.
752 if (typeChecker->currentScope->doesAllowUnsafeOperations())
781 751 return;
782 // Print error message
783
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const std::string lhsName = lhs.getName(true);
784
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 const std::string rhsName = rhs.getName(true);
785
6/12
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
2 const std::string errorMsg = "Cannot apply '" + std::string(name) + "' operator on types " + lhsName + " and " + rhsName +
786
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 " as this is an unsafe operation. Please use unsafe blocks if you know what you are doing.";
787
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 SOFT_ERROR_VOID(node, UNSAFE_OPERATION_IN_SAFE_CONTEXT, errorMsg)
788 1 }
789
790 19730 void OpRuleManager::ensureNoConstAssign(const ASTNode *node, const QualType &lhs, bool isDecl, bool isReturn) {
791 // Check if we try to assign a constant value
792
10/12
✓ Branch 1 taken 19730 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19730 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2797 times.
✓ Branch 7 taken 16933 times.
✓ Branch 8 taken 15 times.
✓ Branch 9 taken 2782 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 13 times.
✓ Branch 12 taken 2 times.
✓ Branch 13 taken 19728 times.
19730 if (lhs.removeReferenceWrapper().isConst() && !isDecl && !isReturn) {
793
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
2 const std::string errorMessage = "Trying to assign value to an immutable variable of type " + lhs.getName(true);
794
1/2
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
2 throw SemanticError(node, REASSIGN_CONST_VARIABLE, errorMessage);
795 2 }
796 19728 }
797
798 } // namespace spice::compiler
799