]> granicus.if.org Git - clang/commitdiff
Added support for "break" statements in source-level ASTs.
authorTed Kremenek <kremenek@apple.com>
Wed, 22 Aug 2007 21:51:58 +0000 (21:51 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 22 Aug 2007 21:51:58 +0000 (21:51 +0000)
Some comment cleanups.

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

AST/CFG.cpp

index 98d9c8f8f865f2cc3c6ead3fbc888f437524823d..eb358281ef2275c2c7921a63761621d63076ef34 100644 (file)
@@ -56,6 +56,7 @@ class CFGBuilder : public StmtVisitor<CFGBuilder,CFGBlock*> {
   CFGBlock* Exit;
   CFGBlock* Succ;
   CFGBlock* ContinueTargetBlock;
+  CFGBlock* BreakTargetBlock;
   unsigned NumBlocks;
   
   typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
@@ -66,7 +67,7 @@ class CFGBuilder : public StmtVisitor<CFGBuilder,CFGBlock*> {
   
 public:  
   explicit CFGBuilder() : cfg(NULL), Block(NULL), Exit(NULL), Succ(NULL),
-                          ContinueTargetBlock(NULL),
+                          ContinueTargetBlock(NULL), BreakTargetBlock(NULL),
                           NumBlocks(0) {
     // Create an empty CFG.
     cfg = new CFG();                        
@@ -336,11 +337,15 @@ public:
       
       // Save the current values for Block, Succ, and ContinueTargetBlock
       SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
-                                save_continue(ContinueTargetBlock);
+                                save_continue(ContinueTargetBlock),
+                                save_break(BreakTargetBlock);
       
       // All continues within this loop should go to the condition block
       ContinueTargetBlock = ConditionBlock;
       
+      // All breaks should go to the code that follows the loop.
+      BreakTargetBlock = Block;
+      
       // create a new block to contain the body.      
       Block = createBlock();
       
@@ -389,11 +394,15 @@ public:
       
       // Save the current values for Block, Succ, and ContinueTargetBlock
       SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
-                                save_continue(ContinueTargetBlock);
+                                save_continue(ContinueTargetBlock),
+                                save_break(BreakTargetBlock);
 
       // All continues within this loop should go to the condition block
       ContinueTargetBlock = ConditionBlock;
       
+      // All breaks should go to the code that follows the loop.
+      BreakTargetBlock = Block;
+      
       // NULL out Block to force lazy instantiation of blocks for the body.
       Block = NULL;
       
@@ -403,6 +412,8 @@ public:
       ConditionBlock->addSuccessor(BodyBlock);
     }
     
+    // Link up the condition block with the code that follows the loop.
+    // (the false branch).
     ConditionBlock->addSuccessor(Block);
     
     // There can be no more statements in the condition block
@@ -414,7 +425,7 @@ public:
   }
   
   CFGBlock* VisitContinueStmt(ContinueStmt* C) {
-    // While is a control-flow statement.  Thus we stop processing the
+    // "continue" is a control-flow statement.  Thus we stop processing the
     // current block.
     if (Block) FinishBlock(Block);
     
@@ -429,6 +440,22 @@ public:
     return Block;
   }
   
+  CFGBlock* VisitBreakStmt(BreakStmt* B) {
+    // "break" is a control-flow statement.  Thus we stop processing the
+    // current block.
+    if (Block) FinishBlock(Block);
+    
+    // Now create a new block that ends with the continue statement.
+    Block = createBlock(false);
+    Block->setTerminator(B);
+    
+    // FIXME: We should gracefully handle breaks without resolved targets.
+    assert (BreakTargetBlock);
+    
+    Block->addSuccessor(BreakTargetBlock);
+    return Block;  
+  }
+  
 };
 
 // BuildCFG - A helper function that builds CFGs from ASTS.