m4tx created this revision. m4tx added reviewers: lebedev.ri, rsmith, klimek. Herald added a project: clang. Herald added a subscriber: cfe-commits.
int x; return x = 5; For a code like above, GCC produces a warning suggesting using parentheses about the assignment. This change makes clang produce similar warning to, suggesting either changing the operator to `==`, or wrap the expression inside parentheses. This is based off D45401 <https://reviews.llvm.org/D45401>. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D63089 Files: clang/lib/Sema/SemaChecking.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/test/Sema/parentheses.c clang/test/Sema/parentheses.cpp Index: clang/test/Sema/parentheses.cpp =================================================================== --- clang/test/Sema/parentheses.cpp +++ 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); +} Index: clang/test/Sema/parentheses.c =================================================================== --- clang/test/Sema/parentheses.c +++ 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}} \ Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ 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; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ 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<ParenExpr>(E)) DiagnoseEqualityWithExtraParens(parenE); Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ 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<ImplicitCastExpr>(RetValExp)) { + DiagnoseAssignmentAsCondition(CastExpr->IgnoreImpCasts()); + } + } } //===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
Index: clang/test/Sema/parentheses.cpp =================================================================== --- clang/test/Sema/parentheses.cpp +++ 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); +} Index: clang/test/Sema/parentheses.c =================================================================== --- clang/test/Sema/parentheses.c +++ 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}} \ Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ 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; Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ 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<ParenExpr>(E)) DiagnoseEqualityWithExtraParens(parenE); Index: clang/lib/Sema/SemaChecking.cpp =================================================================== --- clang/lib/Sema/SemaChecking.cpp +++ 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<ImplicitCastExpr>(RetValExp)) { + DiagnoseAssignmentAsCondition(CastExpr->IgnoreImpCasts()); + } + } } //===--- CHECK: Floating-Point comparisons (-Wfloat-equal) ---------------===//
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits