[clang] [clang] Added warn-assignment-bool-context (PR #115234)

Philipp Rados via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 25 09:51:18 PST 2025


https://github.com/PhilippRados updated https://github.com/llvm/llvm-project/pull/115234

>From e819360e6510f12f19b7df9d4eb22c0943776440 Mon Sep 17 00:00:00 2001
From: PhilippR <phil.black at gmx.net>
Date: Thu, 7 Nov 2024 00:06:24 +0100
Subject: [PATCH 1/5] [clang] Added warn-assignment-bool-context

This warning is issued if an assignment is used in a context
where a boolean result is required.
---
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 ++
 clang/include/clang/Sema/Sema.h               |  2 +
 clang/lib/Sema/Sema.cpp                       | 53 +++++++++++++++++++
 clang/lib/Sema/SemaExpr.cpp                   |  6 ++-
 .../test/Sema/warn-assignment-bool-context.c  | 35 ++++++++++++
 .../SemaCXX/warn-assignment-bool-context.cpp  | 45 ++++++++++++++++
 6 files changed, 143 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Sema/warn-assignment-bool-context.c
 create mode 100644 clang/test/SemaCXX/warn-assignment-bool-context.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ae3e243bdc58b..4ba4327bde5cf 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8477,6 +8477,9 @@ def err_incomplete_object_call : Error<
 def warn_condition_is_assignment : Warning<"using the result of an "
   "assignment as a condition without parentheses">,
   InGroup<Parentheses>;
+def warn_assignment_bool_context : Warning<"suggest parentheses around assignment used as truth value">,
+  InGroup<Parentheses>;
+
 def warn_free_nonheap_object
   : Warning<"attempt to call %0 on non-heap %select{object %2|object: block expression|object: lambda-to-function-pointer conversion}1">,
     InGroup<FreeNonHeapObject>;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 93d98e1cbb9c8..6bf73956d3f94 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7232,6 +7232,8 @@ class Sema final : public SemaBase {
   /// being used as a boolean condition, warn if it's an assignment.
   void DiagnoseAssignmentAsCondition(Expr *E);
 
+  void DiagnoseAssignmentBoolContext(Expr *E, QualType ToType);
+
   /// Redundant parentheses over an equality comparison can indicate
   /// that the user intended an assignment used as condition.
   void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE);
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 2b51765e80864..a8e4657ac0b6e 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -687,6 +687,48 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E) {
       << FixItHint::CreateReplacement(E->getSourceRange(), "nullptr");
 }
 
+void Sema::DiagnoseAssignmentBoolContext(Expr *E, QualType Ty) {
+  // Use copy to not alter original expression.
+  Expr *ECopy = E;
+
+  if (Ty->isBooleanType()) {
+    // `bool(x=0)` and if (x=0){} emit:
+    // - ImplicitCastExpr bool IntegralToBoolean
+    // -- ImplicitCastExpr int LValueToRValue
+    // --- Assignment ...
+    // But should still emit this warning (at least gcc does), even if bool-cast
+    // is not directly followed by assignment.
+    // NOTE: Is this robust enough or can there be other semantic expression
+    // until the assignment?
+    while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ECopy)) {
+      // If there is another implicit cast to bool then this warning would have
+      // been already emitted.
+      if (ICE->getType()->isBooleanType())
+        return;
+      ECopy = ICE->getSubExpr();
+    }
+
+    if (BinaryOperator *Op = dyn_cast<BinaryOperator>(ECopy)) {
+      // Should only be issued for regular assignment `=`,
+      // not for compound-assign like `+=`.
+      // NOTE: Might make sense to emit for all assignments even if gcc
+      // only does for regular assignment.
+      if (Op->getOpcode() == BO_Assign) {
+        SourceLocation Loc = Op->getOperatorLoc();
+        Diag(Loc, diag::warn_assignment_bool_context)
+            << ECopy->getSourceRange();
+
+        SourceLocation Open = ECopy->getBeginLoc();
+        SourceLocation Close =
+            getLocForEndOfToken(ECopy->getSourceRange().getEnd());
+        Diag(Loc, diag::note_condition_assign_silence)
+            << FixItHint::CreateInsertion(Open, "(")
+            << FixItHint::CreateInsertion(Close, ")");
+      }
+    }
+  }
+}
+
 /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast.
 /// If there is already an implicit cast, merge into the existing one.
 /// The result is of the given category.
@@ -761,6 +803,17 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
     }
   }
 
