]> granicus.if.org Git - clang/commitdiff
Added:
authorMarcin Swiderski <marcin.sfider@gmail.com>
Fri, 1 Oct 2010 00:23:17 +0000 (00:23 +0000)
committerMarcin Swiderski <marcin.sfider@gmail.com>
Fri, 1 Oct 2010 00:23:17 +0000 (00:23 +0000)
- Adding LocalScope for CompoundStmt,
- Adding CFGAutomaticObjDtors for end of scope, return, goto, break, continue,
- Regression tests for above cases.

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

lib/Analysis/CFG.cpp
test/Analysis/auto-obj-dtors-cfg-output.cpp [new file with mode: 0644]

index 06142dd49408656fed49297ccb4d1a0b9074edf3..a4e24f8b9f9116874f040ee5ee92e856211ca3c5 100644 (file)
@@ -433,6 +433,7 @@ CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C,
     if (LI == LabelMap.end()) continue;
 
     JumpTarget JT = LI->second;
+    prependAutomaticObjDtorsWithTerminator(B, I->ScopePos, JT.ScopePos);
     AddSuccessor(B, JT.Block);
   }
 
@@ -865,6 +866,7 @@ CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
   // If there is no target for the break, then we are looking at an incomplete
   // AST.  This means that the CFG cannot be constructed.
   if (BreakJumpTarget.Block) {
+    addAutomaticObjDtors(ScopePos, BreakJumpTarget.ScopePos, B);
     AddSuccessor(Block, BreakJumpTarget.Block);
   } else
     badCFG = true;
@@ -978,6 +980,7 @@ CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
 
 
 CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
+  addLocalScopeAndDtors(C);
   CFGBlock* LastBlock = Block;
 
   for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
@@ -1117,6 +1120,10 @@ CFGBlock *CFGBuilder::VisitDeclSubExpr(Decl* D) {
        VA = FindVA(VA->getElementType().getTypePtr()))
     Block = addStmt(VA->getSizeExpr());
 
+  // Remove variable from local scope.
+  if (ScopePos && VD == *ScopePos)
+    ++ScopePos;
+
   return Block;
 }
 
@@ -1220,6 +1227,7 @@ CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) {
   Block = createBlock(false);
 
   // The Exit block is the only successor.
+  addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R);
   AddSuccessor(Block, &cfg->getExit());
 
   // Add the return statement to the block.  This may create new blocks if R
