https://github.com/Mick235711 created 
https://github.com/llvm/llvm-project/pull/112289

Currently, the following program
```cpp
[[nodiscard]] int fun() { return 1; }
[[deprecated]] int fun2() { return 2; }

int main()
{
    fun(); fun2();
}
```
generates the following diagnostics on Clang trunk: ([Compiler 
Explorer](https://godbolt.org/z/48crWEoYY))
```cpp
<source>:6:5: warning: ignoring return value of function declared with 
'nodiscard' attribute [-Wunused-result]
    6 |     fun(); fun2();
      |     ^~~
<source>:6:12: warning: 'fun2' is deprecated [-Wdeprecated-declarations]
    6 |     fun(); fun2();
      |            ^
<source>:2:3: note: 'fun2' has been explicitly marked deprecated here
    2 | [[deprecated]] int fun2() { return 2; }
      |   ^
2 warnings generated.
```
There seems to exist a discrepancy between `[[deprecated]]` and 
`[[nodiscard]]`. The former generates a warning on the usage of the function, 
together with a note on the declaration of the function. In contrast, the 
latter only generates a warning.

This PR tries to fix this discrepancy by additionally generating a note on the 
declaration of all `[[nodiscard]]`-related attributes (`nodiscard`, 
`warn_unused_result`, `pure`, and `const`). All 4 attributes generate a warning 
on ignoring the return value/constructor result on the trunk, and after this 
PR, all 4 attributes additionally generate a note. The above program will 
output the following diagnostics after this PR:
```cpp
test.cpp:6:5: warning: ignoring return value of function declared with 
'nodiscard' attribute [-Wunused-result]
    6 |     fun(); fun2();
      |     ^~~
test.cpp:1:3: note: 'fun' has been explicitly marked nodiscard here
    1 | [[nodiscard]] int fun() { return 1; }
      |   ^
test.cpp:6:12: warning: 'fun2' is deprecated [-Wdeprecated-declarations]
    6 |     fun(); fun2();
      |            ^
test.cpp:2:3: note: 'fun2' has been explicitly marked deprecated here
    2 | [[deprecated]] int fun2() { return 2; }
      |   ^
2 warnings generated.
```

---
FIrst time contributor here who is not very familiar with Clang's 
infrastructure... Any comments and suggestions are welcome. No new test cases 
are added, as I felt that adding `expected-note`s on existing test cases 
already serves as testing for this PR.

>From 05e44dc97dcb351f719a5f2ce553c8af5aacfac7 Mon Sep 17 00:00:00 2001
From: Yihe Li <winmiked...@hotmail.com>
Date: Tue, 15 Oct 2024 08:13:22 +0800
Subject: [PATCH] [clang] Generate note on declaration for nodiscard-related
 attributes

---
 clang/include/clang/AST/Expr.h                |  5 +-
 .../clang/Basic/DiagnosticSemaKinds.td        |  2 +
 clang/lib/AST/Expr.cpp                        | 10 +--
 clang/lib/Sema/SemaStmt.cpp                   | 63 ++++++++++++-------
 .../dcl.attr/dcl.attr.nodiscard/p2.cpp        | 29 ++++-----
 .../dcl.attr/dcl.attr.nodiscard/p3.cpp        |  2 +-
 .../test/OpenMP/declare_variant_messages.cpp  |  2 +-
 clang/test/Sema/c2x-nodiscard.c               | 12 ++--
 clang/test/Sema/unused-expr.c                 | 10 +--
 clang/test/SemaCXX/coroutines.cpp             |  2 +-
 clang/test/SemaCXX/warn-unused-result.cpp     | 26 ++++----
 .../SemaObjC/method-warn-unused-attribute.m   |  6 +-
 12 files changed, 98 insertions(+), 71 deletions(-)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index cbe62411d11bff..8f5679767529fd 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3182,11 +3182,12 @@ class CallExpr : public Expr {
 
   /// Returns the WarnUnusedResultAttr that is either declared on the called
   /// function, or its return type declaration.
-  const Attr *getUnusedResultAttr(const ASTContext &Ctx) const;
+  std::pair<const NamedDecl *, const Attr *>
+  getUnusedResultAttr(const ASTContext &Ctx) const;
 
   /// Returns true if this call expression should warn on unused results.
   bool hasUnusedResultAttr(const ASTContext &Ctx) const {
-    return getUnusedResultAttr(Ctx) != nullptr;
+    return getUnusedResultAttr(Ctx).second != nullptr;
   }
 
   SourceLocation getRParenLoc() const { return RParenLoc; }
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c709795e7b21d8..3f6e4c35146454 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9290,6 +9290,8 @@ def warn_unused_result_typedef_unsupported_spelling : 
Warning<
 def warn_unused_volatile : Warning<
   "expression result unused; assign into a variable to force a volatile load">,
   InGroup<DiagGroup<"unused-volatile-lvalue">>;
+def note_nodiscard_specified_here : Note<
+  "%0 has been explicitly marked %1 here">;
 
 def ext_cxx14_attr : Extension<
   "use of the %0 attribute is a C++14 extension">, InGroup<CXX14Attrs>;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 9ecbf121e3fc0d..b9450d6a61e57c 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1616,22 +1616,24 @@ QualType CallExpr::getCallReturnType(const ASTContext 
&Ctx) const {
   return FnType->getReturnType();
 }
 
-const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const {
+std::pair<const NamedDecl *, const Attr *>
+CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const {
   // If the return type is a struct, union, or enum that is marked nodiscard,
   // then return the return type attribute.
   if (const TagDecl *TD = getCallReturnType(Ctx)->getAsTagDecl())
     if (const auto *A = TD->getAttr<WarnUnusedResultAttr>())
-      return A;
+      return {TD, A};
 
   for (const auto *TD = getCallReturnType(Ctx)->getAs<TypedefType>(); TD;
        TD = TD->desugar()->getAs<TypedefType>())
     if (const auto *A = TD->getDecl()->getAttr<WarnUnusedResultAttr>())
-      return A;
+      return {TD->getDecl(), A};
 
   // Otherwise, see if the callee is marked nodiscard and return that attribute
   // instead.
   const Decl *D = getCalleeDecl();
-  return D ? D->getAttr<WarnUnusedResultAttr>() : nullptr;
+  return {dyn_cast<NamedDecl>(D),
+          D ? D->getAttr<WarnUnusedResultAttr>() : nullptr};
 }
 
 SourceLocation CallExpr::getBeginLoc() const {
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 9e235a46707cd4..baaa6422b88fd4 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -14,6 +14,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/ASTLambda.h"
+#include "clang/AST/Attrs.inc"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclObjC.h"
@@ -204,23 +205,29 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr 
*E) {
   return true;
 }
 
-static bool DiagnoseNoDiscard(Sema &S, const WarnUnusedResultAttr *A,
-                              SourceLocation Loc, SourceRange R1,
-                              SourceRange R2, bool IsCtor) {
+static bool DiagnoseNoDiscard(Sema &S, const NamedDecl *OffendingDecl,
+                              const WarnUnusedResultAttr *A, SourceLocation 
Loc,
+                              SourceRange R1, SourceRange R2, bool IsCtor) {
   if (!A)
     return false;
   StringRef Msg = A->getMessage();
 
+  bool result;
   if (Msg.empty()) {
     if (IsCtor)
-      return S.Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2;
-    return S.Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
-  }
+      result = S.Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2;
+    else
+      result = S.Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
+  } else if (IsCtor)
+    result = S.Diag(Loc, diag::warn_unused_constructor_msg)
+             << A << Msg << R1 << R2;
+  else
+    result = S.Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
 
-  if (IsCtor)
-    return S.Diag(Loc, diag::warn_unused_constructor_msg) << A << Msg << R1
-                                                          << R2;
-  return S.Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
+  if (OffendingDecl)
+    S.Diag(A->getLocation(), diag::note_nodiscard_specified_here)
+        << OffendingDecl << A->getSpelling();
+  return result;
 }
 
 void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
@@ -290,9 +297,12 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, 
unsigned DiagID) {
     if (E->getType()->isVoidType())
       return;
 
-    if (DiagnoseNoDiscard(*this, cast_or_null<WarnUnusedResultAttr>(
-                                     CE->getUnusedResultAttr(Context)),
-                          Loc, R1, R2, /*isCtor=*/false))
+    const NamedDecl *OffendingDecl;
+    const Attr *A;
+    std::tie(OffendingDecl, A) = CE->getUnusedResultAttr(Context);
+    if (DiagnoseNoDiscard(*this, OffendingDecl,
+                          cast_or_null<WarnUnusedResultAttr>(A), Loc, R1, R2,
+                          /*isCtor=*/false))
       return;
 
     // If the callee has attribute pure, const, or warn_unused_result, warn 
with
@@ -302,27 +312,38 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, 
unsigned DiagID) {
     if (const Decl *FD = CE->getCalleeDecl()) {
       if (ShouldSuppress)
         return;
-      if (FD->hasAttr<PureAttr>()) {
+      if (const auto *A = FD->getAttr<PureAttr>()) {
         Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure";
+        if (OffendingDecl && !OffendingDecl->getIdentifier()->getBuiltinID())
+          Diag(A->getLocation(), diag::note_nodiscard_specified_here)
+              << OffendingDecl << "pure";
         return;
       }
-      if (FD->hasAttr<ConstAttr>()) {
+      if (const auto *A = FD->getAttr<ConstAttr>()) {
         Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const";
+        if (OffendingDecl && !OffendingDecl->getIdentifier()->getBuiltinID())
+          Diag(A->getLocation(), diag::note_nodiscard_specified_here)
+              << OffendingDecl << "const";
         return;
       }
     }
   } else if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
     if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
+      const NamedDecl *OffendingDecl = Ctor;
       const auto *A = Ctor->getAttr<WarnUnusedResultAttr>();
-      A = A ? A : Ctor->getParent()->getAttr<WarnUnusedResultAttr>();
-      if (DiagnoseNoDiscard(*this, A, Loc, R1, R2, /*isCtor=*/true))
+      if (!A) {
+        OffendingDecl = Ctor->getParent();
+        A = OffendingDecl->getAttr<WarnUnusedResultAttr>();
+      }
+      if (DiagnoseNoDiscard(*this, OffendingDecl, A, Loc, R1, R2,
+                            /*isCtor=*/true))
         return;
     }
   } else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
     if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) {
 
-      if (DiagnoseNoDiscard(*this, TD->getAttr<WarnUnusedResultAttr>(), Loc, 
R1,
-                            R2, /*isCtor=*/false))
+      if (DiagnoseNoDiscard(*this, TD, TD->getAttr<WarnUnusedResultAttr>(), 
Loc,
+                            R1, R2, /*isCtor=*/false))
         return;
     }
   } else if (ShouldSuppress)
@@ -336,8 +357,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned 
DiagID) {
     }
     const ObjCMethodDecl *MD = ME->getMethodDecl();
     if (MD) {
-      if (DiagnoseNoDiscard(*this, MD->getAttr<WarnUnusedResultAttr>(), Loc, 
R1,
-                            R2, /*isCtor=*/false))
+      if (DiagnoseNoDiscard(*this, MD, MD->getAttr<WarnUnusedResultAttr>(), 
Loc,
+                            R1, R2, /*isCtor=*/false))
         return;
     }
   } else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
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 693ca29370cf3f..158fbdbd67be34 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
@@ -2,18 +2,18 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++17 
-verify=expected,cxx11-17,since-cxx17 -pedantic %s
 // RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=expected,since-cxx17 
