CFGBlock* WalkAST_VisitChildren(Stmt* Terminator);
CFGBlock* WalkAST_VisitDeclSubExpr(Decl* D);
CFGBlock* WalkAST_VisitStmtExpr(StmtExpr* Terminator);
- void FinishBlock(CFGBlock* B);
+ bool FinishBlock(CFGBlock* B);
bool badCFG;
};
/// FinishBlock - When the last statement has been added to the block,
/// we must reverse the statements because they have been inserted
/// in reverse order.
-void CFGBuilder::FinishBlock(CFGBlock* B) {
+bool CFGBuilder::FinishBlock(CFGBlock* B) {
+ if (badCFG)
+ return false;
+
assert (B);
B->reverseStmts();
+ return true;
}
/// addStmt - Used to add statements/expressions to the current CFGBlock
// of the ternary expression.
CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock();
ConfluenceBlock->appendStmt(C);
- FinishBlock(ConfluenceBlock);
+ if (!FinishBlock(ConfluenceBlock))
+ return 0;
// Create a block for the LHS expression if there is an LHS expression.
// A GCC extension allows LHS to be NULL, causing the condition to
CFGBlock* LHSBlock = NULL;
if (C->getLHS()) {
LHSBlock = Visit(C->getLHS());
- FinishBlock(LHSBlock);
- Block = NULL;
+ if (!FinishBlock(LHSBlock))
+ return 0;
+ Block = NULL;
}
// Create the block for the RHS expression.
Succ = ConfluenceBlock;
CFGBlock* RHSBlock = Visit(C->getRHS());
- FinishBlock(RHSBlock);
-
+ if (!FinishBlock(RHSBlock))
+ return 0;
+
// Create the block that will contain the condition.
Block = createBlock(false);
case Stmt::ChooseExprClass: {
ChooseExpr* C = cast<ChooseExpr>(Terminator);
- CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock();
+ CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
ConfluenceBlock->appendStmt(C);
- FinishBlock(ConfluenceBlock);
+ if (!FinishBlock(ConfluenceBlock))
+ return 0;
Succ = ConfluenceBlock;
Block = NULL;
CFGBlock* LHSBlock = Visit(C->getLHS());
- FinishBlock(LHSBlock);
+ if (!FinishBlock(LHSBlock))
+ return 0;
Succ = ConfluenceBlock;
Block = NULL;
CFGBlock* RHSBlock = Visit(C->getRHS());
- FinishBlock(RHSBlock);
+ if (!FinishBlock(RHSBlock))
+ return 0;
Block = createBlock(false);
Block->addSuccessor(LHSBlock);
if (B->isLogicalOp()) { // && or ||
CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock();
ConfluenceBlock->appendStmt(B);
- FinishBlock(ConfluenceBlock);
+ if (!FinishBlock(ConfluenceBlock))
+ return 0;
// create the block evaluating the LHS
CFGBlock* LHSBlock = createBlock(false);
Succ = ConfluenceBlock;
Block = NULL;
CFGBlock* RHSBlock = Visit(B->getRHS());
- FinishBlock(RHSBlock);
+ if (!FinishBlock(RHSBlock))
+ return 0;
// Now link the LHSBlock with RHSBlock.
if (B->getOpcode() == BinaryOperator::LOr) {
// successor block.
if (Block) {
Succ = Block;
- FinishBlock(Block);
+ if (!FinishBlock(Block))
+ return 0;
}
// Process the false branch. NULL out Block so that the recursive
if (!ElseBlock) // Can occur when the Else body has all NullStmts.
ElseBlock = sv.get();
- else if (Block)
- FinishBlock(ElseBlock);
+ else if (Block) {
+ if (!FinishBlock(ElseBlock))
+ return 0;
+ }
}
// Process the true branch. NULL out Block so that the recursive
ThenBlock = createBlock(false);
ThenBlock->addSuccessor(sv.get());
}
- else if (Block)
- FinishBlock(ThenBlock);
+ else if (Block) {
+ if (!FinishBlock(ThenBlock))
+ return 0;
+ }
}
// Now create a new block containing the if statement.
// label (and we have already processed the substatement) there is no
// extra control-flow to worry about.
LabelBlock->setLabel(L);
- FinishBlock(LabelBlock);
+ if (!FinishBlock(LabelBlock))
+ return 0;
// We set Block to NULL to allow lazy creation of a new block
// (if necessary);
CFGBlock* LoopSuccessor = NULL;
if (Block) {
- FinishBlock(Block);
+ if (!FinishBlock(Block))
+ return 0;
LoopSuccessor = Block;
}
else LoopSuccessor = Succ;
if (Stmt* C = F->getCond()) {
Block = ExitConditionBlock;
EntryConditionBlock = addStmt(C);
- if (Block) FinishBlock(EntryConditionBlock);
+ if (Block) {
+ if (!FinishBlock(EntryConditionBlock))
+ return 0;
+ }
}
// The condition block is the implicit successor for the loop body as
// Finish up the increment (or empty) block if it hasn't been already.
if (Block) {
assert(Block == Succ);
- FinishBlock(Block);
+ if (!FinishBlock(Block))
+ return 0;
Block = 0;
}
if (!BodyBlock)
BodyBlock = EntryConditionBlock; // can happen for "for (...;...; ) ;"
- else if (Block)
- FinishBlock(BodyBlock);
+ else if (Block) {
+ if (!FinishBlock(BodyBlock))
+ return 0;
+ }
// This new body block is a successor to our "exit" condition block.
ExitConditionBlock->addSuccessor(BodyBlock);
CFGBlock* LoopSuccessor = 0;
if (Block) {
- FinishBlock(Block);
+ if (!FinishBlock(Block))
+ return 0;
LoopSuccessor = Block;
Block = 0;
}
// generate new blocks as necesary. We DON'T add the statement by default
// to the CFG unless it contains control-flow.
EntryConditionBlock = WalkAST(S->getElement(), false);
- if (Block) { FinishBlock(EntryConditionBlock); Block = 0; }
+ if (Block) {
+ if (!FinishBlock(EntryConditionBlock))
+ return 0;
+ Block = 0;
+ }
// The condition block is the implicit successor for the loop body as
// well as any code above the loop.
if (!BodyBlock)
BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;"
- else if (Block)
- FinishBlock(BodyBlock);
+ else if (Block) {
+ if (!FinishBlock(BodyBlock))
+ return 0;
+ }
// This new body block is a successor to our "exit" condition block.
ExitConditionBlock->addSuccessor(BodyBlock);
CFGBlock* LoopSuccessor = NULL;
if (Block) {
- FinishBlock(Block);
+ if (!FinishBlock(Block))
+ return 0;
LoopSuccessor = Block;
}
else LoopSuccessor = Succ;
Block = ExitConditionBlock;
EntryConditionBlock = addStmt(C);
assert(Block == EntryConditionBlock);
- if (Block) FinishBlock(EntryConditionBlock);
+ if (Block) {
+ if (!FinishBlock(EntryConditionBlock))
+ return 0;
+ }
}
// The condition block is the implicit successor for the loop body as
if (!BodyBlock)
BodyBlock = EntryConditionBlock; // can happen for "while(...) ;"
- else if (Block)
- FinishBlock(BodyBlock);
+ else if (Block) {
+ if (!FinishBlock(BodyBlock))
+ return 0;
+ }
// Add the loop body entry as a successor to the condition.
ExitConditionBlock->addSuccessor(BodyBlock);
// If we were in the middle of a block we stop processing that block
// and reverse its statements.
- if (Block) FinishBlock(Block);
+ if (Block) {
+ if (!FinishBlock(Block))
+ return 0;
+ }
// Create the new block.
Block = createBlock(false);
CFGBlock* LoopSuccessor = NULL;
if (Block) {
- FinishBlock(Block);
+ if (!FinishBlock(Block))
+ return 0;
LoopSuccessor = Block;
}
else LoopSuccessor = Succ;
if (Stmt* C = D->getCond()) {
Block = ExitConditionBlock;
EntryConditionBlock = addStmt(C);
- if (Block) FinishBlock(EntryConditionBlock);
+ if (Block) {
+ if (!FinishBlock(EntryConditionBlock))
+ return 0;
+ }
}
// The condition block is the implicit successor for the loop body.
if (!BodyBlock)
BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"
- else if (Block)
- FinishBlock(BodyBlock);
+ else if (Block) {
+ if (!FinishBlock(BodyBlock))
+ return 0;
+ }
// Add an intermediate block between the BodyBlock and the
// ExitConditionBlock to represent the "loop back" transition.
CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
// "continue" is a control-flow statement. Thus we stop processing the
// current block.
- if (Block) FinishBlock(Block);
+ if (Block) {
+ if (!FinishBlock(Block))
+ return 0;
+ }
// Now create a new block that ends with the continue statement.
Block = createBlock(false);
CFGBlock* CFGBuilder::VisitBreakStmt(BreakStmt* B) {
// "break" is a control-flow statement. Thus we stop processing the
// current block.
- if (Block) FinishBlock(Block);
+ if (Block) {
+ if (!FinishBlock(Block))
+ return 0;
+ }
// Now create a new block that ends with the continue statement.
Block = createBlock(false);
CFGBlock* SwitchSuccessor = NULL;
if (Block) {
- FinishBlock(Block);
+ if (!FinishBlock(Block))
+ return 0;
SwitchSuccessor = Block;
}
else SwitchSuccessor = Succ;
assert (Terminator->getBody() && "switch must contain a non-NULL body");
Block = NULL;
CFGBlock *BodyBlock = Visit(Terminator->getBody());
- if (Block) FinishBlock(BodyBlock);
+ if (Block) {
+ if (!FinishBlock(BodyBlock))
+ return 0;
+ }
// If we have no "default:" case, the default transition is to the
// code following the switch body.
// Cases statements partition blocks, so this is the top of
// the basic block we were processing (the "case XXX:" is the label).
CaseBlock->setLabel(Terminator);
- FinishBlock(CaseBlock);
+ if (!FinishBlock(CaseBlock))
+ return 0;
// Add this block to the list of successors for the block with the
// switch statement.
// Default statements partition blocks, so this is the top of
// the basic block we were processing (the "default:" is the label).
DefaultCaseBlock->setLabel(Terminator);
- FinishBlock(DefaultCaseBlock);
+ if (!FinishBlock(DefaultCaseBlock))
+ return 0;
// Unlike case statements, we don't add the default block to the
// successors for the switch statement immediately. This is done
// IndirectGoto is a control-flow statement. Thus we stop processing the
// current block and create a new one.
- if (Block) FinishBlock(Block);
+ if (Block) {
+ if (!FinishBlock(Block))
+ return 0;
+ }
Block = createBlock(false);
Block->setTerminator(I);
Block->addSuccessor(IBlock);