summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2016-03-07 22:44:55 +0000
committerAaron Ballman <aaron@aaronballman.com>2016-03-07 22:44:55 +0000
commite7964789dabaa5b9fb26c50f54deafb7fb8db4d6 (patch)
treee9284db077152c2c9222edb213e39ebbb193ef7d /clang/lib
parent146c14ac33136ebff2714f4596f6d7db85d6b5e8 (diff)
downloadbcm5719-llvm-e7964789dabaa5b9fb26c50f54deafb7fb8db4d6.tar.gz
bcm5719-llvm-e7964789dabaa5b9fb26c50f54deafb7fb8db4d6.zip
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
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp16
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp3
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp6
-rw-r--r--clang/lib/Sema/SemaStmt.cpp12
4 files changed, 25 insertions, 12 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 041b530bf07..abaec2d7e10 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2935,16 +2935,22 @@ SourceRange FunctionDecl::getReturnTypeSourceRange() const {
return RTRange;
}
-bool FunctionDecl::hasUnusedResultAttr() const {
+const Attr *FunctionDecl::getUnusedResultAttr() const {
QualType RetType = getReturnType();
if (RetType->isRecordType()) {
const CXXRecordDecl *Ret = RetType->getAsCXXRecordDecl();
const auto *MD = dyn_cast<CXXMethodDecl>(this);
- if (Ret && Ret->hasAttr<WarnUnusedResultAttr>() &&
- !(MD && MD->getCorrespondingMethodInClass(Ret, true)))
- return true;
+ if (Ret && !(MD && MD->getCorrespondingMethodInClass(Ret, true))) {
+ if (const auto *R = Ret->getAttr<WarnUnusedResultAttr>())
+ return R;
+ }
+ } else if (const auto *ET = RetType->getAs<EnumType>()) {
+ if (const EnumDecl *ED = ET->getDecl()) {
+ if (const auto *R = ED->getAttr<WarnUnusedResultAttr>())
+ return R;
+ }
}
- return hasAttr<WarnUnusedResultAttr>();
+ return getAttr<WarnUnusedResultAttr>();
}
/// \brief For an inline function definition in C, or for a gnu_inline function
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 798284b3d39..15aded52b45 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -3635,7 +3635,8 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
case AttributeList::AT_FallThrough:
case AttributeList::AT_CXX11NoReturn:
return true;
-
+ case AttributeList::AT_WarnUnusedResult:
+ return !ScopeName && AttrName->getName().equals("nodiscard");
default:
return false;
}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index bb02e0b59c4..ce78ab00926 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2463,6 +2463,12 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const AttributeList &Attr)
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 c58bf464004..b73b4f08841 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -249,10 +249,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
// 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 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
}
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;
}
}
OpenPOWER on IntegriCloud