-pedantic %s
 
-struct [[nodiscard]] S {};
+struct [[nodiscard]] S {}; // expected-note 4 {{'S' has been explicitly marked 
nodiscard here}}
 // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
 S get_s();
 S& get_s_ref();
 
-enum [[nodiscard]] E {};
+enum [[nodiscard]] E {}; // expected-note 2 {{'E' has been explicitly marked 
nodiscard here}}
 // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
 E get_e();
 
-[[nodiscard]] int get_i();
+[[nodiscard]] int get_i(); // expected-note {{'get_i' has been explicitly 
marked nodiscard here}}
 // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
-[[nodiscard]] volatile int &get_vi();
+[[nodiscard]] volatile int &get_vi(); // expected-note {{'get_vi' has been 
explicitly marked nodiscard here}}
 // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
 
 void f() {
@@ -32,6 +32,7 @@ void f() {
 
 [[nodiscard]] volatile char &(*fp)(); // expected-warning {{'nodiscard' 
attribute only applies to functions, classes, or enumerations}}
 // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
+// expected-note@-2 {{'fp' has been explicitly marked nodiscard here}}
 void g() {
   fp(); // expected-warning {{ignoring return value of function declared with 
'nodiscard' attribute}}
 
@@ -67,20 +68,20 @@ void f() {
 }
 } // namespace PR31526
 
