[clang] [clang] Generate note on declaration for nodiscard-related attributes (PR #112289)
Yihe Li via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 15 11:12:52 PDT 2024
https://github.com/Mick235711 updated https://github.com/llvm/llvm-project/pull/112289
>From b9911d5b997306376fcf5348a24f8bae7b71bfeb Mon Sep 17 00:00:00 2001
From: Yihe Li <winmikedows at 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 | 6 +-
clang/lib/AST/Expr.cpp | 9 ++-
clang/lib/Sema/SemaAvailability.cpp | 8 +-
clang/lib/Sema/SemaExpr.cpp | 2 +-
clang/lib/Sema/SemaStmt.cpp | 77 +++++++++++++------
.../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 +-
14 files changed, 116 insertions(+), 80 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 e78acc8dc8c57b..35e2b4faf6e975 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5939,8 +5939,8 @@ def warn_unavailable_fwdclass_message : Warning<
"%0 may be unavailable because the receiver type is unknown">,
InGroup<UnavailableDeclarations>;
def note_availability_specified_here : Note<
- "%0 has been explicitly marked "
- "%select{unavailable|deleted|deprecated}1 here">;
+ "%select{|%1 }0has been explicitly marked "
+ "%select{unavailable|deleted|deprecated|nodiscard|warn_unused_result|pure|const}2 here">;
def note_partial_availability_specified_here : Note<
"%0 has been marked as being introduced in %1 %2 %select{|in %5 environment }4here, "
"but the deployment target is %1 %3%select{| %6 environment }4">;
@@ -9263,7 +9263,7 @@ def warn_unused_container_subscript_expr : Warning<
"container access result unused - container access should not be used for side effects">,
InGroup<UnusedValue>;
def warn_unused_call : Warning<
- "ignoring return value of function declared with %0 attribute">,
+ "ignoring return value of function declared with %select{pure|const}0 attribute">,
InGroup<UnusedValue>;
def warn_unused_constructor : Warning<
"ignoring temporary created by a constructor declared with %0 attribute">,
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/SemaAvailability.cpp b/clang/lib/Sema/SemaAvailability.cpp
index 798cabaa31a476..da74033f233895 100644
--- a/clang/lib/Sema/SemaAvailability.cpp
+++ b/clang/lib/Sema/SemaAvailability.cpp
@@ -670,8 +670,12 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
}
- S.Diag(NoteLocation, diag_available_here)
- << OffendingDecl << available_here_select_kind;
+ if (diag_available_here == diag::note_availability_specified_here)
+ S.Diag(NoteLocation, diag_available_here)
+ << true << OffendingDecl << available_here_select_kind;
+ else
+ S.Diag(NoteLocation, diag_available_here)
+ << OffendingDecl << available_here_select_kind;
}
void Sema::handleDelayedAvailabilityCheck(DelayedDiagnostic &DD, Decl *Ctx) {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 044f56f2af71bf..3951a40eecf5be 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -140,7 +140,7 @@ void Sema::NoteDeletedFunction(FunctionDecl *Decl) {
return NoteDeletedInheritingConstructor(Ctor);
Diag(Decl->getLocation(), diag::note_availability_specified_here)
- << Decl << 1;
+ << true << Decl << 1;
}
/// Determine whether a FunctionDecl was ever declared with an
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 9e235a46707cd4..873d6cf3a6bf45 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,30 @@ 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;
+ // nodiscard = 3, warn_unused_result = 4
+ unsigned available_here_select_kind =
+ (A->getSpelling() == StringRef{"nodiscard"} ? 3 : 4);
+ return S.Diag(A->getLocation(), diag::note_availability_specified_here)
+ << isa<NamedDecl>(OffendingDecl) << dyn_cast<NamedDecl>(OffendingDecl)
+ << available_here_select_kind;
}
void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
@@ -290,9 +298,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 +311,47 @@ 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) {
+ // pure = 0, const = 1 for warn_unused_call
+ unsigned available_here_select_kind = (isa<PureAttr>(A) ? 0 : 1);
+ Diag(Loc, diag::warn_unused_call)
+ << R1 << R2 << available_here_select_kind;
+ available_here_select_kind += 5; // pure = 5, const = 6 for availability
+ if (const auto *ND = dyn_cast<NamedDecl>(OffendingDecl)) {
+ if (!ND->getIdentifier()->getBuiltinID())
+ Diag(A->getLocation(), diag::note_availability_specified_here)
+ << true << ND << available_here_select_kind;
+ } else {
+ Diag(A->getLocation(), diag::note_availability_specified_here)
+ << false << ND << available_here_select_kind;
+ }
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 +365,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 at -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 at -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 at -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 at -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 at -1 {{use of the 'nodiscard' attribute is a C++17 extension}}
+// expected-note at -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 at -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 at -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 at -1 {{use of the 'nodiscard' attribute is a C++20 extension}}
[[nodiscard("conflicting reason")]] int conflicting_reason();
// cxx11-17-warning at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -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) {
More information about the cfe-commits
mailing list