aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-04-10 00:01:14 +0000
committerTed Kremenek <kremenek@apple.com>2009-04-10 00:01:14 +0000
commitb725232b46e92f3e36b03a32a6fc75748c312122 (patch)
tree4d9adc37e8bf8da2272db69b7d09242c93081345
parent2cf2634ffdb4f7c8d46cef3f8e60a55993f1c57a (diff)
Implement attribute "analyzer_noreturn" (<rdar://problem/6777003>). This allows
clients of the analyzer to designate custom assertion routines as "noreturn" functions from the analyzer's perspective but not the compiler's. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68746 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Attr.h12
-rw-r--r--include/clang/Parse/AttributeList.h1
-rw-r--r--lib/Analysis/GRExprEngine.cpp2
-rw-r--r--lib/Parse/AttributeList.cpp1
-rw-r--r--lib/Sema/SemaDeclAttr.cpp24
-rw-r--r--test/Analysis/misc-ps.m20
6 files changed, 54 insertions, 6 deletions
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index 28f7ec2db6..9deed40d4c 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -29,6 +29,7 @@ public:
Alias,
Aligned,
AlwaysInline,
+ AnalyzerNoReturn, // Clang-specific.
Annotate,
AsmLabel, // Represent GCC asm label extension.
Blocks,
@@ -238,6 +239,17 @@ public:
static bool classof(const Attr *A) { return A->getKind() == NoReturn; }
static bool classof(const NoReturnAttr *A) { return true; }
};
+
+class AnalyzerNoReturnAttr : public Attr {
+public:
+ AnalyzerNoReturnAttr() : Attr(AnalyzerNoReturn) {}
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Attr *A) {
+ return A->getKind() == AnalyzerNoReturn;
+ }
+ static bool classof(const AnalyzerNoReturnAttr *A) { return true; }
+};
class DeprecatedAttr : public Attr {
public:
diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h
index 2113965bee..751d370dda 100644
--- a/include/clang/Parse/AttributeList.h
+++ b/include/clang/Parse/AttributeList.h
@@ -49,6 +49,7 @@ public:
AT_alias,
AT_aligned,
AT_always_inline,
+ AT_analyzer_noreturn,
AT_annotate,
AT_blocks,
AT_cleanup,
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index c7ff0aec27..1d1100a55a 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/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/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index cd192c92ef..14011e5b6f 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/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/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index f3f04f0774..bcc17e7eae 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/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;
diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m
index fede2a2d13..777784aabc 100644
--- a/test/Analysis/misc-ps.m
+++ b/test/Analysis/misc-ps.m
@@ -225,3 +225,23 @@ void pr6708148_test(void) {
pr6708148_use(x); // no-warning
}
+// Handle both kinds of noreturn attributes for pruning paths.
+void rdar_6777003_noret() __attribute__((noreturn));
+void rdar_6777003_analyzer_noret() __attribute__((analyzer_noreturn));
+
+void rdar_6777003(int x) {
+ int *p = 0;
+
+ if (x == 1) {
+ rdar_6777003_noret();
+ *p = 1; // no-warning;
+ }
+
+ if (x == 2) {
+ rdar_6777003_analyzer_noret();
+ *p = 1; // no-warning;
+ }
+
+ *p = 1; // expected-warning{{Dereference of null pointer}}
+}
+