File tree Expand file tree Collapse file tree 3 files changed +20
-9
lines changed
src/Likely Bugs/Likely Typos
test/query-tests/Likely Bugs/Likely Typos/AssignWhereCompareMeant Expand file tree Collapse file tree 3 files changed +20
-9
lines changed Original file line number Diff line number Diff line change @@ -54,14 +54,29 @@ class BooleanControllingAssignmentInExpr extends BooleanControllingAssignment {
54
54
override predicate isWhitelisted ( ) {
55
55
this .getConversion ( ) .( ParenthesisExpr ) .isParenthesised ( )
56
56
or
57
- // whitelist this assignment if all comparison operations in the expression that this
57
+ // Allow this assignment if all comparison operations in the expression that this
58
58
// assignment is part of, are not parenthesized. In that case it seems like programmer
59
59
// is fine with unparenthesized comparison operands to binary logical operators, and
60
60
// the parenthesis around this assignment was used to call it out as an assignment.
61
61
this .isParenthesised ( ) and
62
62
forex ( ComparisonOperation op | op = getComparisonOperand * ( this .getParent + ( ) ) |
63
63
not op .isParenthesised ( )
64
64
)
65
+ or
66
+ // Match a pattern like:
67
+ // ```
68
+ // if((a = b) && use_value(a)) { ... }
69
+ // ```
70
+ // where the assignment is meant to update the value of `a` before it's used in some other boolean
71
+ // subexpression that is guarenteed to be evaluate _after_ the assignment.
72
+ this .isParenthesised ( ) and
73
+ exists ( LogicalAndExpr parent , Variable var , VariableAccess access |
74
+ var = this .getLValue ( ) .( VariableAccess ) .getTarget ( ) and
75
+ access = var .getAnAccess ( ) and
76
+ not access .isUsedAsLValue ( ) and
77
+ parent .getRightOperand ( ) = access .getParent * ( ) and
78
+ parent .getLeftOperand ( ) = this .getParent * ( )
79
+ )
65
80
}
66
81
}
67
82
Original file line number Diff line number Diff line change 19
19
| test.cpp:144:32:144:36 | ... = ... | Use of '=' where '==' may have been intended. |
20
20
| test.cpp:150:32:150:36 | ... = ... | Use of '=' where '==' may have been intended. |
21
21
| test.cpp:153:46:153:50 | ... = ... | Use of '=' where '==' may have been intended. |
22
- | test.cpp:160:7:160:12 | ... = ... | Use of '=' where '==' may have been intended. |
23
- | test.cpp:162:7:162:12 | ... = ... | Use of '=' where '==' may have been intended. |
24
- | test.cpp:163:7:163:12 | ... = ... | Use of '=' where '==' may have been intended. |
25
- | test.cpp:164:7:164:12 | ... = ... | Use of '=' where '==' may have been intended. |
26
22
| test.cpp:166:22:166:27 | ... = ... | Use of '=' where '==' may have been intended. |
27
23
| test.cpp:168:24:168:29 | ... = ... | Use of '=' where '==' may have been intended. |
28
24
| test.cpp:169:23:169:28 | ... = ... | Use of '=' where '==' may have been intended. |
Original file line number Diff line number Diff line change @@ -157,11 +157,11 @@ void f3(int x, int y) {
157
157
bool use (int );
158
158
159
159
void f4 (int x, bool b) {
160
- if ((x = 10 ) && use (x)) {} // GOOD [FALSE POSITIVE] : This is likely just a short-hand way of writing an assignment
160
+ if ((x = 10 ) && use (x)) {} // GOOD: This is likely just a short-hand way of writing an assignment
161
161
// followed by a boolean check.
162
- if ((x = 10 ) && b && use (x)) {} // GOOD [FALSE POSITIVE] : Same reason as above
163
- if ((x = 10 ) && use (x) && b) {} // GOOD [FALSE POSITIVE] : Same reason as above
164
- if ((x = 10 ) && (use (x) && b)) {} // GOOD [FALSE POSITIVE] : Same reason as above
162
+ if ((x = 10 ) && b && use (x)) {} // GOOD: Same reason as above
163
+ if ((x = 10 ) && use (x) && b) {} // GOOD: Same reason as above
164
+ if ((x = 10 ) && (use (x) && b)) {} // GOOD: Same reason as above
165
165
166
166
if (use (x) && b && (x = 10 )) {} // BAD: The assignment is the last thing that happens in the comparison.
167
167
// This doesn't match the usual pattern.
You can’t perform that action at this time.
0 commit comments