Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -696,6 +696,7 @@ // in -Wparentheses because most users who use -Wparentheses explicitly // do not want these warnings. def ParenthesesOnEquality : DiagGroup<"parentheses-equality">; +def AssigmentInBoolContext : DiagGroup<"assigment-in-bool-context">; def Parentheses : DiagGroup<"parentheses", [LogicalOpParentheses, LogicalNotParentheses, @@ -703,7 +704,8 @@ ShiftOpParentheses, OverloadedShiftOpParentheses, ParenthesesOnEquality, - DanglingElse]>; + DanglingElse, + AssigmentInBoolContext]>; // -Wconversion has its own warnings, but we split a few out for // legacy reasons: Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -6733,9 +6733,9 @@ def err_incomplete_object_call : Error< "incomplete type in call to object of type %0">; -def warn_condition_is_assignment : Warning<"using the result of an " - "assignment as a condition without parentheses">, - InGroup; +def warn_condition_is_assignment : Warning<"converting the result of an " + "assignment to bool">, + InGroup; // Completely identical except off by default. def warn_condition_is_idiomatic_assignment : Warning<"using the result " "of an assignment as a condition without parentheses">, Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -4136,6 +4136,7 @@ } case ICK_Boolean_Conversion: + DiagnoseAssignmentAsCondition(From->IgnoreImpCasts()); // Perform half-to-boolean conversion via float. if (From->getType()->isHalfType()) { From = ImpCastExprToType(From, Context.FloatTy, CK_FloatingCast).get(); Index: test/CodeCompletion/crash-skipped-bodies-template-inst.cpp =================================================================== --- test/CodeCompletion/crash-skipped-bodies-template-inst.cpp +++ test/CodeCompletion/crash-skipped-bodies-template-inst.cpp @@ -6,7 +6,7 @@ int x; if (x = 10) {} // Check that body of this function is actually skipped. - // CHECK-NOT: crash-skipped-bodies-template-inst.cpp:7:{{[0-9]+}}: warning: using the result of an assignment as a condition without parentheses + // CHECK-NOT: crash-skipped-bodies-template-inst.cpp:7:{{[0-9]+}}: warning: converting the result of an assignment to bool return this; } }; @@ -14,7 +14,7 @@ int x; if (x = 10) {} // Check that this function is not skipped. - // CHECK: crash-skipped-bodies-template-inst.cpp:15:9: warning: using the result of an assignment as a condition without parentheses + // CHECK: crash-skipped-bodies-template-inst.cpp:15:9: warning: converting the result of an assignment to bool return impl(); } Index: test/CodeCompletion/skip-auto-funcs.cpp =================================================================== --- test/CodeCompletion/skip-auto-funcs.cpp +++ test/CodeCompletion/skip-auto-funcs.cpp @@ -7,7 +7,7 @@ int x; if (x = 10) {} // Check that this function is not skipped. - // CHECK: 8:9: warning: using the result of an assignment as a condition without parentheses + // CHECK: 8:9: warning: converting the result of an assignment to bool return 1; } @@ -16,7 +16,7 @@ int x; if (x = 10) {} // Check that this function is not skipped. - // CHECK: 17:9: warning: using the result of an assignment as a condition without parentheses + // CHECK: 17:9: warning: converting the result of an assignment to bool return 1; } @@ -25,7 +25,7 @@ int x; if (x = 10) {} // Check that this function is skipped. - // CHECK-NOT: 26:9: warning: using the result of an assignment as a condition without parentheses + // CHECK-NOT: 26:9: warning: converting the result of an assignment to bool return 1; }; @@ -33,7 +33,7 @@ int x; if (x = 10) {} // This could potentially be skipped, but it isn't at the moment. - // CHECK: 34:9: warning: using the result of an assignment as a condition without parentheses + // CHECK: 34:9: warning: converting the result of an assignment to bool return 1; }; @@ -42,7 +42,7 @@ int x; if (x = 10) {} // Check that this function is not skipped. - // CHECK: 43:9: warning: using the result of an assignment as a condition without parentheses + // CHECK: 43:9: warning: converting the result of an assignment to bool return T(); } @@ -51,7 +51,7 @@ int x; if (x = 10) {} // Check that this function is not skipped. - // CHECK: 52:9: warning: using the result of an assignment as a condition without parentheses + // CHECK: 52:9: warning: converting the result of an assignment to bool return 1; } Index: test/Modules/diag-pragma.c =================================================================== --- test/Modules/diag-pragma.c +++ test/Modules/diag-pragma.c @@ -6,7 +6,7 @@ @import diag_pragma; int foo(int x) { - if (x = DIAG_PRAGMA_MACRO) // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + if (x = DIAG_PRAGMA_MACRO) // expected-warning {{converting the result of an assignment to bool}} \ // expected-note {{place parentheses}} expected-note {{use '=='}} return 0; return 1; Index: test/Modules/diag-pragma.cpp =================================================================== --- test/Modules/diag-pragma.cpp +++ test/Modules/diag-pragma.cpp @@ -40,7 +40,7 @@ void("bar" + x); - if (x = DIAG_PRAGMA_MACRO) // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + if (x = DIAG_PRAGMA_MACRO) // expected-warning {{converting the result of an assignment to bool}} \ // expected-note {{place parentheses}} expected-note {{use '=='}} return 0; return 1; Index: test/Sema/assigment-in-bool-context.c =================================================================== --- test/Sema/assigment-in-bool-context.c +++ test/Sema/assigment-in-bool-context.c @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -Wassigment-in-bool-context -fsyntax-only -verify %s +// RUN: %clang_cc1 -Wparentheses -fsyntax-only -verify %s + +_Bool warn1(int x) { + return x = 0; +} + +_Bool warn2(int x, _Bool a, _Bool b) { + return x = 0 || (a && b); +} + +_Bool warn3(int x, _Bool a) { + return x = 0 || a; +} + +_Bool warn4(int x) { + return _Bool(x = 0); // expected-error {{expected expression}} +} + +int warn5(int x) { + return _Bool(x = 0); // expected-error {{expected expression}} +} + +_Bool warn6(int x, int a) { + return x = a; +} + +int nowarn1(int x) { + return (x = 0); +} + +int nowarn2(int x) { + return x = 0; +} + +int nowarn3(int x) { + return x == 0; +} + +_Bool nowarn4(int x) { + return x == 0; +} Index: test/Sema/parentheses.c =================================================================== --- test/Sema/parentheses.c +++ test/Sema/parentheses.c @@ -4,7 +4,7 @@ // Test the various warnings under -Wparentheses void if_assign(void) { int i; - if (i = 4) {} // expected-warning {{assignment as a condition}} \ + if (i = 4) {} // expected-warning {{converting the result of an assignment to bool}} \ // 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]]:7-[[@LINE-3]]:7}:"(" @@ -145,6 +145,3 @@ (void)(x + y > 0 ? 1 : 2); // no warning (void)(x + (y > 0) ? 1 : 2); // expected-warning {{operator '?:' has lower precedence than '+'}} expected-note 2{{place parentheses}} } - -// RUN: not %clang_cc1 -fsyntax-only -Wparentheses -Werror -fdiagnostics-show-option %s 2>&1 | FileCheck %s -check-prefix=CHECK-FLAG -// CHECK-FLAG: error: using the result of an assignment as a condition without parentheses [-Werror,-Wparentheses] Index: test/SemaCXX/assigment-in-bool-context.cpp =================================================================== --- test/SemaCXX/assigment-in-bool-context.cpp +++ test/SemaCXX/assigment-in-bool-context.cpp @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -Wassigment-in-bool-context -fsyntax-only -verify %s +// RUN: %clang_cc1 -Wparentheses -fsyntax-only -verify %s + +bool warn1(int x) { + return x = 0; // expected-warning {{converting the result of an assignment to bool}} + // expected-note@-1 {{place parentheses around the assignment to silence this warning}} + // expected-note@-2 {{use '==' to turn this assignment into an equality comparison}} +} + +bool warn2(int x, bool a, bool b) { + return x = 0 || (a && b); // expected-warning {{converting the result of an assignment to bool}} + // expected-note@-1 {{place parentheses around the assignment to silence this warning}} + // expected-note@-2 {{use '==' to turn this assignment into an equality comparison}} +} + +bool warn3(int x, bool a) { + return x = 0 || a; // expected-warning {{converting the result of an assignment to bool}} + // expected-note@-1 {{place parentheses around the assignment to silence this warning}} + // expected-note@-2 {{use '==' to turn this assignment into an equality comparison}} +} + +bool warn4(int x) { + return bool(x = 0); // expected-warning {{converting the result of an assignment to bool}} + // expected-note@-1 {{place parentheses around the assignment to silence this warning}} + // expected-note@-2 {{use '==' to turn this assignment into an equality comparison}} +} + +int warn5(int x) { + return bool(x = 0); // expected-warning {{converting the result of an assignment to bool}} + // expected-note@-1 {{place parentheses around the assignment to silence this warning}} + // expected-note@-2 {{use '==' to turn this assignment into an equality comparison}} +} + +bool warn6(int x, int a) { + return x = a; // expected-warning {{converting the result of an assignment to bool}} + // expected-note@-1 {{place parentheses around the assignment to silence this warning}} + // expected-note@-2 {{use '==' to turn this assignment into an equality comparison}} +} + +int nowarn1(int x) { + return (x = 0); +} + +int nowarn2(int x) { + return x = 0; +} + +int nowarn3(int x) { + return x == 0; +} + +bool nowarn4(int x) { + return x == 0; +} Index: test/SemaCXX/warn-assignment-condition.cpp =================================================================== --- test/SemaCXX/warn-assignment-condition.cpp +++ test/SemaCXX/warn-assignment-condition.cpp @@ -12,41 +12,41 @@ A a, b; // With scalars. - if (x = 7) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + if (x = 7) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} if ((x = 7)) {} do { - } while (x = 7); // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + } while (x = 7); // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} do { } while ((x = 7)); - while (x = 7) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + while (x = 7) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} while ((x = 7)) {} - for (; x = 7; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + for (; x = 7; ) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} for (; (x = 7); ) {} - if (p = p) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + if (p = p) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} if ((p = p)) {} do { - } while (p = p); // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + } while (p = p); // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} do { } while ((p = p)); - while (p = p) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + while (p = p) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} while ((p = p)) {} - for (; p = p; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + for (; p = p; ) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} for (; (p = p); ) {} @@ -58,51 +58,51 @@ while (A y = a) {} // With temporaries. - if (x = (b+b).foo()) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + if (x = (b+b).foo()) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} if ((x = (b+b).foo())) {} do { - } while (x = (b+b).foo()); // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + } while (x = (b+b).foo()); // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} do { } while ((x = (b+b).foo())); - while (x = (b+b).foo()) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + while (x = (b+b).foo()) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} while ((x = (b+b).foo())) {} - for (; x = (b+b).foo(); ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + for (; x = (b+b).foo(); ) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} for (; (x = (b+b).foo()); ) {} // With a user-defined operator. - if (a = b + b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + if (a = b + b) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} if ((a = b + b)) {} do { - } while (a = b + b); // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + } while (a = b + b); // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} do { } while ((a = b + b)); - while (a = b + b) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + while (a = b + b) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} while ((a = b + b)) {} - for (; a = b + b; ) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + for (; a = b + b; ) {} // expected-warning {{converting the result of an assignment to 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}} \ + if (x |= 2) {} // expected-warning {{converting the result of an assignment to bool}} \ // 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}} \ + if (a |= b) {} // expected-warning {{converting the result of an assignment to bool}} \ // expected-note{{use '!=' to turn this compound assignment into an inequality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} Index: test/SemaObjC/idiomatic-parentheses.m =================================================================== --- test/SemaObjC/idiomatic-parentheses.m +++ test/SemaObjC/idiomatic-parentheses.m @@ -27,7 +27,7 @@ if (self = [self initWithInt: i]) { } // rdar://11066598 - if (self.uid = 100) { // expected-warning {{using the result of an assignment as a condition without parentheses}} \ + if (self.uid = 100) { // expected-warning {{converting the result of an assignment to bool}} \ // expected-note {{place parentheses around the assignment to silence this warning}} \ // expected-note {{use '==' to turn this assignment into an equality comparison}} // ... Index: test/SemaObjC/self-assign.m =================================================================== --- test/SemaObjC/self-assign.m +++ test/SemaObjC/self-assign.m @@ -6,7 +6,7 @@ - (id):(int)x :(int)y { int z; // - if (self = [self :x :y]) {} // expected-warning{{using the result of an assignment as a condition without parentheses}} \ + if (self = [self :x :y]) {} // expected-warning{{converting the result of an assignment to bool}} \ // expected-note{{use '==' to turn this assignment into an equality comparison}} \ // expected-note{{place parentheses around the assignment to silence this warning}} return self;