aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-02-13 21:46:34 +0000
committerTed Kremenek <kremenek@apple.com>2008-02-13 21:46:34 +0000
commit295222c1f0926d84de77f076e79903523eeb5dbf (patch)
treee0ba7ddf83b98e7df82e9c336a06c3d04b732c07
parent44842c2d4485cc6785ebd72c3f4e53976ce9990e (diff)
Fixed bug in CFG construction when processing switch statements that contain no
"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
-rw-r--r--AST/CFG.cpp16
1 files changed, 16 insertions, 0 deletions
diff --git a/AST/CFG.cpp b/AST/CFG.cpp
index 51b8cb5240..eb39fdfc01 100644
--- a/AST/CFG.cpp
+++ b/AST/CFG.cpp
@@ -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