diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Parse/AttributeList.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 24 |
3 files changed, 21 insertions, 6 deletions
diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index c7ff0aec27f..1d1100a55ad 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -1292,7 +1292,7 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, FunctionDecl* FD = cast<loc::FuncVal>(L).getDecl(); - if (FD->getAttr<NoReturnAttr>()) + if (FD->getAttr<NoReturnAttr>() || FD->getAttr<AnalyzerNoReturnAttr>()) Builder->BuildSinks = true; else { // HACK: Some functions are not marked noreturn, and don't return. diff --git a/clang/lib/Parse/AttributeList.cpp b/clang/lib/Parse/AttributeList.cpp index cd192c92ef0..14011e5b6f1 100644 --- a/clang/lib/Parse/AttributeList.cpp +++ b/clang/lib/Parse/AttributeList.cpp @@ -126,6 +126,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { break; case 17: if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union; + if (!memcmp(Str, "analyzer_noreturn", 17)) return AT_analyzer_noreturn; break; case 18: if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index f3f04f07742..bcc17e7eae7 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -400,20 +400,32 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, d->addAttr(::new (S.Context) AlwaysInlineAttr()); } -static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { +static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, + Sema &S, const char *attrName) { // check the attribute arguments. if (Attr.getNumArgs() != 0) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0; - return; + return false; } if (!isFunctionOrMethod(d)) { S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) - << "noreturn" << 0 /*function*/; - return; + << attrName << 0 /*function*/; + return false; } - d->addAttr(::new (S.Context) NoReturnAttr()); + return true; +} + +static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { + if (HandleCommonNoReturnAttr(d, Attr, S, "noreturn")) + d->addAttr(::new (S.Context) NoReturnAttr()); +} + +static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + if (HandleCommonNoReturnAttr(d, Attr, S, "analyzer_noreturn")) + d->addAttr(::new (S.Context) AnalyzerNoReturnAttr()); } static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1498,6 +1510,8 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { case AttributeList::AT_aligned: HandleAlignedAttr (D, Attr, S); break; case AttributeList::AT_always_inline: HandleAlwaysInlineAttr (D, Attr, S); break; + case AttributeList::AT_analyzer_noreturn: + HandleAnalyzerNoReturnAttr (D, Attr, S); break; case AttributeList::AT_annotate: HandleAnnotateAttr (D, Attr, S); break; case AttributeList::AT_constructor: HandleConstructorAttr(D, Attr, S); break; case AttributeList::AT_deprecated: HandleDeprecatedAttr(D, Attr, S); break; |