-struct [[nodiscard("reason")]] ReasonStruct {};
+struct [[nodiscard("reason")]] ReasonStruct {}; // expected-note 
{{'ReasonStruct' has been explicitly marked nodiscard here}}
 // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 
extension}}
 struct LaterReason;
-struct [[nodiscard("later reason")]] LaterReason {};
+struct [[nodiscard("later reason")]] LaterReason {}; // expected-note 
{{'LaterReason' has been explicitly marked nodiscard here}}
 // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 
extension}}
 
 ReasonStruct get_reason();
 LaterReason get_later_reason();
-[[nodiscard("another reason")]] int another_reason();
+[[nodiscard("another reason")]] int another_reason(); // expected-note 
{{'another_reason' has been explicitly marked nodiscard here}}
 // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 
extension}}
 
 [[nodiscard("conflicting reason")]] int conflicting_reason();
 // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 
extension}}
-[[nodiscard("special reason")]] int conflicting_reason();
+[[nodiscard("special reason")]] int conflicting_reason(); // expected-note 
{{'conflicting_reason' has been explicitly marked nodiscard here}}
 // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 
extension}}
 
 void cxx20_use() {
@@ -91,23 +92,23 @@ void cxx20_use() {
 }
 
 namespace p1771 {
-struct[[nodiscard("Don't throw me away!")]] ConvertTo{};
+struct[[nodiscard("Don't throw me away!")]] ConvertTo{}; // expected-note 3 
{{'ConvertTo' has been explicitly marked nodiscard here}}
 // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 
extension}}
 struct S {
-  [[nodiscard]] S();
+  [[nodiscard]] S(); // expected-note {{'S' has been explicitly marked 
nodiscard here}}
   // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
