From: Marcin Swiderski Date: Fri, 1 Oct 2010 01:38:14 +0000 (+0000) Subject: Added generating CFGAutomaticObjDtors for init statement, condition variable and... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47575f1f775f5f250be4f395fa694a7274a65f33;p=clang Added generating CFGAutomaticObjDtors for init statement, condition variable and implicit scope in for statement. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@115265 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index bc83e20753..ac49ca52ca 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -1313,8 +1313,23 @@ CFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) { CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { 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 init statement and possible condition variable. + // Add destructor for init statement and condition variable. + // Store scope position for continue statement. + if (Stmt* Init = F->getInit()) + addLocalScopeForStmt(Init); LocalScope::const_iterator LoopBeginScopePos = ScopePos; + if (VarDecl* VD = F->getConditionVariable()) + addLocalScopeForVarDecl(VD); + LocalScope::const_iterator ContinueScopePos = ScopePos; + + addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F); + // "for" is a control-flow statement. Thus we stop processing the current // block. if (Block) { @@ -1327,7 +1342,7 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { // Save the current value for the break targets. // All breaks should go to the code following the loop. SaveAndRestore save_break(BreakJumpTarget); - BreakJumpTarget = JumpTarget(LoopSuccessor, LoopBeginScopePos); + BreakJumpTarget = JumpTarget(LoopSuccessor, ScopePos); // Because of short-circuit evaluation, the condition of the loop can span // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that @@ -1383,6 +1398,9 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { // Create a new block to contain the (bottom) of the loop body. Block = NULL; + + // Loop body should end with destructor of Condition variable (if any). + addAutomaticObjDtors(ScopePos, LoopBeginScopePos, F); if (Stmt* I = F->getInc()) { // Generate increment code in its own basic block. This is the target of @@ -1392,7 +1410,7 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { // No increment code. Create a special, empty, block that is used as the // target block for "looping back" to the start of the loop. assert(Succ == EntryConditionBlock); - Succ = createBlock(); + Succ = Block ? Block : createBlock(); } // Finish up the increment (or empty) block if it hasn't been already. @@ -1403,12 +1421,17 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) { Block = 0; } - ContinueJumpTarget = JumpTarget(Succ, LoopBeginScopePos); + ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos); // The starting block for the loop increment is the block that should // represent the 'loop target' for looping back to the start of the loop. ContinueJumpTarget.Block->setLoopTarget(F); + // If body is not a compound statement create implicit scope + // and add destructors. + if (!isa(F->getBody())) + addLocalScopeAndDtors(F->getBody()); + // Now populate the body block, and in the process create new blocks as we // walk the body of the loop. CFGBlock* BodyBlock = addStmt(F->getBody()); diff --git a/test/Analysis/auto-obj-dtors-cfg-output.cpp b/test/Analysis/auto-obj-dtors-cfg-output.cpp index daea562570..2024e62ab6 100644 --- a/test/Analysis/auto-obj-dtors-cfg-output.cpp +++ b/test/Analysis/auto-obj-dtors-cfg-output.cpp @@ -121,6 +121,23 @@ void test_switch_jumps() { A g; } +void test_for_implicit_scope() { + for (A a; A b = a; ) + A c; +} + +void test_for_jumps() { + A a; + for (A b; A c = b; ) { + A d; + if (UV) break; + if (UV) continue; + if (UV) return; + A e; + } + A f; +} + // CHECK: [ B2 (ENTRY) ] // CHECK: Predecessors (0): // CHECK: Successors (1): B1 @@ -600,3 +617,112 @@ void test_switch_jumps() { // CHECK: [ B0 (EXIT) ] // CHECK: Predecessors (2): B1 B5 // 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: for (A a; [B2.4];) +// CHECK: [B4.1] 3: b.operator int() +// CHECK: 4: [B2.3] +// CHECK: T: for (...; [B2.4]; ) +// CHECK: Predecessors (2): B3 B5 +// CHECK: Successors (2): B4 B1 +// CHECK: [ B3 ] +// CHECK: 1: [B2.2].~A() (Implicit destructor) +// CHECK: Predecessors (1): B4 +// CHECK: Successors (1): B2 +// CHECK: [ B4 ] +// CHECK: 1: A c; +// CHECK: 2: [B4.1].~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: [B11.2].~A() (Implicit destructor) +// CHECK: 3: A f; +// CHECK: 4: [B1.3].~A() (Implicit destructor) +// CHECK: 5: [B11.1].~A() (Implicit destructor) +// CHECK: Predecessors (2): B9 B2 +// CHECK: Successors (1): B0 +// CHECK: [ B2 ] +// CHECK: 1: b +// CHECK: 2: for (A b; [B2.4];) { +// 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: c.operator int() +// CHECK: 4: [B2.3] +// CHECK: T: for (...; [B2.4]; ) +// CHECK: Predecessors (2): B3 B11 +// CHECK: Successors (2): B10 B1 +// CHECK: [ B3 ] +// CHECK: 1: [B2.2].~A() (Implicit destructor) +// CHECK: Predecessors (2): B4 B7 +// CHECK: Successors (1): B2 +// CHECK: [ B4 ] +// CHECK: 1: A e; +// CHECK: 2: [B4.1].~A() (Implicit destructor) +// CHECK: 3: [B10.1].~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.2].~A() (Implicit destructor) +// CHECK: 5: [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: 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 d; +// CHECK: 2: UV +// CHECK: T: if [B10.2] +// CHECK: Predecessors (1): B2 +// CHECK: Successors (2): B9 B8 +// CHECK: [ B11 ] +// CHECK: 1: A a; +// CHECK: 2: A b; +// CHECK: Predecessors (1): B12 +// CHECK: Successors (1): B2 +// CHECK: [ B0 (EXIT) ] +// CHECK: Predecessors (2): B1 B5 +// CHECK: Successors (0):