summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Labath <labath@google.com>2013-07-17 08:33:58 +0000
committerPavel Labath <labath@google.com>2013-07-17 08:33:58 +0000
commit9ced602cc67e33e7e6136325f1503037ace2b1a6 (patch)
tree97bc4481890be6898960dd27db763cb47718839b
parentc2e4e95580e37ff09b61833ba7c55ed9a3ffd80f (diff)
downloadbcm5719-llvm-9ced602cc67e33e7e6136325f1503037ace2b1a6.tar.gz
bcm5719-llvm-9ced602cc67e33e7e6136325f1503037ace2b1a6.zip
[analyzer] Add very limited support for temporary destructors
Summary: This patch enables ExprEndgine to reason about temporary object destructors. However, these destructor calls are never inlined, since this feature is still broken. Still, this is sufficient to properly handle noreturn temporary destructors and close bug #15599. I have also enabled the cfg-temporary-dtors analyzer option by default. Reviewers: jordan_rose CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D1131 llvm-svn: 186498
-rw-r--r--clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp2
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp10
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp6
-rw-r--r--clang/test/Analysis/analyzer-config.c2
-rw-r--r--clang/test/Analysis/analyzer-config.cpp2
-rw-r--r--clang/test/Analysis/dtor.cpp15
-rw-r--r--clang/test/Analysis/temp-obj-dtors-cfg-output.cpp51
7 files changed, 84 insertions, 4 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 9dcf58babd2..93b620410bc 100644
--- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -119,7 +119,7 @@ bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name,
bool AnalyzerOptions::includeTemporaryDtorsInCFG() {
return getBooleanOption(IncludeTemporaryDtorsInCFG,
"cfg-temporary-dtors",
- /* Default = */ false);
+ /* Default = */ true);
}
bool AnalyzerOptions::mayInlineCXXStandardLibrary() {
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 59c66b83c73..39ca429e19d 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -589,7 +589,15 @@ void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {}
+ ExplodedNodeSet &Dst) {
+
+ QualType varType = D.getBindTemporaryExpr()->getSubExpr()->getType();
+
+ // FIXME: Inlining of temporary destructors is not supported yet anyway, so we
+ // just put a NULL region for now. This will need to be changed later.
+ VisitCXXDestructor(varType, NULL, D.getBindTemporaryExpr(),
+ /*IsBase=*/ false, Pred, Dst);
+}
void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet &DstTop) {
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index b76649e6fc6..aa7593e7218 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -804,6 +804,12 @@ bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();
AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);
+ // Temporary object destructor processing is currently broken, so we never
+ // inline them.
+ // FIME: Remove this once temp destructors are working.
+ if ((*currBldrCtx->getBlock())[currStmtIdx].getAs<CFGTemporaryDtor>())
+ return false;
+
// The auto-synthesized bodies are essential to inline as they are
// usually small and commonly used. Note: we should do this check early on to
// ensure we always inline these calls.
diff --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c
index 55b1df9ca8a..c80eb164b99 100644
--- a/clang/test/Analysis/analyzer-config.c
+++ b/clang/test/Analysis/analyzer-config.c
@@ -6,7 +6,7 @@ void foo() { bar(); }
// CHECK: [config]
// CHECK-NEXT: cfg-conditional-static-initializers = true
-// CHECK-NEXT: cfg-temporary-dtors = false
+// CHECK-NEXT: cfg-temporary-dtors = true
// CHECK-NEXT: faux-bodies = true
// CHECK-NEXT: graph-trim-interval = 1000
// CHECK-NEXT: ipa = dynamic-bifurcate
diff --git a/clang/test/Analysis/analyzer-config.cpp b/clang/test/Analysis/analyzer-config.cpp
index 521344a5119..4160508a382 100644
--- a/clang/test/Analysis/analyzer-config.cpp
+++ b/clang/test/Analysis/analyzer-config.cpp
@@ -17,7 +17,7 @@ public:
// CHECK-NEXT: c++-stdlib-inlining = true
// CHECK-NEXT: c++-template-inlining = true
// CHECK-NEXT: cfg-conditional-static-initializers = true
-// CHECK-NEXT: cfg-temporary-dtors = false
+// CHECK-NEXT: cfg-temporary-dtors = true
// CHECK-NEXT: faux-bodies = true
// CHECK-NEXT: graph-trim-interval = 1000
// CHECK-NEXT: ipa = dynamic-bifurcate
diff --git a/clang/test/Analysis/dtor.cpp b/clang/test/Analysis/dtor.cpp
index 58bdcea6317..80b31570697 100644
--- a/clang/test/Analysis/dtor.cpp
+++ b/clang/test/Analysis/dtor.cpp
@@ -416,4 +416,19 @@ namespace NoReturn {
f(&x);
*x = 47; // no warning
}
+
+ void g2(int *x) {
+ if (! x) NR();
+ *x = 47; // no warning
+ }
+
+ void f3(int **x) {
+ NR();
+ }
+
+ void g3() {
+ int *x;
+ f3(&x);
+ *x = 47; // no warning
+ }
}
diff --git a/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp b/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
index 1ddccb704b1..ff68a876e91 100644
--- a/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ b/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -108,6 +108,24 @@ TestCtorInits::TestCtorInits()
: a(int(A()) + int(B()))
, b() {}
+class NoReturn {
+public:
+ ~NoReturn() __attribute__((noreturn));
+ void f();
+};
+
+void test_noreturn1() {
+ int a;
+ NoReturn().f();
+ int b;
+}
+
+void test_noreturn2() {
+ int a;
+ NoReturn(), 47;
+ int b;
+}
+
// CHECK: [B1 (ENTRY)]
// CHECK: Succs (1): B0
// CHECK: [B0 (EXIT)]
@@ -846,3 +864,36 @@ TestCtorInits::TestCtorInits()
// CHECK: [B0 (EXIT)]
// CHECK: Preds (1): B1
+// CHECK: [B3 (ENTRY)]
+// CHECK: Succs (1): B2
+// CHECK: [B1]
+// CHECK: 1: int b;
+// CHECK: Succs (1): B0
+// CHECK: [B2]
+// CHECK: 1: int a;
+// CHECK: 2: NoReturn() (CXXConstructExpr, class NoReturn)
+// CHECK: 3: [B2.2] (BindTemporary)
+// CHECK: 4: [B2.3].f
+// CHECK: 5: [B2.4]()
+// CHECK: 6: ~NoReturn() (Temporary object destructor)
+// CHECK: Preds (1): B3
+// CHECK: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK: Preds (2): B1 B2
+
+// CHECK: [B3 (ENTRY)]
+// CHECK: Succs (1): B2
+// CHECK: [B1]
+// CHECK: 1: int b;
+// CHECK: Succs (1): B0
+// CHECK: [B2]
+// CHECK: 1: int a;
+// CHECK: 2: NoReturn() (CXXConstructExpr, class NoReturn)
+// CHECK: 3: [B2.2] (BindTemporary)
+// CHECK: 4: 47
+// CHECK: 5: ... , [B2.4]
+// CHECK: 6: ~NoReturn() (Temporary object destructor)
+// CHECK: Preds (1): B3
+// CHECK: Succs (1): B0
+// CHECK: [B0 (EXIT)]
+// CHECK: Preds (2): B1 B2
OpenPOWER on IntegriCloud