-  [[nodiscard("Don't let that S-Char go!")]] S(char);
+  [[nodiscard("Don't let that S-Char go!")]] S(char); // expected-note 2 {{'S' 
has been explicitly marked nodiscard here}}
   // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 
extension}}
   S(int);
   [[gnu::warn_unused_result]] S(double);
   operator ConvertTo();
-  [[nodiscard]] operator int();
+  [[nodiscard]] operator int(); // expected-note 2 {{'operator int' has been 
explicitly marked nodiscard here}}
   // cxx11-warning@-1 {{use of the 'nodiscard' attribute is a C++17 extension}}
-  [[nodiscard("Don't throw away as a double")]] operator double();
+  [[nodiscard("Don't throw away as a double")]] operator double(); // 
expected-note {{'operator double' has been explicitly marked nodiscard here}}
   // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 
extension}}
 };
 
-struct[[nodiscard("Don't throw me away either!")]] Y{};
+struct[[nodiscard("Don't throw me away either!")]] Y{}; // expected-note {{'Y' 
has been explicitly marked nodiscard here}}
 // cxx11-17-warning@-1 {{use of the 'nodiscard' attribute is a C++20 
extension}}
 
 void usage() {
diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p3.cpp 
b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p3.cpp
index a3543cff7d2c92..6df334e1c0b488 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p3.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.nodiscard/p3.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -std=c++1z -verify %s
 
 namespace std_example {
-  struct [[nodiscard]] error_info{
+  struct [[nodiscard]] error_info{ // expected-note {{'error_info' has been 
explicitly marked nodiscard here}}
     // ...
   };
 
diff --git a/clang/test/OpenMP/declare_variant_messages.cpp 
b/clang/test/OpenMP/declare_variant_messages.cpp
index b8a806e7ef75b3..5fe53d70270fbc 100644
--- a/clang/test/OpenMP/declare_variant_messages.cpp
+++ b/clang/test/OpenMP/declare_variant_messages.cpp
@@ -133,7 +133,7 @@ int score_and_cond_const();
 template <int C>
 int score_and_cond_const_inst();
 
-__attribute__((pure)) int pure() { return 0; }
+__attribute__((pure)) int pure() { return 0; } // expected-note {{'pure' has 
been explicitly marked pure here}}
 
 #pragma omp declare variant(pure) match(user = {condition(1)}) // 
