]> granicus.if.org Git - clang/commitdiff
Fixed bug in CFG construction when processing switch statements that contain no
authorTed Kremenek <kremenek@apple.com>
Wed, 13 Feb 2008 21:46:34 +0000 (21:46 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 13 Feb 2008 21:46:34 +0000 (21:46 +0000)
"default" case. In such cases, we now correctly add the CFGBlock representing
the code after the switch statement as a successor to the block terminated by
the switch statement.

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

AST/CFG.cpp

index 51b8cb5240a83025eca5979a5490da1523e5dc0d..eb39fdfc01d19538c126b1f7ab0e0b0d4c90216e 100644 (file)
@@ -65,6 +65,7 @@ class VISIBILITY_HIDDEN CFGBuilder : public StmtVisitor<CFGBuilder,CFGBlock*> {
   CFGBlock* ContinueTargetBlock;
   CFGBlock* BreakTargetBlock;
   CFGBlock* SwitchTerminatedBlock;
+  bool      SwitchHasDefaultCase;
   
   // LabelMap records the mapping from Label expressions to their blocks.
   typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
@@ -109,6 +110,7 @@ public:
   CFGBlock* VisitBreakStmt(BreakStmt* B);
   CFGBlock* VisitSwitchStmt(SwitchStmt* S);
   CFGBlock* VisitSwitchCase(SwitchCase* S);
+  CFGBlock* VisitDefaultStmt(DefaultStmt* D);
   CFGBlock* VisitIndirectGotoStmt(IndirectGotoStmt* I);
   
 private:
@@ -884,6 +886,9 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* S) {
   SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock),
                             save_break(BreakTargetBlock);
   
+  SaveAndRestore<bool> save_has_default_case(SwitchHasDefaultCase);
+  SwitchHasDefaultCase = false;
+  
   // Create a new block that will contain the switch statement.
   SwitchTerminatedBlock = createBlock(false);
   
@@ -900,10 +905,16 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* S) {
   CFGBlock *BodyBlock = Visit(S->getBody());
   if (Block) FinishBlock(BodyBlock);
 
+  // If we have no "default:" case, the default transition is to the
+  // code following the switch body.
+  if (!SwitchHasDefaultCase)
+    SwitchTerminatedBlock->addSuccessor(SwitchSuccessor);
+  
   // Add the terminator and condition in the switch block.
   SwitchTerminatedBlock->setTerminator(S);
   assert (S->getCond() && "switch condition must be non-NULL");
   Block = SwitchTerminatedBlock;
+  
   return addStmt(S->getCond());
 }
 
@@ -933,6 +944,11 @@ CFGBlock* CFGBuilder::VisitSwitchCase(SwitchCase* S) {
   
   return CaseBlock;    
 }
+  
+CFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* D) {
+  SwitchHasDefaultCase = true;
+  return VisitSwitchCase(D);
+}
 
 CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) {
   // Lazily create the indirect-goto dispatch block if there isn't one