+  // FIXME: Doesn't include C89, so this warning isn't emitted when passing
+  // `std=c89`.
+  auto isC = getLangOpts().C99 || getLangOpts().C11 || getLangOpts().C17 ||
+             getLangOpts().C23;
+  // Do not emit this warning for Objective-C, since it's a common idiom.
+  // NOTE: Are there other languages that this could affect besides C and C++?
+  // Ideally would check `getLangOpts().Cplusplus || getLangOpts().C` but there
+  // is no option for C (only C99 etc.).
+  if ((getLangOpts().CPlusPlus || isC) && !getLangOpts().ObjC)
+    DiagnoseAssignmentBoolContext(E, Ty);
+
   if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
     if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
       ImpCast->setType(Ty);
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 49fdb5b5ab43d..bee8751c3fa7a 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -20287,7 +20287,11 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
 
 ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E,
                                        bool IsConstexpr) {
-  DiagnoseAssignmentAsCondition(E);
+  // This warning is already covered by `warn_assignment_bool_context` in C++.
+  // NOTE: Ideally both warnings would be combined
+  if (!getLangOpts().CPlusPlus || getLangOpts().ObjC)
+    DiagnoseAssignmentAsCondition(E);
+
   if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
     DiagnoseEqualityWithExtraParens(parenE);
 
diff --git a/clang/test/Sema/warn-assignment-bool-context.c b/clang/test/Sema/warn-assignment-bool-context.c
new file mode 100644
index 0000000000000..bf746e0bed2c2
--- /dev/null
+++ b/clang/test/Sema/warn-assignment-bool-context.c
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -Wparentheses -verify %s
+
+// NOTE: Don't know if tests allow includes.
+#include <stdbool.h>
+
+// Do not emit the warning for compound-assignments. 
+bool f(int x) { return x = 0; }  // expected-warning {{suggest parentheses around assignment used as truth value}}\
+                                 // expected-note{{place parentheses around the assignment to silence this warning}}
+bool f2(int x) { return x += 0; }
+
+bool f3(bool x) { return x = 0; }
+
+void test() {
+  int x;
+
+  // This should emit the `warn_condition_is_assignment` warning, since
+  // C doesn't do implicit conversion booleans for conditions.
+  if (x = 0) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
+                // expected-note{{place parentheses around the assignment to silence this warning}}\
+                // expected-note{{use '==' to turn this assignment into an equality comparison}}
+  if (x = 4 && x){} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
+                    // expected-note{{place parentheses around the assignment to silence this warning}}\
+                    // expected-note{{use '==' to turn this assignment into an equality comparison}}
+
+  (void)(bool)(x = 1);
+  (void)(bool)(int)(x = 1);
+
+
+  bool _a = x = 3; // expected-warning {{suggest parentheses around assignment used as truth value}}\
+                   // expected-note{{place parentheses around the assignment to silence this warning}}
+
+  // Shouldn't warn for above cases if parentheses were provided.
+  if ((x = 0)) {}
+  bool _b = (x = 3);
+}
diff --git a/clang/test/SemaCXX/warn-assignment-bool-context.cpp b/clang/test/SemaCXX/warn-assignment-bool-context.cpp
new file mode 100644
index 0000000000000..a4831f53e311b
--- /dev/null
+++ b/clang/test/SemaCXX/warn-assignment-bool-context.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wparentheses -verify %s
+
+// Do not emit the warning for compound-assignments. 
+bool f(int x) { return x = 0; }  // expected-warning {{suggest parentheses around assignment used as truth value}} \
+                                 // expected-note{{place parentheses around the assignment to silence this warning}}
+bool f2(int x) { return x += 0; }
+
+bool f3(bool x) { return x = 0; }
+
+void test() {
+  int x;
+
+  // Assignemnts inside of conditions should still emit the more specific `warn_condition_is_assignment` warning.
+  if (x = 0) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
+                // expected-note{{use '==' to turn this assignment into an equality comparison}} \
+                // expected-note{{place parentheses around the assignment to silence this warning}}
+  if (x = 4 && x){} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
+                    // expected-note{{use '==' to turn this assignment into an equality comparison}} \
+                    // expected-note{{place parentheses around the assignment to silence this warning}}
+
+
+  (void)bool(x = 1); // expected-warning {{suggest parentheses around assignment used as truth value}}\
+                     // expected-note{{place parentheses around the assignment to silence this warning}}
+  (void)(bool)(x = 1);
+
+  // This should still emit since the RHS is casted to `int` before being casted back to `bool`.
+  (void)bool(x = false); // expected-warning {{suggest parentheses around assignment used as truth value}} \
+                         // expected-note{{place parentheses around the assignment to silence this warning}}
+
+  // Should only issue warning once, even if multiple implicit casts.
+  // FIXME: This only checks that warning occurs not how often.
+  (void)bool(bool(x = 1)); // expected-warning {{suggest parentheses around assignment used as truth value}} \
+                           // expected-note{{place parentheses around the assignment to silence this warning}}
+  (void)bool(int(bool(x = 1))); // expected-warning {{suggest parentheses around assignment used as truth value}} \
+                                // expected-note{{place parentheses around the assignment to silence this warning}}
+  (void)bool(int(x = 1));
+
+  bool _a = x = 3; // expected-warning {{suggest parentheses around assignment used as truth value}} \
+                   // expected-note{{place parentheses around the assignment to silence this warning}}
+
+  // Shouldn't warn for above cases if parentheses were provided.
+  if ((x = 0)) {}
+  (void)bool((x = 1));
+  bool _b= (x = 3);
+}

>From 2a06e37ac54d5b47221f9923dcfe4111bfc72ea0 Mon Sep 17 00:00:00 2001
From: PhilippR <phil.black at gmx.net>
Date: Sat, 22 Feb 2025 20:11:43 +0100
Subject: [PATCH 2/5] [clang] Store condition info in Expr; Passes all tests

---
 clang/include/clang/AST/Expr.h                |  3 +-
 .../clang/Basic/DiagnosticSemaKinds.td        |  2 +-
 clang/lib/Sema/Sema.cpp                       | 32 +++++++------------
 clang/lib/Sema/SemaExpr.cpp                   |  6 ++--
 .../test/Sema/warn-assignment-bool-context.c  |  9 +++---
 .../SemaCXX/warn-assignment-bool-context.cpp  | 14 ++++----
 6 files changed, 28 insertions(+), 38 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 466c65a9685ad..2d4771bbc1022 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -116,10 +116,11 @@ class Expr : public ValueStmt {
   Expr(Expr &&) = delete;
   Expr &operator=(const Expr&) = delete;
   Expr &operator=(Expr&&) = delete;
+  bool isCondition;
 
 protected:
   Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK)
-      : ValueStmt(SC) {
+      : ValueStmt(SC), isCondition(false) {
     ExprBits.Dependent = 0;
     ExprBits.ValueKind = VK;
     ExprBits.ObjectKind = OK;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4ba4327bde5cf..70aa54f541819 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8477,7 +8477,7 @@ def err_incomplete_object_call : Error<
 def warn_condition_is_assignment : Warning<"using the result of an "
   "assignment as a condition without parentheses">,
   InGroup<Parentheses>;
-def warn_assignment_bool_context : Warning<"suggest parentheses around assignment used as truth value">,
+def warn_assignment_bool_context : Warning<"using the result of an assignment as a truth value without parentheses">,
   InGroup<Parentheses>;
 
 def warn_free_nonheap_object
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index a8e4657ac0b6e..963e96b8c607c 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -688,9 +688,6 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E) {
 }
 
 void Sema::DiagnoseAssignmentBoolContext(Expr *E, QualType Ty) {
-  // Use copy to not alter original expression.
-  Expr *ECopy = E;
-
   if (Ty->isBooleanType()) {
     // `bool(x=0)` and if (x=0){} emit:
     // - ImplicitCastExpr bool IntegralToBoolean
@@ -698,17 +695,19 @@ void Sema::DiagnoseAssignmentBoolContext(Expr *E, QualType Ty) {
     // --- Assignment ...
     // But should still emit this warning (at least gcc does), even if bool-cast
     // is not directly followed by assignment.
-    // NOTE: Is this robust enough or can there be other semantic expression
-    // until the assignment?
-    while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ECopy)) {
+    while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
       // If there is another implicit cast to bool then this warning would have
       // been already emitted.
       if (ICE->getType()->isBooleanType())
         return;
-      ECopy = ICE->getSubExpr();
+      E = ICE->getSubExpr();
     }
 
-    if (BinaryOperator *Op = dyn_cast<BinaryOperator>(ECopy)) {
+    // Condition-assignment warnings are already handled by `DiagnoseAssignmentAsCondition()`
+    if (E->isCondition)
+      return;
+
+    if (BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
       // Should only be issued for regular assignment `=`,
       // not for compound-assign like `+=`.
       // NOTE: Might make sense to emit for all assignments even if gcc
@@ -716,11 +715,11 @@ void Sema::DiagnoseAssignmentBoolContext(Expr *E, QualType Ty) {
       if (Op->getOpcode() == BO_Assign) {
         SourceLocation Loc = Op->getOperatorLoc();
         Diag(Loc, diag::warn_assignment_bool_context)
-            << ECopy->getSourceRange();
+            << E->getSourceRange();
 
-        SourceLocation Open = ECopy->getBeginLoc();
+        SourceLocation Open = E->getBeginLoc();
         SourceLocation Close =
-            getLocForEndOfToken(ECopy->getSourceRange().getEnd());
+            getLocForEndOfToken(E->getSourceRange().getEnd());
         Diag(Loc, diag::note_condition_assign_silence)
             << FixItHint::CreateInsertion(Open, "(")
             << FixItHint::CreateInsertion(Close, ")");
@@ -803,16 +802,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty,
     }
   }
 
-  // FIXME: Doesn't include C89, so this warning isn't emitted when passing
-  // `std=c89`.
-  auto isC = getLangOpts().C99 || getLangOpts().C11 || getLangOpts().C17 ||
-             getLangOpts().C23;
-  // Do not emit this warning for Objective-C, since it's a common idiom.
-  // NOTE: Are there other languages that this could affect besides C and C++?
-  // Ideally would check `getLangOpts().Cplusplus || getLangOpts().C` but there
-  // is no option for C (only C99 etc.).
-  if ((getLangOpts().CPlusPlus || isC) && !getLangOpts().ObjC)
-    DiagnoseAssignmentBoolContext(E, Ty);
+  DiagnoseAssignmentBoolContext(E, Ty);
 
   if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) {
     if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index bee8751c3fa7a..f195c0ce45f97 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -20287,10 +20287,8 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
 
 ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E,
                                        bool IsConstexpr) {
-  // This warning is already covered by `warn_assignment_bool_context` in C++.
-  // NOTE: Ideally both warnings would be combined
-  if (!getLangOpts().CPlusPlus || getLangOpts().ObjC)
-    DiagnoseAssignmentAsCondition(E);
+  DiagnoseAssignmentAsCondition(E);
+  E->isCondition = true;
 
   if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
     DiagnoseEqualityWithExtraParens(parenE);
diff --git a/clang/test/Sema/warn-assignment-bool-context.c b/clang/test/Sema/warn-assignment-bool-context.c
index bf746e0bed2c2..fdefc82eab97a 100644
--- a/clang/test/Sema/warn-assignment-bool-context.c
+++ b/clang/test/Sema/warn-assignment-bool-context.c
@@ -1,10 +1,11 @@
 // RUN: %clang_cc1 -x c -fsyntax-only -Wparentheses -verify %s
 
-// NOTE: Don't know if tests allow includes.
-#include <stdbool.h>
+#define bool _Bool
+#define true 1
+#define false 0
 
 // Do not emit the warning for compound-assignments. 
-bool f(int x) { return x = 0; }  // expected-warning {{suggest parentheses around assignment used as truth value}}\
+bool f(int x) { return x = 0; }  // expected-warning {{using the result of an assignment as a truth value without parentheses}}\
                                  // expected-note{{place parentheses around the assignment to silence this warning}}
 bool f2(int x) { return x += 0; }
 
@@ -26,7 +27,7 @@ void test() {
   (void)(bool)(int)(x = 1);
 
 
-  bool _a = x = 3; // expected-warning {{suggest parentheses around assignment used as truth value}}\
+  bool _a = x = 3; // expected-warning {{using the result of an assignment as a truth value without parentheses}}\
                    // expected-note{{place parentheses around the assignment to silence this warning}}
 
   // Shouldn't warn for above cases if parentheses were provided.
diff --git a/clang/test/SemaCXX/warn-assignment-bool-context.cpp b/clang/test/SemaCXX/warn-assignment-bool-context.cpp
index a4831f53e311b..2973f7ef38290 100644
--- a/clang/test/SemaCXX/warn-assignment-bool-context.cpp
+++ b/clang/test/SemaCXX/warn-assignment-bool-context.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -x c++ -fsyntax-only -Wparentheses -verify %s
 
 // Do not emit the warning for compound-assignments. 
-bool f(int x) { return x = 0; }  // expected-warning {{suggest parentheses around assignment used as truth value}} \
+bool f(int x) { return x = 0; }  // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                                  // expected-note{{place parentheses around the assignment to silence this warning}}
 bool f2(int x) { return x += 0; }
 
@@ -10,7 +10,7 @@ bool f3(bool x) { return x = 0; }
 void test() {
   int x;
 
-  // Assignemnts inside of conditions should still emit the more specific `warn_condition_is_assignment` warning.
+  // Assignments inside of conditions should still emit the more specific `warn_condition_is_assignment` warning.
   if (x = 0) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
                 // expected-note{{use '==' to turn this assignment into an equality comparison}} \
                 // expected-note{{place parentheses around the assignment to silence this warning}}
@@ -19,23 +19,23 @@ void test() {
                     // expected-note{{place parentheses around the assignment to silence this warning}}
 
 
-  (void)bool(x = 1); // expected-warning {{suggest parentheses around assignment used as truth value}}\
+  (void)bool(x = 1); // expected-warning {{using the result of an assignment as a truth value without parentheses}}\
                      // expected-note{{place parentheses around the assignment to silence this warning}}
   (void)(bool)(x = 1);
 
   // This should still emit since the RHS is casted to `int` before being casted back to `bool`.
-  (void)bool(x = false); // expected-warning {{suggest parentheses around assignment used as truth value}} \
+  (void)bool(x = false); // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                          // expected-note{{place parentheses around the assignment to silence this warning}}
 
   // Should only issue warning once, even if multiple implicit casts.
   // FIXME: This only checks that warning occurs not how often.
-  (void)bool(bool(x = 1)); // expected-warning {{suggest parentheses around assignment used as truth value}} \
+  (void)bool(bool(x = 1)); // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                            // expected-note{{place parentheses around the assignment to silence this warning}}
-  (void)bool(int(bool(x = 1))); // expected-warning {{suggest parentheses around assignment used as truth value}} \
+  (void)bool(int(bool(x = 1))); // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                                 // expected-note{{place parentheses around the assignment to silence this warning}}
   (void)bool(int(x = 1));
 
-  bool _a = x = 3; // expected-warning {{suggest parentheses around assignment used as truth value}} \
+  bool _a = x = 3; // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                    // expected-note{{place parentheses around the assignment to silence this warning}}
 
   // Shouldn't warn for above cases if parentheses were provided.

>From 419fb2a6b41817f55c129a87f8ba6822576103ee Mon Sep 17 00:00:00 2001
From: PhilippR <phil.black at gmx.net>
Date: Mon, 24 Feb 2025 21:08:37 +0100
Subject: [PATCH 3/5] [clang] Changed IsInsideCondition field to private

---
 clang/include/clang/AST/Expr.h | 14 ++++++++++++--
 clang/lib/Sema/Sema.cpp        |  2 +-
 clang/lib/Sema/SemaExpr.cpp    |  2 +-
 3 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 2d4771bbc1022..a44cdb2715b03 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -109,6 +109,7 @@ struct SubobjectAdjustment {
 /// required.
 class Expr : public ValueStmt {
   QualType TR;
+  bool IsInsideCondition;
 
 public:
   Expr() = delete;
@@ -116,11 +117,10 @@ class Expr : public ValueStmt {
   Expr(Expr &&) = delete;
   Expr &operator=(const Expr&) = delete;
   Expr &operator=(Expr&&) = delete;
-  bool isCondition;
 
 protected:
   Expr(StmtClass SC, QualType T, ExprValueKind VK, ExprObjectKind OK)
-      : ValueStmt(SC), isCondition(false) {
+      : ValueStmt(SC), IsInsideCondition(false) {
     ExprBits.Dependent = 0;
     ExprBits.ValueKind = VK;
     ExprBits.ObjectKind = OK;
@@ -451,6 +451,16 @@ class Expr : public ValueStmt {
     return (OK == OK_Ordinary || OK == OK_BitField);
   }
 
+  bool isInsideCondition() const {
+    return IsInsideCondition;
+  }
+
+  /// setValueKind - Mark this expression to be inside a condition.
+  /// necessary for `warn_assignment_bool_context` diagnostic
+  void setIsInsideCondition() {
+    IsInsideCondition = true;
+  }
+
   /// setValueKind - Set the value kind produced by this expression.
   void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; }
 
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 963e96b8c607c..e4cdc01c31bff 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -704,7 +704,7 @@ void Sema::DiagnoseAssignmentBoolContext(Expr *E, QualType Ty) {
     }
 
     // Condition-assignment warnings are already handled by `DiagnoseAssignmentAsCondition()`
-    if (E->isCondition)
+    if (E->isInsideCondition())
       return;
 
     if (BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index f195c0ce45f97..672507ffdad5e 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -20288,7 +20288,7 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
 ExprResult Sema::CheckBooleanCondition(SourceLocation Loc, Expr *E,
                                        bool IsConstexpr) {
   DiagnoseAssignmentAsCondition(E);
-  E->isCondition = true;
+  E->setIsInsideCondition();
 
   if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
     DiagnoseEqualityWithExtraParens(parenE);

>From 303a9820dd8ccde03b1e9c964dfe45dc5b927f8c Mon Sep 17 00:00:00 2001
From: PhilippR <phil.black at gmx.net>
Date: Mon, 24 Feb 2025 21:36:45 +0100
Subject: [PATCH 4/5] [clang] Formatted

---
 clang/include/clang/AST/Expr.h | 8 ++------
 clang/lib/Sema/Sema.cpp        | 6 +++---
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index a44cdb2715b03..b0e4379fcf294 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -451,15 +451,11 @@ class Expr : public ValueStmt {
     return (OK == OK_Ordinary || OK == OK_BitField);
   }
 
-  bool isInsideCondition() const {
-    return IsInsideCondition;
-  }
+  bool isInsideCondition() const { return IsInsideCondition; }
 
   /// setValueKind - Mark this expression to be inside a condition.
   /// necessary for `warn_assignment_bool_context` diagnostic
-  void setIsInsideCondition() {
-    IsInsideCondition = true;
-  }
+  void setIsInsideCondition() { IsInsideCondition = true; }
 
   /// setValueKind - Set the value kind produced by this expression.
   void setValueKind(ExprValueKind Cat) { ExprBits.ValueKind = Cat; }
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index e4cdc01c31bff..86e2ed9d60ec7 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -703,7 +703,8 @@ void Sema::DiagnoseAssignmentBoolContext(Expr *E, QualType Ty) {
       E = ICE->getSubExpr();
     }
 
-    // Condition-assignment warnings are already handled by `DiagnoseAssignmentAsCondition()`
+    // Condition-assignment warnings are already handled by
+    // `DiagnoseAssignmentAsCondition()`
     if (E->isInsideCondition())
       return;
 
@@ -714,8 +715,7 @@ void Sema::DiagnoseAssignmentBoolContext(Expr *E, QualType Ty) {
       // only does for regular assignment.
       if (Op->getOpcode() == BO_Assign) {
         SourceLocation Loc = Op->getOperatorLoc();
-        Diag(Loc, diag::warn_assignment_bool_context)
-            << E->getSourceRange();
+        Diag(Loc, diag::warn_assignment_bool_context) << E->getSourceRange();
 
         SourceLocation Open = E->getBeginLoc();
         SourceLocation Close =

>From b72f7a736ea344b43db3cf5c72e9c19840ceca26 Mon Sep 17 00:00:00 2001
From: PhilippR <phil.black at gmx.net>
Date: Tue, 25 Feb 2025 18:26:17 +0100
Subject: [PATCH 5/5] [clang] Merged diagnostic warn_condition_is_assignment
 into generic warn_assignment_bool_context

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 --
 clang/lib/Sema/SemaExpr.cpp                   |  2 +-
 .../crash-skipped-bodies-template-inst.cpp    |  4 +--
 clang/test/CodeCompletion/skip-auto-funcs.cpp | 12 +++----
 clang/test/Misc/warning-flags-enabled.c       |  2 +-
 clang/test/Modules/diag-pragma.c              |  2 +-
 clang/test/Modules/diag-pragma.cpp            |  2 +-
 .../crash-skipped-bodies-template-inst.cpp    |  4 +--
 clang/test/Sema/parentheses.c                 |  4 +--
 .../test/Sema/warn-assignment-bool-context.c  |  6 ++--
 .../SemaCXX/warn-assignment-bool-context.cpp  |  6 ++--
 .../SemaCXX/warn-assignment-condition.cpp     | 36 +++++++++----------
 clang/test/SemaObjC/idiomatic-parentheses.m   |  2 +-
 clang/test/SemaObjC/self-assign.m             |  2 +-
 .../SemaOpenACC/compute-construct-if-clause.c |  2 +-
 15 files changed, 43 insertions(+), 46 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 70aa54f541819..dbd5c22bd45be 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8474,9 +8474,6 @@ def err_cannot_form_pointer_to_member_of_reference_type : Error<
 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<Parentheses>;
 def warn_assignment_bool_context : Warning<"using the result of an assignment as a truth value without parentheses">,
   InGroup<Parentheses>;
 
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 672507ffdad5e..10f53142c58b6 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -20203,7 +20203,7 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
 void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
   SourceLocation Loc;
 
-  unsigned diagnostic = diag::warn_condition_is_assignment;
+  unsigned diagnostic = diag::warn_assignment_bool_context;
   bool IsOrAssign = false;
 
   if (BinaryOperator *Op = dyn_cast<BinaryOperator>(E)) {
diff --git a/clang/test/CodeCompletion/crash-skipped-bodies-template-inst.cpp b/clang/test/CodeCompletion/crash-skipped-bodies-template-inst.cpp
index 7fec995ba061b..2922761629241 100644
--- a/clang/test/CodeCompletion/crash-skipped-bodies-template-inst.cpp
+++ b/clang/test/CodeCompletion/crash-skipped-bodies-template-inst.cpp
@@ -6,7 +6,7 @@ auto make_func() {
       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: using the result of an assignment as a truth value without parentheses
       return this;
     }
   };
@@ -14,7 +14,7 @@ auto make_func() {
   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: using the result of an assignment as a truth value without parentheses
   return impl();
 }
 
diff --git a/clang/test/CodeCompletion/skip-auto-funcs.cpp b/clang/test/CodeCompletion/skip-auto-funcs.cpp
index c0fa0f556daef..f0dccd8bd9ecd 100644
--- a/clang/test/CodeCompletion/skip-auto-funcs.cpp
+++ b/clang/test/CodeCompletion/skip-auto-funcs.cpp
@@ -7,7 +7,7 @@ auto not_skipped() {
   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: using the result of an assignment as a truth value without parentheses
   return 1;
 }
 
@@ -16,7 +16,7 @@ auto lambda_not_skipped = []() {
   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: using the result of an assignment as a truth value without parentheses
   return 1;
 }
 
@@ -25,7 +25,7 @@ auto skipped() -> T {
   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: using the result of an assignment as a truth value without parentheses
   return 1;
 };
 
@@ -33,7 +33,7 @@ auto lambda_skipped = []() -> int {
   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: using the result of an assignment as a truth value without parentheses
   return 1;
 };
 
@@ -42,7 +42,7 @@ decltype(auto)** not_skipped_ptr() {
   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: using the result of an assignment as a truth value without parentheses
   return T();
 }
 
@@ -51,7 +51,7 @@ decltype(auto) not_skipped_decltypeauto() {
   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: using the result of an assignment as a truth value without parentheses
   return 1;
 }
 
diff --git a/clang/test/Misc/warning-flags-enabled.c b/clang/test/Misc/warning-flags-enabled.c
index 9f210674b126e..085fb482cb490 100644
--- a/clang/test/Misc/warning-flags-enabled.c
+++ b/clang/test/Misc/warning-flags-enabled.c
@@ -4,7 +4,7 @@
 // We just check a few to make sure it's doing something sensible.
 //
 // CHECK: ext_unterminated_char_or_string
-// CHECK: warn_condition_is_assignment
+// CHECK: warn_assignment_bool_context
 // CHECK: warn_null_arg
 
 
diff --git a/clang/test/Modules/diag-pragma.c b/clang/test/Modules/diag-pragma.c
index 80224629a1c81..2b592d0de2af3 100644
--- a/clang/test/Modules/diag-pragma.c
+++ b/clang/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 {{using the result of an assignment as a truth value without parentheses}} \
                              // expected-note {{place parentheses}} expected-note {{use '=='}}
     return 0;
   return 1;
diff --git a/clang/test/Modules/diag-pragma.cpp b/clang/test/Modules/diag-pragma.cpp
index 4b6318045372a..45cb5ba88b2e8 100644
--- a/clang/test/Modules/diag-pragma.cpp
+++ b/clang/test/Modules/diag-pragma.cpp
@@ -40,7 +40,7 @@ int foo(int x) {
 
   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 {{using the result of an assignment as a truth value without parentheses}} \
                              // expected-note {{place parentheses}} expected-note {{use '=='}}
     return 0;
   return 1;
diff --git a/clang/test/OpenMP/crash-skipped-bodies-template-inst.cpp b/clang/test/OpenMP/crash-skipped-bodies-template-inst.cpp
index c7ba432d5090b..a9123fec9bcfe 100644
--- a/clang/test/OpenMP/crash-skipped-bodies-template-inst.cpp
+++ b/clang/test/OpenMP/crash-skipped-bodies-template-inst.cpp
@@ -9,7 +9,7 @@ auto make_func() {
         ;
       }
       // 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: using the result of an assignment as a truth value without parentheses
       return this;
     }
   };
@@ -17,7 +17,7 @@ auto make_func() {
   int x;
   if (x = 10) {}
   // Check that this function is not skipped.
-  // CHECK: crash-skipped-bodies-template-inst.cpp:18:9: warning: using the result of an assignment as a condition without parentheses
+  // CHECK: crash-skipped-bodies-template-inst.cpp:18:9: warning: using the result of an assignment as a truth value without parentheses
   return impl();
 }
 
diff --git a/clang/test/Sema/parentheses.c b/clang/test/Sema/parentheses.c
index f0090c2ee9d14..041be436adcf4 100644
--- a/clang/test/Sema/parentheses.c
+++ b/clang/test/Sema/parentheses.c
@@ -5,7 +5,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 {{assignment as a truth value}} \
                 // 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}:"("
@@ -118,4 +118,4 @@ void conditional_op(int x, int y, _Bool b, void* p) {
 }
 
 // RUN: not %clang_cc1 -fsyntax-only -Wparentheses -Werror %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]
+// CHECK-FLAG: error: using the result of an assignment as a truth value without parentheses [-Werror,-Wparentheses]
diff --git a/clang/test/Sema/warn-assignment-bool-context.c b/clang/test/Sema/warn-assignment-bool-context.c
index fdefc82eab97a..2c01c63d31bf9 100644
--- a/clang/test/Sema/warn-assignment-bool-context.c
+++ b/clang/test/Sema/warn-assignment-bool-context.c
@@ -14,12 +14,12 @@ bool f3(bool x) { return x = 0; }
 void test() {
   int x;
 
-  // This should emit the `warn_condition_is_assignment` warning, since
+  // This should emit the `warn_assignment_bool_context` warning once, since
   // C doesn't do implicit conversion booleans for conditions.
-  if (x = 0) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
+  if (x = 0) {} // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                 // expected-note{{place parentheses around the assignment to silence this warning}}\
                 // expected-note{{use '==' to turn this assignment into an equality comparison}}
-  if (x = 4 && x){} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
+  if (x = 4 && x){} // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                     // expected-note{{place parentheses around the assignment to silence this warning}}\
                     // expected-note{{use '==' to turn this assignment into an equality comparison}}
 
diff --git a/clang/test/SemaCXX/warn-assignment-bool-context.cpp b/clang/test/SemaCXX/warn-assignment-bool-context.cpp
index 2973f7ef38290..85e4b9fc2f014 100644
--- a/clang/test/SemaCXX/warn-assignment-bool-context.cpp
+++ b/clang/test/SemaCXX/warn-assignment-bool-context.cpp
@@ -10,11 +10,11 @@ bool f3(bool x) { return x = 0; }
 void test() {
   int x;
 
-  // Assignments inside of conditions should still emit the more specific `warn_condition_is_assignment` warning.
-  if (x = 0) {} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
+  // Assignments inside of conditions should still emit the more specific `==` fixits.
+  if (x = 0) {} // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                 // expected-note{{use '==' to turn this assignment into an equality comparison}} \
                 // expected-note{{place parentheses around the assignment to silence this warning}}
-  if (x = 4 && x){} // expected-warning {{using the result of an assignment as a condition without parentheses}} \
+  if (x = 4 && x){} // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                     // expected-note{{use '==' to turn this assignment into an equality comparison}} \
                     // expected-note{{place parentheses around the assignment to silence this warning}}
 
diff --git a/clang/test/SemaCXX/warn-assignment-condition.cpp b/clang/test/SemaCXX/warn-assignment-condition.cpp
index 65332846bd091..a16d77716cced 100644
--- a/clang/test/SemaCXX/warn-assignment-condition.cpp
+++ b/clang/test/SemaCXX/warn-assignment-condition.cpp
@@ -12,41 +12,41 @@ void test() {
   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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 @@ void test() {
   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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value without parentheses}} \
                 // 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 {{using the result of an assignment as a truth value 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}} \
+  if (a |= b) {} // expected-warning {{using the result of an assignment as a truth value 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}}
 
diff --git a/clang/test/SemaObjC/idiomatic-parentheses.m b/clang/test/SemaObjC/idiomatic-parentheses.m
index bed3f0ad40563..8a173678d0be4 100644
--- a/clang/test/SemaObjC/idiomatic-parentheses.m
+++ b/clang/test/SemaObjC/idiomatic-parentheses.m
@@ -25,7 +25,7 @@ - (id) init {
 - (id) initWithInt: (int) i {
   if (self = [self initWithInt: i]) {
   }
-  if (self.uid = 100) { // expected-warning {{using the result of an assignment as a condition without parentheses}} \
+  if (self.uid = 100) { // expected-warning {{using the result of an assignment as a truth value without parentheses}} \
                         // expected-note {{place parentheses around the assignment to silence this warning}} \
                         // expected-note {{use '==' to turn this assignment into an equality comparison}}
         // ...
diff --git a/clang/test/SemaObjC/self-assign.m b/clang/test/SemaObjC/self-assign.m
index d2bd3f4c81976..7b38113e88e2d 100644
--- a/clang/test/SemaObjC/self-assign.m
+++ b/clang/test/SemaObjC/self-assign.m
@@ -5,7 +5,7 @@ @interface A
 @implementation A
 - (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{{using the result of an assignment as a truth value without parentheses}} \
     // expected-note{{use '==' to turn this assignment into an equality comparison}} \
     // expected-note{{place parentheses around the assignment to silence this warning}}
     return self;
diff --git a/clang/test/SemaOpenACC/compute-construct-if-clause.c b/clang/test/SemaOpenACC/compute-construct-if-clause.c
index 4629b1b2c2bd0..e34b9be377d69 100644
--- a/clang/test/SemaOpenACC/compute-construct-if-clause.c
+++ b/clang/test/SemaOpenACC/compute-construct-if-clause.c
@@ -28,7 +28,7 @@ void BoolExpr(int *I, float *F) {
   while(0);
 
   // expected-warning at +4{{incompatible pointer types assigning to 'int *' from 'float *'}}
-  // expected-warning at +3{{using the result of an assignment as a condition without parentheses}}
+  // expected-warning at +3{{using the result of an assignment as a truth value without parentheses}}
   // expected-note at +2{{place parentheses around the assignment to silence this warning}}
   // expected-note at +1{{use '==' to turn this assignment into an equality comparison}}
 #pragma acc kernels if (I = F)



More information about the cfe-commits mailing list