Fix CFGBuilder to not blow out the stack when processing deeply nested CaseStmts. Fixes <rdar://problem/8268753>.

llvm-svn: 110286
This commit is contained in:
Ted Kremenek 2010-08-04 23:54:30 +00:00
parent c8bd9c277b
commit 60fa657aa2
1 changed files with 32 additions and 5 deletions

View File

@ -1617,9 +1617,30 @@ CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) {
// CaseStmts are essentially labels, so they are the first statement in a
// block.
CFGBlock *TopBlock = 0, *LastBlock = 0;
if (CS->getSubStmt())
addStmt(CS->getSubStmt());
if (Stmt *Sub = CS->getSubStmt()) {
// For deeply nested chains of CaseStmts, instead of doing a recursion
// (which can blow out the stack), manually unroll and create blocks
// along the way.
while (isa<CaseStmt>(Sub)) {
CFGBlock *CurrentBlock = createBlock(false);
CurrentBlock->setLabel(CS);
if (TopBlock)
AddSuccessor(LastBlock, CurrentBlock);
else
TopBlock = CurrentBlock;
AddSuccessor(SwitchTerminatedBlock, CurrentBlock);
LastBlock = CurrentBlock;
CS = cast<CaseStmt>(Sub);
Sub = CS->getSubStmt();
}
addStmt(Sub);
}
CFGBlock* CaseBlock = Block;
if (!CaseBlock)
@ -1640,10 +1661,16 @@ CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) {
// We set Block to NULL to allow lazy creation of a new block (if necessary)
Block = NULL;
if (TopBlock) {
AddSuccessor(LastBlock, CaseBlock);
Succ = TopBlock;
}
else {
// This block is now the implicit successor of other blocks.
Succ = CaseBlock;
}
return CaseBlock;
return Succ;
}
CFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) {