expected-warning {{ignoring return value of function declared with pure 
attribute}}
 int unused_warning_after_specialization() { return foo(); }
diff --git a/clang/test/Sema/c2x-nodiscard.c b/clang/test/Sema/c2x-nodiscard.c
index f8b0567366465d..8865e2f9cd0ca2 100644
--- a/clang/test/Sema/c2x-nodiscard.c
+++ b/clang/test/Sema/c2x-nodiscard.c
@@ -9,7 +9,7 @@ struct [[nodiscard]] S1 { // ok
 struct [[nodiscard, nodiscard]] S2 { // ok
   int i;
 };
-struct [[nodiscard("Wrong")]] S3 {
+struct [[nodiscard("Wrong")]] S3 { // expected-note {{'S3' has been explicitly 
marked nodiscard here}}
   int i;
 };
 
@@ -20,15 +20,15 @@ enum [[nodiscard]] E1 { One };
 
 [[nodiscard]] int i; // expected-warning {{'nodiscard' attribute only applies 
to Objective-C methods, enums, structs, unions, classes, functions, function 
pointers, and typedefs}}
 
-struct [[nodiscard]] S4 {
+struct [[nodiscard]] S4 { // expected-note {{'S4' has been explicitly marked 
nodiscard here}}
   int i;
 };
 struct S4 get_s(void);
 
-enum [[nodiscard]] E2 { Two };
+enum [[nodiscard]] E2 { Two }; // expected-note {{'E2' has been explicitly 
marked nodiscard here}}
 enum E2 get_e(void);
 
-[[nodiscard]] int get_i(void);
+[[nodiscard]] int get_i(void); // expected-note {{'get_i' has been explicitly 
marked nodiscard here}}
 
 void f2(void) {
   get_s(); // expected-warning {{ignoring return value of function declared 
with 'nodiscard' attribute}}
@@ -43,7 +43,7 @@ void f2(void) {
   (void)get_e();
 }
 
-struct [[nodiscard]] error_info{
+struct [[nodiscard]] error_info{ // expected-note {{'error_info' has been 
explicitly marked nodiscard here}}
   int i;
 };
 
@@ -54,7 +54,7 @@ void test_missiles(void) {
   launch_missiles();
 }
 
-[[nodiscard]] int f3();
+[[nodiscard]] int f3(); // expected-note {{'f3' has been explicitly marked 
nodiscard here}}
 
 void GH104391() {
 #define M (unsigned int) f3()
diff --git a/clang/test/Sema/unused-expr.c b/clang/test/Sema/unused-expr.c
index 6723a33cbd4e01..9e444f94d67137 100644
--- a/clang/test/Sema/unused-expr.c
+++ b/clang/test/Sema/unused-expr.c
@@ -73,15 +73,15 @@ void t4(int a) {
   for (;;b < 1) {} // expected-warning{{relational comparison result unused}}
 }
 
-int t5f(void) __attribute__((warn_unused_result));
+int t5f(void) __attribute__((warn_unused_result)); // expected-note {{'t5f' 
has been explicitly marked warn_unused_result here}}
 void t5(void) {
   t5f();   // expected-warning {{ignoring return value of function declared 
with 'warn_unused_result' attribute}}
 }
 
 
