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 {
5454 override predicate isWhitelisted ( ) {
5555 this .getConversion ( ) .( ParenthesisExpr ) .isParenthesised ( )
5656 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
5858 // assignment is part of, are not parenthesized. In that case it seems like programmer
5959 // is fine with unparenthesized comparison operands to binary logical operators, and
6060 // the parenthesis around this assignment was used to call it out as an assignment.
6161 this .isParenthesised ( ) and
6262 forex ( ComparisonOperation op | op = getComparisonOperand * ( this .getParent + ( ) ) |
6363 not op .isParenthesised ( )
6464 )
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+ )
6580 }
6681}
6782
Original file line number Diff line number Diff line change 1919| test.cpp:144:32:144:36 | ... = ... | Use of '=' where '==' may have been intended. |
2020| test.cpp:150:32:150:36 | ... = ... | Use of '=' where '==' may have been intended. |
2121| 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. |
2622| test.cpp:166:22:166:27 | ... = ... | Use of '=' where '==' may have been intended. |
2723| test.cpp:168:24:168:29 | ... = ... | Use of '=' where '==' may have been intended. |
2824| 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) {
157157bool use (int );
158158
159159void 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
161161 // 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
165165
166166 if (use (x) && b && (x = 10 )) {} // BAD: The assignment is the last thing that happens in the comparison.
167167 // This doesn't match the usual pattern.
You can’t perform that action at this time.
0 commit comments