diff options
| author | Aaron Ballman <aaron@aaronballman.com> | 2016-03-07 22:44:55 +0000 |
|---|---|---|
| committer | Aaron Ballman <aaron@aaronballman.com> | 2016-03-07 22:44:55 +0000 |
| commit | e7964789dabaa5b9fb26c50f54deafb7fb8db4d6 (patch) | |
| tree | e9284db077152c2c9222edb213e39ebbb193ef7d /clang/lib | |
| parent | 146c14ac33136ebff2714f4596f6d7db85d6b5e8 (diff) | |
| download | bcm5719-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.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 12 |
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; } } |

