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">;
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())) {
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.
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, ")");
struct A {
int foo();
friend A operator+(const A&, const A&);
+ A operator|=(const A&);
operator bool();
};
// 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}}
}