diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -9700,6 +9700,13 @@ << FD << getLangOpts().CPlusPlus11; } } + + // C++ implicit casts are checked inside PerformImplicitConversion + if (!getLangOpts().CPlusPlus) { + if (ImplicitCastExpr *CastExpr = dyn_cast(RetValExp)) { + DiagnoseAssignmentAsCondition(CastExpr->IgnoreImpCasts()); + } + } } //===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===// diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -16375,7 +16375,10 @@ ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr) { - DiagnoseAssignmentAsCondition(E); + // C++ implicit casts are checked inside PerformImplicitConversion + if (!getLangOpts().CPlusPlus) { + DiagnoseAssignmentAsCondition(E); + } if (ParenExpr *parenE = dyn_cast(E)) DiagnoseEqualityWithExtraParens(parenE); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3926,6 +3926,11 @@ FromType = From->getType(); } + // Warn on assignments inside implicit casts (= instead of ==) + if (SCS.Second == ICK_Boolean_Conversion || FromType == Context.BoolTy) { + DiagnoseAssignmentAsCondition(From->IgnoreImpCasts()); + } + // If we're converting to an atomic type, first convert to the corresponding // non-atomic type. QualType ToAtomicType; diff --git a/clang/test/Sema/parentheses.c b/clang/test/Sema/parentheses.c --- a/clang/test/Sema/parentheses.c +++ b/clang/test/Sema/parentheses.c @@ -14,6 +14,18 @@ if ((i = 4)) {} } +_Bool return_assign(void) { + int i; + return i = 4; // expected-warning {{assignment as a condition}} \ + // expected-note{{place parentheses around the assignment to silence this warning}} \ + // expected-note{{use '==' to turn this assignment into an equality comparison}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:10}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:15-[[@LINE-4]]:15}:")" + // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:12-[[@LINE-5]]:13}:"==" + + return (i = 4); +} + void bitwise_rel(unsigned i) { (void)(i & 0x2 == 0); // expected-warning {{& has lower precedence than ==}} \ // expected-note{{place parentheses around the '==' expression to silence this warning}} \ diff --git a/clang/test/Sema/parentheses.cpp b/clang/test/Sema/parentheses.cpp --- a/clang/test/Sema/parentheses.cpp +++ b/clang/test/Sema/parentheses.cpp @@ -215,3 +215,15 @@ // fix-it:"{{.*}}":{[[@LINE-9]]:20-[[@LINE-9]]:20}:")" } } + +bool return_assign() { + int i; + return i = 4; // expected-warning {{assignment as a condition}} \ + // expected-note{{place parentheses around the assignment to silence this warning}} \ + // expected-note{{use '==' to turn this assignment into an equality comparison}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:10}:"(" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:15-[[@LINE-4]]:15}:")" + // CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:12-[[@LINE-5]]:13}:"==" + + return (i = 4); +}