]> granicus.if.org Git - clang/commitdiff
[analyzer] Add very limited support for temporary destructors
authorPavel Labath <labath@google.com>
Wed, 17 Jul 2013 08:33:58 +0000 (08:33 +0000)
committerPavel Labath <labath@google.com>
Wed, 17 Jul 2013 08:33:58 +0000 (08:33 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186498 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
lib/StaticAnalyzer/Core/ExprEngine.cpp
lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
test/Analysis/analyzer-config.c
test/Analysis/analyzer-config.cpp
test/Analysis/dtor.cpp
test/Analysis/temp-obj-dtors-cfg-output.cpp

index 9dcf58babd278c778e51c7933b2887babf224434..93b620410bc44070ee4a347069df64bc4f957433 100644 (file)
@@ -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() {
index 59c66b83c73074d85d625eadc300e6285bd94e16..39ca429e19d3f25d23c8d4331a4c986cad9eaca0 100644 (file)
@@ -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) {
index b76649e6fc6f02deeb10addaaa610a4e212dd0ef..aa7593e7218023870da34badbc592f8c72d888c6 100644 (file)
@@ -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.
index 55b1df9ca8a1d991be7789815b597f9aabe2e3bc..c80eb164b99efc64581483478e2215c5ab4f65d3 100644 (file)
@@ -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
index 521344a5119a8bcbd6b7d9641463475091abed0e..4160508a382b7d3a129ab28f1c38b10bf683814e 100644 (file)
@@ -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
index 58bdcea6317a5cd066390aa9f458da9c5bce6be8..80b31570697bbb14480eca65d070699e4819fada 100644 (file)
@@ -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
+  }
 }
index 1ddccb704b132d8b1719169d4dff37b4a8191409..ff68a876e91049bb80bb78736003a2c1bdf29492 100644 (file)
@@ -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