https://github.com/halbi2 updated 
https://github.com/llvm/llvm-project/pull/153116

>From ca3213a6e252919fe6eb19ed2a6d6cd6de539bca Mon Sep 17 00:00:00 2001
From: halbi2 <hehira...@gmail.com>
Date: Mon, 11 Aug 2025 21:29:46 -0400
Subject: [PATCH 1/2] [clang] [Sema] Simplify Expr::isUnusedResultAWarning for
 CXXConstructExpr

Two tests have new warnings because `warn_unused_result` is now respected for 
constructor
temporaries. These tests were newly added in #112521 last year. This is good 
because the
new behavior is better than the old.
---
 clang/lib/AST/Expr.cpp                        | 33 ++++++-------------
 .../dcl.attr/dcl.attr.nodiscard/p2.cpp        |  2 +-
 clang/test/SemaCXX/warn-unused-result.cpp     |  4 +--
 3 files changed, 13 insertions(+), 26 deletions(-)

diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 7cac655ef151c..e3a746069cd3f 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2805,32 +2805,19 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, 
SourceLocation &Loc,
 
   case CXXTemporaryObjectExprClass:
   case CXXConstructExprClass: {
-    if (const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl()) {
-      const auto *WarnURAttr = Type->getAttr<WarnUnusedResultAttr>();
-      if (Type->hasAttr<WarnUnusedAttr>() ||
-          (WarnURAttr && WarnURAttr->IsCXX11NoDiscard())) {
-        WarnE = this;
-        Loc = getBeginLoc();
-        R1 = getSourceRange();
-        return true;
-      }
-    }
-
     const auto *CE = cast<CXXConstructExpr>(this);
-    if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
-      const auto *WarnURAttr = Ctor->getAttr<WarnUnusedResultAttr>();
-      if (WarnURAttr && WarnURAttr->IsCXX11NoDiscard()) {
-        WarnE = this;
-        Loc = getBeginLoc();
-        R1 = getSourceRange();
+    const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl();
 
-        if (unsigned NumArgs = CE->getNumArgs())
-          R2 = SourceRange(CE->getArg(0)->getBeginLoc(),
-                           CE->getArg(NumArgs - 1)->getEndLoc());
-        return true;
-      }
-    }
+    if ((Type && Type->hasAttr<WarnUnusedAttr>()) || 
CE->hasUnusedResultAttr(Ctx)) {
+      WarnE = this;
+      Loc = getBeginLoc();
+      R1 = getSourceRange();
 
+      if (unsigned NumArgs = CE->getNumArgs())
+        R2 = SourceRange(CE->getArg(0)->getBeginLoc(),
+                         CE->getArg(NumArgs - 1)->getEndLoc());
+      return true;
+    }
     return false;
   }
 
diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp 
b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
index 0012ab976baa5..7f933a4dcc6b2 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p2.cpp
@@ -115,7 +115,7 @@ void usage() {
   S();    // expected-warning {{ignoring temporary created by a constructor 
declared with 'nodiscard' attribute}}
   S('A'); // expected-warning {{ignoring temporary created by a constructor 
declared with 'nodiscard' attribute: Don't let that S-Char go!}}
   S(1);
-  S(2.2);
+  S(2.2); // expected-warning {{ignoring temporary created by a constructor 
declared with 'gnu::warn_unused_result' attribute}}
   Y(); // expected-warning {{ignoring temporary of type 'Y' declared with 
'nodiscard' attribute: Don't throw me away either!}}
   S s;
   ConvertTo{}; // expected-warning {{ignoring return value of type 'ConvertTo' 
declared with 'nodiscard' attribute: Don't throw me away!}}
diff --git a/clang/test/SemaCXX/warn-unused-result.cpp 
b/clang/test/SemaCXX/warn-unused-result.cpp
index 447654eccd563..1f7913f1aa994 100644
--- a/clang/test/SemaCXX/warn-unused-result.cpp
+++ b/clang/test/SemaCXX/warn-unused-result.cpp
@@ -309,7 +309,7 @@ void use() {
 
   S<double>(2);     // no warning
   S<int>(2);        // expected-warning {{ignoring temporary of type 'S<int>' 
declared with 'nodiscard'}}
-  S<const char>(2); // no warning (warn_unused_result does not diagnose 
constructor temporaries)
+  S<const char>(2); // expected-warning {{ignoring temporary of type 'S<const 
char>' declared with 'clang::warn_unused_result' attribute}}
 
   // function should take precedence over type
   obtain2(1.0);             // expected-warning {{ignoring return value of 
function declared with 'nodiscard'}}
@@ -336,7 +336,7 @@ struct [[nodiscard]] G {
 void use2() {
   H{2};       // no warning
   H(2.0);     // expected-warning {{ignoring temporary created by a 
constructor declared with 'nodiscard'}}
-  H("Hello"); // no warning (warn_unused_result does not diagnose constructor 
temporaries)
+  H("Hello"); // expected-warning {{ignoring temporary created by a 
constructor declared with 'warn_unused_result' attribute}}
 
   // no warning for explicit cast to void
   (void)H(2);

>From 426d6d765a59c5a4dc356848b8a3b1db23a2d3c1 Mon Sep 17 00:00:00 2001
From: halbi2 <hehira...@gmail.com>
Date: Mon, 11 Aug 2025 23:14:35 -0400
Subject: [PATCH 2/2] fix clang-format

---
 clang/lib/AST/Expr.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index e3a746069cd3f..e14cff552c922 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2808,7 +2808,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, 
SourceLocation &Loc,
     const auto *CE = cast<CXXConstructExpr>(this);
     const CXXRecordDecl *Type = getType()->getAsCXXRecordDecl();
 
-    if ((Type && Type->hasAttr<WarnUnusedAttr>()) || 
CE->hasUnusedResultAttr(Ctx)) {
+    if ((Type && Type->hasAttr<WarnUnusedAttr>()) ||
+        CE->hasUnusedResultAttr(Ctx)) {
       WarnE = this;
       Loc = getBeginLoc();
       R1 = getSourceRange();

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to