-int fn1(void) __attribute__ ((warn_unused_result));
-int fn2() __attribute__ ((pure));
-int fn3() __attribute__ ((__const));
+int fn1(void) __attribute__ ((warn_unused_result)); // expected-note 3 {{'fn1' 
has been explicitly marked warn_unused_result here}}
+int fn2() __attribute__ ((pure)); // expected-note 2 {{'fn2' has been 
explicitly marked pure here}}
+int fn3() __attribute__ ((__const)); // expected-note {{'fn3' has been 
explicitly marked const here}}
 int t6(void) {
   if (fn1() < 0 || fn2(2,1) < 0 || fn3(2) < 0)  // no warnings
     return -1;
@@ -97,7 +97,7 @@ int t6(void) {
 int t7 __attribute__ ((warn_unused_result)); // expected-warning 
{{'warn_unused_result' attribute only applies to Objective-C methods, enums, 
structs, unions, classes, functions, function pointers, and typedefs}}
 
 // PR4010
-int (*fn4)(void) __attribute__ ((warn_unused_result));
+int (*fn4)(void) __attribute__ ((warn_unused_result)); // expected-note 
{{'fn4' has been explicitly marked warn_unused_result here}}
 void t8(void) {
   fn4(); // expected-warning {{ignoring return value of function declared with 
'warn_unused_result' attribute}}
 }
diff --git a/clang/test/SemaCXX/coroutines.cpp 
b/clang/test/SemaCXX/coroutines.cpp
index 068fdab4bfe384..c9d442a0338121 100644
--- a/clang/test/SemaCXX/coroutines.cpp
+++ b/clang/test/SemaCXX/coroutines.cpp
@@ -1497,7 +1497,7 @@ class awaitable_unused_warn {
   using handle_type = std::coroutine_handle<>;
   constexpr bool await_ready() noexcept { return false; }
   void await_suspend(handle_type) noexcept {}
-  [[nodiscard]] int await_resume() noexcept { return 1; }
+  [[nodiscard]] int await_resume() noexcept { return 1; } // expected-note 2 
{{'await_resume' has been explicitly marked nodiscard here}}
 };
 
 template <class Await>
diff --git a/clang/test/SemaCXX/warn-unused-result.cpp 
b/clang/test/SemaCXX/warn-unused-result.cpp
index 4b7a2503ecc0dd..247be530274af2 100644
--- a/clang/test/SemaCXX/warn-unused-result.cpp
+++ b/clang/test/SemaCXX/warn-unused-result.cpp
@@ -1,13 +1,13 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
 
-int f() __attribute__((warn_unused_result));
+int f() __attribute__((warn_unused_result)); // expected-note 12 {{'f' has 
been explicitly marked warn_unused_result here}}
 
 struct S {
   void t() const;
 };
-S g1() __attribute__((warn_unused_result));
-S *g2() __attribute__((warn_unused_result));
-S &g3() __attribute__((warn_unused_result));
+S g1() __attribute__((warn_unused_result)); // expected-note {{'g1' has been 
explicitly marked warn_unused_result here}}
+S *g2() __attribute__((warn_unused_result)); // expected-note {{'g2' has been 
explicitly marked warn_unused_result here}}
+S &g3() __attribute__((warn_unused_result)); // expected-note {{'g3' has been 
explicitly marked warn_unused_result here}}
 
 void test() {
   f(); // expected-warning {{ignoring return value}}
@@ -64,7 +64,7 @@ void testSubstmts(int i) {
 }
 
 struct X {
- int foo() __attribute__((warn_unused_result));
+ int foo() __attribute__((warn_unused_result)); // expected-note 2 {{'foo' has 
been explicitly marked warn_unused_result here}}
 };
 
 void bah() {
@@ -80,7 +80,7 @@ class Foo {
   Status doStuff();
 };
 
-struct [[clang::warn_unused_result]] Status {
+struct [[clang::warn_unused_result]] Status { // expected-note 3 {{'Status' 
has been explicitly marked warn_unused_result here}}
   bool ok() const;
   Status& operator=(const Status& x);
   inline void Update(const Status& new_status) {
@@ -115,7 +115,7 @@ void lazy() {
 }
 
 template <typename T>
-class [[clang::warn_unused_result]] StatusOr {
+class [[clang::warn_unused_result]] StatusOr { // expected-note 
{{'StatusOr<int>' has been explicitly marked warn_unused_result here}}
 };
 StatusOr<int> doit();
 void test() {
@@ -129,7 +129,7 @@ void test() {
 }
 
 namespace PR17587 {
-struct [[clang::warn_unused_result]] Status;
+struct [[clang::warn_unused_result]] Status; // expected-note {{'Status' has 
been explicitly marked warn_unused_result here}}
 
 struct Foo {
   Status Bar();
@@ -193,7 +193,7 @@ void g() {
 
 namespace {
 // C++ Methods should warn even in their own class.
-struct [[clang::warn_unused_result]] S {
+struct [[clang::warn_unused_result]] S { // expected-note 5 {{'S' has been 
explicitly marked warn_unused_result here}}
   S DoThing() { return {}; };
   S operator++(int) { return {}; };
   S operator--(int) { return {}; };
@@ -202,7 +202,7 @@ struct [[clang::warn_unused_result]] S {
   S operator--() { return {}; };
 };
 
-struct [[clang::warn_unused_result]] P {
+struct [[clang::warn_unused_result]] P { // expected-note 5 {{'P' has been 
explicitly marked warn_unused_result here}}
   P DoThing() { return {}; };
 };
 
@@ -238,7 +238,7 @@ void f() {
 } // namespace
 
 namespace PR39837 {
-[[clang::warn_unused_result]] int f(int);
+[[clang::warn_unused_result]] int f(int); // expected-note {{'f' has been 
explicitly marked warn_unused_result here}}
 
 void g() {
   int a[2];
@@ -256,7 +256,7 @@ void i([[nodiscard]] bool (*fp)()); // expected-warning 
{{'nodiscard' attribute
 }
 
 namespace unused_typedef_result {
-[[clang::warn_unused_result]] typedef void *a;
+[[clang::warn_unused_result]] typedef void *a; // expected-note 3 {{'a' has 
been explicitly marked warn_unused_result here}}
 typedef a indirect;
 a af1();
 indirect indirectf1();
@@ -276,7 +276,7 @@ void bf2() {
   b1f1(); // no warning
   b2f1(); // no warning
 }
-__attribute__((warn_unused_result)) typedef void *c;
+__attribute__((warn_unused_result)) typedef void *c; // expected-note 2 {{'c' 
has been explicitly marked warn_unused_result here}}
 c cf1();
 void cf2() {
   cf1(); // expected-warning {{ignoring return value}}
diff --git a/clang/test/SemaObjC/method-warn-unused-attribute.m 
b/clang/test/SemaObjC/method-warn-unused-attribute.m
index b83dabf3bbdc22..99917b8df94330 100644
--- a/clang/test/SemaObjC/method-warn-unused-attribute.m
+++ b/clang/test/SemaObjC/method-warn-unused-attribute.m
@@ -1,10 +1,10 @@
 // RUN: %clang_cc1  -fsyntax-only -Wunused-value -verify %s
 
 @interface INTF
-- (id) foo __attribute__((warn_unused_result)); 
+- (id) foo __attribute__((warn_unused_result));
 - (void) garf __attribute__((warn_unused_result)); // expected-warning 
{{attribute 'warn_unused_result' cannot be applied to Objective-C method 
without return value}}
-- (int) fee __attribute__((warn_unused_result));
-+ (int) c __attribute__((warn_unused_result));
+- (int) fee __attribute__((warn_unused_result)); // expected-note {{'fee' has 
been explicitly marked warn_unused_result here}}
++ (int) c __attribute__((warn_unused_result)); // expected-note {{'c' has been 
explicitly marked warn_unused_result here}}
 @end
 
 void foo(INTF *a) {

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

Reply via email to