Implement support for [[nodiscard]] in C++1z that is based off existing support for warn_unused_result, and treat it as an extension pre-C++1z. This also means extending the existing warn_unused_result attribute so that it can be placed on an enum as well as a class.
llvm-svn: 262872
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index bb02e0b..ce78ab0 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2463,6 +2463,12 @@
return;
}
+ // If this is spelled as the standard C++1z attribute, but not in C++1z, warn
+ // about using it as an extension.
+ if (!S.getLangOpts().CPlusPlus1z && Attr.isCXX11Attribute() &&
+ !Attr.getScopeName())
+ S.Diag(Attr.getLoc(), diag::ext_nodiscard_attr_is_a_cxx1z_extension);
+
D->addAttr(::new (S.Context)
WarnUnusedResultAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index c58bf46..b73b4f0 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -249,10 +249,10 @@
// is written in a macro body, only warn if it has the warn_unused_result
// attribute.
if (const Decl *FD = CE->getCalleeDecl()) {
- const FunctionDecl *Func = dyn_cast<FunctionDecl>(FD);
- if (Func ? Func->hasUnusedResultAttr()
- : FD->hasAttr<WarnUnusedResultAttr>()) {
- Diag(Loc, diag::warn_unused_result) << R1 << R2;
+ if (const Attr *A = isa<FunctionDecl>(FD)
+ ? cast<FunctionDecl>(FD)->getUnusedResultAttr()
+ : FD->getAttr<WarnUnusedResultAttr>()) {
+ Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
return;
}
if (ShouldSuppress)
@@ -276,8 +276,8 @@
}
const ObjCMethodDecl *MD = ME->getMethodDecl();
if (MD) {
- if (MD->hasAttr<WarnUnusedResultAttr>()) {
- Diag(Loc, diag::warn_unused_result) << R1 << R2;
+ if (const auto *A = MD->getAttr<WarnUnusedResultAttr>()) {
+ Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
return;
}
}