From: Douglas Gregor Date: Wed, 19 Jan 2011 16:50:08 +0000 (+0000) Subject: Warn about the use of unparenthesized |= in conditionals (which may be X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=92c3a04f3ec683f279814b0eb6d6271b3fd3a219;p=clang 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 --- 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>, 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(E)) { BinaryOperator *Op = cast(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(Op->getRHS()->IgnoreParenCasts())) { @@ -9149,9 +9152,10 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { Loc = Op->getOperatorLoc(); } else if (isa(E)) { CXXOperatorCallExpr *Op = cast(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}} }