https://github.com/Mick235711 updated https://github.com/llvm/llvm-project/pull/112289
>From 2376ab367715ef2f7f77ffc4d5af21393af876bd 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 | 9 +-- clang/lib/Sema/SemaStmt.cpp | 71 ++++++++++++------- .../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, 101 insertions(+), 75 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index cbe62411d11bff..4ba109cf059e43 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 Decl *, 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..cced726f12b000 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< + "%select{|%1 }0has been explicitly marked %2 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..6a3eb1238a89e2 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1616,22 +1616,23 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { return FnType->getReturnType(); } -const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const { +std::pair<const Decl *, 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 {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..fb8ce5f2e27704 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,26 @@ 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 Decl *OffendingDecl, + const WarnUnusedResultAttr *A, SourceLocation Loc, + SourceRange R1, SourceRange R2, bool IsCtor) { if (!A) return false; StringRef Msg = A->getMessage(); 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; - } + S.Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2; + else + S.Diag(Loc, diag::warn_unused_result) << A << R1 << R2; + } else if (IsCtor) + S.Diag(Loc, diag::warn_unused_constructor_msg) << A << Msg << R1 << R2; + else + 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; + return S.Diag(A->getLocation(), diag::note_nodiscard_specified_here) + << isa<NamedDecl>(OffendingDecl) << dyn_cast<NamedDecl>(OffendingDecl) + << A->getSpelling(); } void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) { @@ -290,9 +294,10 @@ 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 auto &[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 +307,43 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) { if (const Decl *FD = CE->getCalleeDecl()) { if (ShouldSuppress) return; - if (FD->hasAttr<PureAttr>()) { - Diag(Loc, diag::warn_unused_call) << R1 << R2 << "pure"; - return; - } - if (FD->hasAttr<ConstAttr>()) { - Diag(Loc, diag::warn_unused_call) << R1 << R2 << "const"; + + const InheritableAttr *A = nullptr; + if (const auto *PA = FD->getAttr<PureAttr>()) + A = PA; + else if (const auto *CA = FD->getAttr<ConstAttr>()) + A = CA; + + if (A) { + StringRef type = (isa<PureAttr>(A) ? "pure" : "const"); + Diag(Loc, diag::warn_unused_call) << R1 << R2 << type; + if (const auto *ND = dyn_cast<NamedDecl>(OffendingDecl)) { + if (!ND->getIdentifier()->getBuiltinID()) + Diag(A->getLocation(), diag::note_nodiscard_specified_here) + << true << ND << type; + } else + Diag(A->getLocation(), diag::note_nodiscard_specified_here) + << false << ND << type; 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