diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-19 16:50:08 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-19 16:50:08 +0000 |
commit | 92c3a04f3ec683f279814b0eb6d6271b3fd3a219 (patch) | |
tree | 8aa282a17c24cd6659392c07d93b76226de96dae | |
parent | 9ea416e598fa3cb09d67d514c4519c99abb81321 (diff) |
Warn about the use of unparenthesized |= in conditionals (which may be
a typo for !=). Fixes PR9001, from Hans Wennborg!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123836 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 20 | ||||
-rw-r--r-- | test/SemaCXX/warn-assignment-condition.cpp | 10 |
3 files changed, 27 insertions, 5 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1c1600a735..870a0e0205 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2796,6 +2796,8 @@ def warn_condition_is_idiomatic_assignment : Warning<"using the result " InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore; def note_condition_assign_to_comparison : Note< "use '==' to turn this assignment into an equality comparison">; +def note_condition_or_assign_to_comparison : Note< + "use '!=' to turn this compound assignment into an inequality comparison">; def note_condition_assign_silence : Note< "place parentheses around the assignment to silence this warning">; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index deb0bb2b6c..e84e0e11fb 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -9118,18 +9118,21 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc, return false; } -// Diagnose the common s/=/==/ typo. Note that adding parentheses +// Diagnose the s/=/==/ and s/\|=/!=/ typos. Note that adding parentheses // will prevent this condition from triggering, which is what we want. void Sema::DiagnoseAssignmentAsCondition(Expr *E) { SourceLocation Loc; unsigned diagnostic = diag::warn_condition_is_assignment; + bool IsOrAssign = false; if (isa<BinaryOperator>(E)) { BinaryOperator *Op = cast<BinaryOperator>(E); - if (Op->getOpcode() != BO_Assign) + if (Op->getOpcode() != BO_Assign && Op->getOpcode() != BO_OrAssign) return; + IsOrAssign = Op->getOpcode() == BO_OrAssign; + // Greylist some idioms by putting them into a warning subcategory. if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) { @@ -9149,9 +9152,10 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { Loc = Op->getOperatorLoc(); } else if (isa<CXXOperatorCallExpr>(E)) { CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(E); - if (Op->getOperator() != OO_Equal) + if (Op->getOperator() != OO_Equal && Op->getOperator() != OO_PipeEqual) return; + IsOrAssign = Op->getOperator() == OO_PipeEqual; Loc = Op->getOperatorLoc(); } else { // Not an assignment. @@ -9162,8 +9166,14 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd()); Diag(Loc, diagnostic) << E->getSourceRange(); - Diag(Loc, diag::note_condition_assign_to_comparison) - << FixItHint::CreateReplacement(Loc, "=="); + + if (IsOrAssign) + Diag(Loc, diag::note_condition_or_assign_to_comparison) + << FixItHint::CreateReplacement(Loc, "!="); + else + Diag(Loc, diag::note_condition_assign_to_comparison) + << FixItHint::CreateReplacement(Loc, "=="); + Diag(Loc, diag::note_condition_assign_silence) << FixItHint::CreateInsertion(Open, "(") << FixItHint::CreateInsertion(Close, ")"); diff --git a/test/SemaCXX/warn-assignment-condition.cpp b/test/SemaCXX/warn-assignment-condition.cpp index e5a3425804..9dcffbfe84 100644 --- a/test/SemaCXX/warn-assignment-condition.cpp +++ b/test/SemaCXX/warn-assignment-condition.cpp @@ -3,6 +3,7 @@ struct A { int foo(); friend A operator+(const A&, const A&); + A operator|=(const A&); operator bool(); }; @@ -95,4 +96,13 @@ void test() { // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} for (; (a = b + b); ) {} + + // Compound assignments. + if (x |= 2) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + // expected-note{{use '!=' to turn this compound assignment into an inequality comparison}} \ + // expected-note{{place parentheses around the assignment to silence this warning}} + + if (a |= b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + // expected-note{{use '!=' to turn this compound assignment into an inequality comparison}} \ + // expected-note{{place parentheses around the assignment to silence this warning}} } |