From: Marcin Swiderski Date: Fri, 1 Oct 2010 00:23:17 +0000 (+0000) Subject: Added: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fcb72ac985c26372315fabc08d43d6f66ff906b4;p=clang Added: - 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 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 06142dd494..a4e24f8b9f 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -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 index 0000000000..d3896c5112 --- /dev/null +++ b/test/Analysis/auto-obj-dtors-cfg-output.cpp @@ -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):