From: Marcin Swiderski Date: Fri, 1 Oct 2010 01:24:41 +0000 (+0000) Subject: dded generating CFGAutomaticObjDtors for condition variable and implicit scopes in... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8ae6058cecba902c0069c24bdc9c26d475559291;p=clang dded generating CFGAutomaticObjDtors for condition variable and implicit scopes in switch statement. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@115264 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 212f3ea7f3..bc83e20753 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1907,6 +1907,18 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { // block. CFGBlock* SwitchSuccessor = NULL; + // Save local scope position because in case of condition variable ScopePos + // won't be restored when traversing AST. + SaveAndRestore save_scope_pos(ScopePos); + + // Create local scope for possible condition variable. + // Store scope position. Add implicit destructor. + if (VarDecl* VD = Terminator->getConditionVariable()) { + LocalScope::const_iterator SwitchBeginScopePos = ScopePos; + addLocalScopeForVarDecl(VD); + addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator); + } + if (Block) { if (badCFG) return 0; @@ -1936,6 +1948,12 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) { // control-flow from the switch goes to case/default statements. assert(Terminator->getBody() && "switch must contain a non-NULL body"); Block = NULL; + + // If body is not a compound statement create implicit scope + // and add destructors. + if (!isa(Terminator->getBody())) + addLocalScopeAndDtors(Terminator->getBody()); + addStmt(Terminator->getBody()); if (Block) { if (badCFG) diff --git a/test/Analysis/auto-obj-dtors-cfg-output.cpp b/test/Analysis/auto-obj-dtors-cfg-output.cpp index 54fa75717c..daea562570 100644 --- a/test/Analysis/auto-obj-dtors-cfg-output.cpp +++ b/test/Analysis/auto-obj-dtors-cfg-output.cpp @@ -100,6 +100,27 @@ void test_do_jumps() { A d; } +void test_switch_implicit_scope() { + A a; + switch (A b = a) + A c; +} + +void test_switch_jumps() { + A a; + switch (A b = a) { + case 0: { + A c; + if (UV) break; + if (UV) return; + A f; + } + case 1: + break; + } + A g; +} + // CHECK: [ B2 (ENTRY) ] // CHECK: Predecessors (0): // CHECK: Successors (1): B1 @@ -489,3 +510,93 @@ void test_do_jumps() { // CHECK: [ B0 (EXIT) ] // CHECK: Predecessors (2): B1 B4 // CHECK: Successors (0): +// CHECK: [ B4 (ENTRY) ] +// CHECK: Predecessors (0): +// CHECK: Successors (1): B2 +// CHECK: [ B1 ] +// CHECK: 1: [B2.3].~A() (Implicit destructor) +// CHECK: 2: [B2.1].~A() (Implicit destructor) +// CHECK: Predecessors (2): B3 B2 +// CHECK: Successors (1): B0 +// CHECK: [ B2 ] +// CHECK: 1: A a; +// CHECK: 2: a +// CHECK: 3: switch ([B2.4]) +// CHECK: [B3.1] 4: b.operator int() +// CHECK: T: switch [B2.4] +// CHECK: Predecessors (1): B4 +// CHECK: Successors (1): B1 +// CHECK: [ B3 ] +// CHECK: 1: A c; +// CHECK: 2: [B3.1].~A() (Implicit destructor) +// CHECK: Predecessors (0): +// CHECK: Successors (1): B1 +// CHECK: [ B0 (EXIT) ] +// CHECK: Predecessors (1): B1 +// CHECK: Successors (0): +// CHECK: [ B9 (ENTRY) ] +// CHECK: Predecessors (0): +// CHECK: Successors (1): B2 +// CHECK: [ B1 ] +// CHECK: 1: [B2.3].~A() (Implicit destructor) +// CHECK: 2: A g; +// CHECK: 3: [B1.2].~A() (Implicit destructor) +// CHECK: 4: [B2.1].~A() (Implicit destructor) +// CHECK: Predecessors (3): B3 B7 B2 +// CHECK: Successors (1): B0 +// CHECK: [ B2 ] +// CHECK: 1: A a; +// CHECK: 2: a +// CHECK: 3: switch ([B2.4]) { +// CHECK: case 0: +// CHECK: { +// CHECK: [B8.1] if ([B8.2]) +// CHECK: break; +// CHECK: if ([B6.1]) +// CHECK: [B5.1][B4.1] } +// CHECK: case 1: +// CHECK: break; +// CHECK: } +// CHECK: 4: b.operator int() +// CHECK: T: switch [B2.4] +// CHECK: Predecessors (1): B9 +// CHECK: Successors (3): B3 B8 +// CHECK: B1 +// CHECK: [ B3 ] +// CHECK: case 1: +// CHECK: T: break; +// CHECK: Predecessors (2): B2 B4 +// CHECK: Successors (1): B1 +// CHECK: [ B4 ] +// CHECK: 1: A f; +// CHECK: 2: [B4.1].~A() (Implicit destructor) +// CHECK: 3: [B8.1].~A() (Implicit destructor) +// CHECK: Predecessors (1): B6 +// CHECK: Successors (1): B3 +// CHECK: [ B5 ] +// CHECK: 1: return; +// CHECK: 2: [B8.1].~A() (Implicit destructor) +// CHECK: 3: [B2.3].~A() (Implicit destructor) +// CHECK: 4: [B2.1].~A() (Implicit destructor) +// CHECK: Predecessors (1): B6 +// CHECK: Successors (1): B0 +// CHECK: [ B6 ] +// CHECK: 1: UV +// CHECK: T: if [B6.1] +// CHECK: Predecessors (1): B8 +// CHECK: Successors (2): B5 B4 +// CHECK: [ B7 ] +// CHECK: 1: [B8.1].~A() (Implicit destructor) +// CHECK: T: break; +// CHECK: Predecessors (1): B8 +// CHECK: Successors (1): B1 +// CHECK: [ B8 ] +// CHECK: case 0: +// CHECK: 1: A c; +// CHECK: 2: UV +// CHECK: T: if [B8.2] +// CHECK: Predecessors (1): B2 +// CHECK: Successors (2): B7 B6 +// CHECK: [ B0 (EXIT) ] +// CHECK: Predecessors (2): B1 B5 +// CHECK: Successors (0):