From: Marcin Swiderski Date: Fri, 1 Oct 2010 01:14:17 +0000 (+0000) Subject: Added generating CFGAutomaticObjDtors for condition variable and implicit scopes... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=05adedcb5e199e377e35f576288caf5ceed40136;p=clang Added generating CFGAutomaticObjDtors for condition variable and implicit scopes in while and do statements. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@115262 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index fd8b009aba..212f3ea7f3 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1584,7 +1584,17 @@ CFGBlock* CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt* S) { CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { CFGBlock* LoopSuccessor = 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 for continue statement. LocalScope::const_iterator LoopBeginScopePos = ScopePos; + if (VarDecl* VD = W->getConditionVariable()) { + addLocalScopeForVarDecl(VD); + addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); + } // "while" is a control-flow statement. Thus we stop processing the current // block. @@ -1654,11 +1664,19 @@ CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) { ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); // All breaks should go to the code following the loop. - BreakJumpTarget = JumpTarget(LoopSuccessor, LoopBeginScopePos); + BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); // NULL out Block to force lazy instantiation of blocks for the body. Block = NULL; + // Loop body should end with destructor of Condition variable (if any). + addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W); + + // If body is not a compound statement create implicit scope + // and add destructors. + if (!isa(W->getBody())) + addLocalScopeAndDtors(W->getBody()); + // Create the body. The returned block is the entry to the loop body. CFGBlock* BodyBlock = addStmt(W->getBody()); @@ -1789,6 +1807,11 @@ CFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) { // NULL out Block to force lazy instantiation of blocks for the body. Block = NULL; + // If body is not a compound statement create implicit scope + // and add destructors. + if (!isa(D->getBody())) + addLocalScopeAndDtors(D->getBody()); + // Create the body. The returned block is the entry to the loop body. BodyBlock = addStmt(D->getBody()); diff --git a/test/Analysis/auto-obj-dtors-cfg-output.cpp b/test/Analysis/auto-obj-dtors-cfg-output.cpp index ce3454d008..54fa75717c 100644 --- a/test/Analysis/auto-obj-dtors-cfg-output.cpp +++ b/test/Analysis/auto-obj-dtors-cfg-output.cpp @@ -65,6 +65,41 @@ void test_if_jumps() { A e; } +void test_while_implicit_scope() { + A a; + while (A b = a) + A c; +} + +void test_while_jumps() { + A a; + while (A b = a) { + A c; + if (UV) break; + if (UV) continue; + if (UV) return; + A d; + } + A e; +} + +void test_do_implicit_scope() { + do A a; + while (UV); +} + +void test_do_jumps() { + A a; + do { + A b; + if (UV) break; + if (UV) continue; + if (UV) return; + A c; + } while (UV); + A d; +} + // CHECK: [ B2 (ENTRY) ] // CHECK: Predecessors (0): // CHECK: Successors (1): B1 @@ -265,3 +300,192 @@ void test_if_jumps() { // CHECK: [ B0 (EXIT) ] // CHECK: Predecessors (3): B1 B3 B6 // CHECK: Successors (0): +// CHECK: [ B6 (ENTRY) ] +// CHECK: Predecessors (0): +// CHECK: Successors (1): B5 +// CHECK: [ B1 ] +// CHECK: 1: [B2.2].~A() (Implicit destructor) +// CHECK: 2: [B5.1].~A() (Implicit destructor) +// CHECK: Predecessors (1): B2 +// CHECK: Successors (1): B0 +// CHECK: [ B2 ] +// CHECK: 1: a +// CHECK: 2: while ([B2.4]) +// CHECK: [B4.1] 3: b.operator int() +// CHECK: 4: [B2.3] +// CHECK: T: while [B2.4] +// CHECK: Predecessors (2): B3 B5 +// CHECK: Successors (2): B4 B1 +// CHECK: [ B3 ] +// CHECK: Predecessors (1): B4 +// CHECK: Successors (1): B2 +// CHECK: [ B4 ] +// CHECK: 1: A c; +// CHECK: 2: [B4.1].~A() (Implicit destructor) +// CHECK: 3: [B2.2].~A() (Implicit destructor) +// CHECK: Predecessors (1): B2 +// CHECK: Successors (1): B3 +// CHECK: [ B5 ] +// CHECK: 1: A a; +// CHECK: Predecessors (1): B6 +// CHECK: Successors (1): B2 +// CHECK: [ B0 (EXIT) ] +// CHECK: Predecessors (1): B1 +// CHECK: Successors (0): +// CHECK: [ B12 (ENTRY) ] +// CHECK: Predecessors (0): +// CHECK: Successors (1): B11 +// CHECK: [ B1 ] +// CHECK: 1: [B2.2].~A() (Implicit destructor) +// CHECK: 2: A e; +// CHECK: 3: [B1.2].~A() (Implicit destructor) +// CHECK: 4: [B11.1].~A() (Implicit destructor) +// CHECK: Predecessors (2): B9 B2 +// CHECK: Successors (1): B0 +// CHECK: [ B2 ] +// CHECK: 1: a +// CHECK: 2: while ([B2.4]) +// CHECK: { +// CHECK: [B10.1] if ([B10.2]) +// CHECK: break; +// CHECK: if ([B8.1]) +// CHECK: continue; +// CHECK: if ([B6.1]) +// CHECK: [B5.1][B4.1] } +// CHECK: 3: b.operator int() +// CHECK: 4: [B2.3] +// CHECK: T: while [B2.4] +// CHECK: Predecessors (2): B3 B11 +// CHECK: Successors (2): B10 B1 +// CHECK: [ B3 ] +// CHECK: Predecessors (2): B4 B7 +// CHECK: Successors (1): B2 +// CHECK: [ B4 ] +// CHECK: 1: A d; +// CHECK: 2: [B4.1].~A() (Implicit destructor) +// CHECK: 3: [B10.1].~A() (Implicit destructor) +// CHECK: 4: [B2.2].~A() (Implicit destructor) +// CHECK: Predecessors (1): B6 +// CHECK: Successors (1): B3 +// CHECK: [ B5 ] +// CHECK: 1: return; +// CHECK: 2: [B10.1].~A() (Implicit destructor) +// CHECK: 3: [B2.2].~A() (Implicit destructor) +// CHECK: 4: [B11.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: [B10.1].~A() (Implicit destructor) +// CHECK: 2: [B2.2].~A() (Implicit destructor) +// CHECK: T: continue; +// CHECK: Predecessors (1): B8 +// CHECK: Successors (1): B3 +// CHECK: [ B8 ] +// CHECK: 1: UV +// CHECK: T: if [B8.1] +// CHECK: Predecessors (1): B10 +// CHECK: Successors (2): B7 B6 +// CHECK: [ B9 ] +// CHECK: 1: [B10.1].~A() (Implicit destructor) +// CHECK: T: break; +// CHECK: Predecessors (1): B10 +// CHECK: Successors (1): B1 +// CHECK: [ B10 ] +// CHECK: 1: A c; +// CHECK: 2: UV +// CHECK: T: if [B10.2] +// CHECK: Predecessors (1): B2 +// CHECK: Successors (2): B9 B8 +// CHECK: [ B11 ] +// CHECK: 1: A a; +// CHECK: Predecessors (1): B12 +// CHECK: Successors (1): B2 +// CHECK: [ B0 (EXIT) ] +// CHECK: Predecessors (2): B1 B5 +// CHECK: Successors (0): +// CHECK: [ B4 (ENTRY) ] +// CHECK: Predecessors (0): +// CHECK: Successors (1): B2 +// CHECK: [ B1 ] +// CHECK: 1: UV +// CHECK: T: do ... while [B1.1] +// CHECK: Predecessors (1): B2 +// CHECK: Successors (2): B3 B0 +// CHECK: [ B2 ] +// CHECK: 1: A a; +// CHECK: 2: [B2.1].~A() (Implicit destructor) +// CHECK: Predecessors (2): B3 B4 +// CHECK: Successors (1): B1 +// CHECK: [ B3 ] +// CHECK: Predecessors (1): B1 +// CHECK: Successors (1): B2 +// CHECK: [ B0 (EXIT) ] +// CHECK: Predecessors (1): B1 +// CHECK: Successors (0): +// CHECK: [ B12 (ENTRY) ] +// CHECK: Predecessors (0): +// CHECK: Successors (1): B11 +// CHECK: [ B1 ] +// CHECK: 1: A d; +// CHECK: 2: [B1.1].~A() (Implicit destructor) +// CHECK: 3: [B11.1].~A() (Implicit destructor) +// CHECK: Predecessors (2): B8 B2 +// CHECK: Successors (1): B0 +// CHECK: [ B2 ] +// CHECK: 1: UV +// CHECK: T: do ... while [B2.1] +// CHECK: Predecessors (2): B3 B6 +// CHECK: Successors (2): B10 B1 +// CHECK: [ B3 ] +// CHECK: 1: A c; +// CHECK: 2: [B3.1].~A() (Implicit destructor) +// CHECK: 3: [B9.1].~A() (Implicit destructor) +// CHECK: Predecessors (1): B5 +// CHECK: Successors (1): B2 +// CHECK: [ B4 ] +// CHECK: 1: return; +// CHECK: 2: [B9.1].~A() (Implicit destructor) +// CHECK: 3: [B11.1].~A() (Implicit destructor) +// CHECK: Predecessors (1): B5 +// CHECK: Successors (1): B0 +// CHECK: [ B5 ] +// CHECK: 1: UV +// CHECK: T: if [B5.1] +// CHECK: Predecessors (1): B7 +// CHECK: Successors (2): B4 B3 +// CHECK: [ B6 ] +// CHECK: 1: [B9.1].~A() (Implicit destructor) +// CHECK: T: continue; +// CHECK: Predecessors (1): B7 +// CHECK: Successors (1): B2 +// CHECK: [ B7 ] +// CHECK: 1: UV +// CHECK: T: if [B7.1] +// CHECK: Predecessors (1): B9 +// CHECK: Successors (2): B6 B5 +// CHECK: [ B8 ] +// CHECK: 1: [B9.1].~A() (Implicit destructor) +// CHECK: T: break; +// CHECK: Predecessors (1): B9 +// CHECK: Successors (1): B1 +// CHECK: [ B9 ] +// CHECK: 1: A b; +// CHECK: 2: UV +// CHECK: T: if [B9.2] +// CHECK: Predecessors (2): B10 B11 +// CHECK: Successors (2): B8 B7 +// CHECK: [ B10 ] +// CHECK: Predecessors (1): B2 +// CHECK: Successors (1): B9 +// CHECK: [ B11 ] +// CHECK: 1: A a; +// CHECK: Predecessors (1): B12 +// CHECK: Successors (1): B9 +// CHECK: [ B0 (EXIT) ] +// CHECK: Predecessors (2): B1 B4 +// CHECK: Successors (0):