diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 316db752153d37f247b970d1eef5f6239fa03cb6..1a9d694805b3e2693dd2a700238e9ee83e3b464b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2853,6 +2853,13 @@ def note_condition_or_assign_to_comparison : Note< def note_condition_assign_silence : Note< "place parentheses around the assignment to silence this warning">; +def warn_equality_with_extra_parens : Warning<"equality comparison with " + "extraneous parentheses">, InGroup; +def note_equality_comparison_to_assign : Note< + "use '=' to turn this equality comparison into an assignment">; +def note_equality_comparison_silence : Note< + "remove extraneous parentheses around the comparison to silence this warning">; + def warn_synthesized_ivar_access : Warning< "direct access of synthesized ivar by using property access %0">, InGroup, DefaultIgnore; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f8cabf9c5f80849523b232b73ca8445f33405f8a..908d1a1ca6877ac6ecfbc19a13ea0f33172f7664 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4734,6 +4734,10 @@ public: /// being used as a boolean condition, warn if it's an assignment. void DiagnoseAssignmentAsCondition(Expr *E); + /// \brief Redundant parentheses over an equality comparison can indicate + /// that the user intended an assignment used as condition. + void DiagnoseEqualityWithExtraParens(ParenExpr *parenE); + /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. bool CheckCXXBooleanCondition(Expr *&CondExpr); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 21bf4203e3e641cdb41e9851e389321cef2511c0..82771298e0ae0287f80fdebdf8cf107595008795 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -9225,8 +9225,30 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) { << FixItHint::CreateInsertion(Close, ")"); } +/// \brief Redundant parentheses over an equality comparison can indicate +/// that the user intended an assignment used as condition. +void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *parenE) { + Expr *E = parenE->IgnoreParens(); + + if (BinaryOperator *opE = dyn_cast(E)) + if (opE->getOpcode() == BO_EQ) { + SourceLocation Loc = opE->getOperatorLoc(); + + Diag(Loc, diag::warn_equality_with_extra_parens) << E->getSourceRange(); + + Diag(Loc, diag::note_equality_comparison_to_assign) + << FixItHint::CreateReplacement(Loc, "="); + + Diag(Loc, diag::note_equality_comparison_silence) + << FixItHint::CreateRemoval(parenE->getSourceRange().getBegin()) + << FixItHint::CreateRemoval(parenE->getSourceRange().getEnd()); + } +} + bool Sema::CheckBooleanCondition(Expr *&E, SourceLocation Loc) { DiagnoseAssignmentAsCondition(E); + if (ParenExpr *parenE = dyn_cast(E)) + DiagnoseEqualityWithExtraParens(parenE); if (!E->isTypeDependent()) { if (E->isBoundMemberFunction(Context)) diff --git a/clang/test/Analysis/self-init.m b/clang/test/Analysis/self-init.m index 1e16e41d7a9a192aeaaf76de46b80bcf193060b6..1dc5aa92f9c3953ab3df219c3fabc80557ae304d 100644 --- a/clang/test/Analysis/self-init.m +++ b/clang/test/Analysis/self-init.m @@ -135,7 +135,7 @@ extern void *somePtr; } -(id)init13 { - if ((self == [super init])) { + if (self == [super init]) { myivar = 0; // expected-warning {{Instance variable used}} } return self; // expected-warning {{Returning 'self'}} diff --git a/clang/test/SemaCXX/warn-assignment-condition.cpp b/clang/test/SemaCXX/warn-assignment-condition.cpp index 9dcffbfe84e8cd48cb8176b1739b19ab824f7996..48cc137dac732bfa7294cce9b05e9180512c0ebe 100644 --- a/clang/test/SemaCXX/warn-assignment-condition.cpp +++ b/clang/test/SemaCXX/warn-assignment-condition.cpp @@ -105,4 +105,8 @@ void test() { 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}} + + if ((x == 5)) {} // expected-warning {{equality comparison with extraneous parentheses}} \ + // expected-note {{use '=' to turn this equality comparison into an assignment}} \ + // expected-note {{remove extraneous parentheses around the comparison to silence this warning}} }