CFGBlock* ContinueTargetBlock;
CFGBlock* BreakTargetBlock;
CFGBlock* SwitchTerminatedBlock;
+ bool SwitchHasDefaultCase;
// LabelMap records the mapping from Label expressions to their blocks.
typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
CFGBlock* VisitBreakStmt(BreakStmt* B);
CFGBlock* VisitSwitchStmt(SwitchStmt* S);
CFGBlock* VisitSwitchCase(SwitchCase* S);
+ CFGBlock* VisitDefaultStmt(DefaultStmt* D);
CFGBlock* VisitIndirectGotoStmt(IndirectGotoStmt* I);
private:
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);
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());
}
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