@@ -1270,6 +1278,7 @@ CFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) {
     BackpatchBlocks.push_back(JumpSource(Block, ScopePos));
   else {
     JumpTarget JT = I->second;
+    addAutomaticObjDtors(ScopePos, JT.ScopePos, G);
     AddSuccessor(Block, JT.Block);
   }
 
@@ -1809,6 +1818,7 @@ CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
   // If there is no target for the continue, then we are looking at an
   // incomplete AST.  This means the CFG cannot be constructed.
   if (ContinueJumpTarget.Block) {
+    addAutomaticObjDtors(ScopePos, ContinueJumpTarget.ScopePos, C);
     AddSuccessor(Block, ContinueJumpTarget.Block);
   } else
     badCFG = true;
diff --git a/test/Analysis/auto-obj-dtors-cfg-output.cpp b/test/Analysis/auto-obj-dtors-cfg-output.cpp
new file mode 100644 (file)
index 0000000..d3896c5
--- /dev/null
@@ -0,0 +1,151 @@
+// RUN: %clang_cc1 -analyze -cfg-dump -cfg-add-implicit-dtors %s 2>&1 | FileCheck %s
+// XPASS: *
+
+class A {
+public:
+  A() {}
+  ~A() {}
+  operator int() const { return 1; }
+};
+
+extern const bool UV;
+
+void test_const_ref() {
+  A a;
+  const A& b = a;
+  const A& c = A();
+}
+
+void test_scope() {
+  A a;
+  { A c;
+    A d;
+  }
+  A b;
+}
+
+void test_return() {
+  A a;
+  A b;
+  if (UV) return;
+  A c;
+}
+
+void test_goto() {
+  A a;
+l0:
+  A b;
+  { A a;
+    if (UV) goto l0;
+    if (UV) goto l1;
+    A b;
+  }
+l1:
+  A c;
+}
+
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A a;
+// CHECK:       2: const A &b = a;
+// CHECK:       3: const A &c = A();
+// CHECK:       4: [B1.3].~A() (Implicit destructor)
+// CHECK:       5: [B1.1].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B2 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B1
+// CHECK:  [ B1 ]
+// CHECK:       1: A a;
+// CHECK:       2: A c;
+// CHECK:       3: A d;
+// CHECK:       4: [B1.3].~A() (Implicit destructor)
+// CHECK:       5: [B1.2].~A() (Implicit destructor)
+// CHECK:       6: A b;
+// CHECK:       7: [B1.6].~A() (Implicit destructor)
+// CHECK:       8: [B1.1].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B2
+// CHECK:     Successors (1): B0
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):
+// CHECK:  [ B4 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B3
+// CHECK:  [ B1 ]
+// CHECK:       1: A c;
+// CHECK:       2: [B1.1].~A() (Implicit destructor)
+// CHECK:       3: [B3.2].~A() (Implicit destructor)
+// CHECK:       4: [B3.1].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: return;
+// CHECK:       2: [B3.2].~A() (Implicit destructor)
+// CHECK:       3: [B3.1].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B3 ]
+// CHECK:       1: A a;
+// CHECK:       2: A b;
+// CHECK:       3: UV
+// CHECK:       T: if [B3.3]
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (2): B2 B1
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (2): B1 B2
+// CHECK:     Successors (0):
+// CHECK:  [ B8 (ENTRY) ]
+// CHECK:     Predecessors (0):
+// CHECK:     Successors (1): B7
+// CHECK:  [ B1 ]
+// CHECK:     l1:
+// CHECK:       1: A c;
+// CHECK:       2: [B1.1].~A() (Implicit destructor)
+// CHECK:       3: [B6.1].~A() (Implicit destructor)
+// CHECK:       4: [B7.1].~A() (Implicit destructor)
+// CHECK:     Predecessors (2): B2 B3
+// CHECK:     Successors (1): B0
+// CHECK:  [ B2 ]
+// CHECK:       1: A b;
+// CHECK:       2: [B2.1].~A() (Implicit destructor)
+// CHECK:       3: [B6.2].~A() (Implicit destructor)
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B3 ]
+// CHECK:       1: [B6.2].~A() (Implicit destructor)
+// CHECK:       T: goto l1;
+// CHECK:     Predecessors (1): B4
+// CHECK:     Successors (1): B1
+// CHECK:  [ B4 ]
+// CHECK:       1: UV
+// CHECK:       T: if [B4.1]
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (2): B3 B2
+// CHECK:  [ B5 ]
+// CHECK:       1: [B6.2].~A() (Implicit destructor)
+// CHECK:       2: [B6.1].~A() (Implicit destructor)
+// CHECK:       T: goto l0;
+// CHECK:     Predecessors (1): B6
+// CHECK:     Successors (1): B6
+// CHECK:  [ B6 ]
+// CHECK:     l0:
+// CHECK:       1: A b;
+// CHECK:       2: A a;
+// CHECK:       3: UV
+// CHECK:       T: if [B6.3]
+// CHECK:     Predecessors (2): B7 B5
+// CHECK:     Successors (2): B5 B4
+// CHECK:  [ B7 ]
+// CHECK:       1: A a;
+// CHECK:     Predecessors (1): B8
+// CHECK:     Successors (1): B6
+// CHECK:  [ B0 (EXIT) ]
+// CHECK:     Predecessors (1): B1
+// CHECK:     Successors (0):