aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-02-09 21:59:52 +0000
committerTed Kremenek <kremenek@apple.com>2012-02-09 21:59:52 +0000
commit10520d76044e8fff71d414f30c21b449fd104960 (patch)
tree821c010e7bac996930dca45efecef887f8f7e77f
parentbb3d14e55d267bf5228699c7bf0c8ccdb71c8f46 (diff)
[analyzer] Proactively avoid inlining vararg functions and blocks until we properly support them.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150207 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp26
-rw-r--r--test/Analysis/inline-not-supported.c29
2 files changed, 54 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 94c5860824..c1591397d0 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -309,6 +309,30 @@ ExprEngine::invalidateArguments(ProgramStateRef State,
}
+// For now, skip inlining variadic functions.
+// We also don't inline blocks.
+static bool shouldInlineCall(const CallExpr *CE, ExprEngine &Eng) {
+ if (!Eng.getAnalysisManager().shouldInlineCall())
+ return false;
+ QualType callee = CE->getCallee()->getType();
+ const FunctionProtoType *FT = 0;
+ if (const PointerType *PT = callee->getAs<PointerType>())
+ FT = dyn_cast<FunctionProtoType>(PT->getPointeeType());
+ else if (const BlockPointerType *BT = callee->getAs<BlockPointerType>()) {
+ // FIXME: inline blocks.
+ // FT = dyn_cast<FunctionProtoType>(BT->getPointeeType());
+ (void) BT;
+ return false;
+ }
+
+ // If we have no prototype, assume the function is okay.
+ if (!FT)
+ return true;
+
+ // Skip inlining of variadic functions.
+ return !FT->isVariadic();
+}
+
void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
ExplodedNodeSet &dst) {
// Perform the previsit of the CallExpr.
@@ -325,7 +349,7 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
: Eng(eng), CE(ce) {}
virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) {
// Should we inline the call?
- if (Eng.getAnalysisManager().shouldInlineCall() &&
+ if (shouldInlineCall(CE, Eng) &&
Eng.InlineCall(Dst, CE, Pred)) {
return;
}
diff --git a/test/Analysis/inline-not-supported.c b/test/Analysis/inline-not-supported.c
new file mode 100644
index 0000000000..0bde6f7e21
--- /dev/null
+++ b/test/Analysis/inline-not-supported.c
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s
+
+// For now, don't inline varargs.
+void foo(int *x, ...) {
+ *x = 1;
+}
+
+void bar() {
+ foo(0, 2); // no-warning
+}
+
+// For now, don't inline vararg blocks.
+void (^baz)(int *x, ...) = ^(int *x, ...) { *x = 1; };
+
+void taz() {
+ baz(0, 2); // no-warning
+}
+
+// For now, don't inline blocks.
+void (^qux)(int *p) = ^(int *p) { *p = 1; };
+void test_qux() {
+ qux(0); // no-warning
+}
+
+
+void test_analyzer_is_running() {
+ int *p = 0;
+ *p = 0xDEADBEEF; // expected-warning {{null}}
+}