void autoCreateBlock() { if (!Block) Block = createBlock(); }
CFGBlock *createBlock(bool add_successor = true);
- bool FinishBlock(CFGBlock* B);
+
CFGBlock *addStmt(Stmt *S) {
return Visit(S, AddStmtChoice::AlwaysAdd);
}
return B;
}
-/// FinishBlock - "Finalize" the block by checking if we have a bad CFG.
-bool CFGBuilder::FinishBlock(CFGBlock* B) {
- if (badCFG)
- return false;
-
- assert(B);
- return true;
-}
-
/// Visit - Walk the subtree of a statement and add extra
/// blocks for ternary operators, &&, and ||. We also process "," and
/// DeclStmts (which may contain nested control-flow).
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
AppendStmt(ConfluenceBlock, B, asc);
- if (!FinishBlock(ConfluenceBlock))
+ if (badCFG)
return 0;
// create the block evaluating the LHS
CFGBlock* RHSBlock = addStmt(B->getRHS());
if (RHSBlock) {
- if (!FinishBlock(RHSBlock))
+ if (badCFG)
return 0;
}
else {
CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
// "break" is a control-flow statement. Thus we stop processing the current
// block.
- if (Block && !FinishBlock(Block))
- return 0;
+ if (badCFG)
+ return 0;
// Now create a new block that ends with the break statement.
Block = createBlock(false);
if (Block) {
Succ = Block;
- if (!FinishBlock(Block))
+ if (badCFG)
return 0;
}
AddStmtChoice asc) {
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
AppendStmt(ConfluenceBlock, C, asc);
- if (!FinishBlock(ConfluenceBlock))
+ if (badCFG)
return 0;
asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue
Succ = ConfluenceBlock;
Block = NULL;
CFGBlock* LHSBlock = Visit(C->getLHS(), asc);
- if (!FinishBlock(LHSBlock))
+ if (badCFG)
return 0;
Succ = ConfluenceBlock;
Block = NULL;
CFGBlock* RHSBlock = Visit(C->getRHS(), asc);
- if (!FinishBlock(RHSBlock))
+ if (badCFG)
return 0;
Block = createBlock(false);
// expression.
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
AppendStmt(ConfluenceBlock, C, asc);
- if (!FinishBlock(ConfluenceBlock))
+ if (badCFG)
return 0;
asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue
CFGBlock* LHSBlock = NULL;
if (C->getLHS()) {
LHSBlock = Visit(C->getLHS(), asc);
- if (!FinishBlock(LHSBlock))
+ if (badCFG)
return 0;
Block = NULL;
}
// Create the block for the RHS expression.
Succ = ConfluenceBlock;
CFGBlock* RHSBlock = Visit(C->getRHS(), asc);
- if (!FinishBlock(RHSBlock))
+ if (badCFG)
return 0;
// Create the block that will contain the condition.
// block.
if (Block) {
Succ = Block;
- if (!FinishBlock(Block))
+ if (badCFG)
return 0;
}
if (!ElseBlock) // Can occur when the Else body has all NullStmts.
ElseBlock = sv.get();
else if (Block) {
- if (!FinishBlock(ElseBlock))
+ if (badCFG)
return 0;
}
}
ThenBlock = createBlock(false);
AddSuccessor(ThenBlock, sv.get());
} else if (Block) {
- if (!FinishBlock(ThenBlock))
+ if (badCFG)
return 0;
}
}
// code afterwards is DEAD (unreachable). We still keep a basic block
// for that code; a simple "mark-and-sweep" from the entry block will be
// able to report such dead blocks.
- if (Block)
- FinishBlock(Block);
// Create the new block.
Block = createBlock(false);
// already processed the substatement) there is no extra control-flow to worry
// about.
LabelBlock->setLabel(L);
- if (!FinishBlock(LabelBlock))
+ if (badCFG)
return 0;
// We set Block to NULL to allow lazy creation of a new block (if necessary);
CFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) {
// Goto is a control-flow statement. Thus we stop processing the current
// block and create a new one.
- if (Block)
- FinishBlock(Block);
Block = createBlock(false);
Block->setTerminator(G);
// "for" is a control-flow statement. Thus we stop processing the current
// block.
if (Block) {
- if (!FinishBlock(Block))
+ if (badCFG)
return 0;
LoopSuccessor = Block;
} else
}
if (Block) {
- if (!FinishBlock(EntryConditionBlock))
+ if (badCFG)
return 0;
}
}
// Finish up the increment (or empty) block if it hasn't been already.
if (Block) {
assert(Block == Succ);
- if (!FinishBlock(Block))
+ if (badCFG)
return 0;
Block = 0;
}
if (!BodyBlock)
BodyBlock = ContinueTargetBlock; // can happen for "for (...;...;...) ;"
- else if (Block && !FinishBlock(BodyBlock))
+ else if (badCFG)
return 0;
// This new body block is a successor to our "exit" condition block.
CFGBlock* LoopSuccessor = 0;
if (Block) {
- if (!FinishBlock(Block))
+ if (badCFG)
return 0;
LoopSuccessor = Block;
Block = 0;
// the CFG unless it contains control-flow.
EntryConditionBlock = Visit(S->getElement(), AddStmtChoice::NotAlwaysAdd);
if (Block) {
- if (!FinishBlock(EntryConditionBlock))
+ if (badCFG)
return 0;
Block = 0;
}
if (!BodyBlock)
BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;"
else if (Block) {
- if (!FinishBlock(BodyBlock))
+ if (badCFG)
return 0;
}
// The sync body starts its own basic block. This makes it a little easier
// for diagnostic clients.
if (SyncBlock) {
- if (!FinishBlock(SyncBlock))
+ if (badCFG)
return 0;
Block = 0;
// "while" is a control-flow statement. Thus we stop processing the current
// block.
if (Block) {
- if (!FinishBlock(Block))
+ if (badCFG)
return 0;
LoopSuccessor = Block;
} else
}
if (Block) {
- if (!FinishBlock(EntryConditionBlock))
+ if (badCFG)
return 0;
}
}
if (!BodyBlock)
BodyBlock = ContinueTargetBlock; // can happen for "while(...) ;"
else if (Block) {
- if (!FinishBlock(BodyBlock))
+ if (badCFG)
return 0;
}
// statement.
// If we were in the middle of a block we stop processing that block.
- if (Block && !FinishBlock(Block))
+ if (badCFG)
return 0;
// Create the new block.
CFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) {
// If we were in the middle of a block we stop processing that block.
- if (Block && !FinishBlock(Block))
+ if (badCFG)
return 0;
// Create the new block.
// "do...while" is a control-flow statement. Thus we stop processing the
// current block.
if (Block) {
- if (!FinishBlock(Block))
+ if (badCFG)
return 0;
LoopSuccessor = Block;
} else
Block = ExitConditionBlock;
EntryConditionBlock = addStmt(C);
if (Block) {
- if (!FinishBlock(EntryConditionBlock))
+ if (badCFG)
return 0;
}
}
if (!BodyBlock)
BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"
else if (Block) {
- if (!FinishBlock(BodyBlock))
+ if (badCFG)
return 0;
}
CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
// "continue" is a control-flow statement. Thus we stop processing the
// current block.
- if (Block && !FinishBlock(Block))
- return 0;
+ if (badCFG)
+ return 0;
// Now create a new block that ends with the continue statement.
Block = createBlock(false);
CFGBlock* SwitchSuccessor = NULL;
if (Block) {
- if (!FinishBlock(Block))
+ if (badCFG)
return 0;
SwitchSuccessor = Block;
} else SwitchSuccessor = Succ;
// control-flow from the switch goes to case/default statements.
assert(Terminator->getBody() && "switch must contain a non-NULL body");
Block = NULL;
- CFGBlock *BodyBlock = addStmt(Terminator->getBody());
+ addStmt(Terminator->getBody());
if (Block) {
- if (!FinishBlock(BodyBlock))
+ if (badCFG)
return 0;
}
// were processing (the "case XXX:" is the label).
CaseBlock->setLabel(CS);
- if (!FinishBlock(CaseBlock))
+ if (badCFG)
return 0;
// Add this block to the list of successors for the block with the switch
// we were processing (the "default:" is the label).
DefaultCaseBlock->setLabel(Terminator);
- if (!FinishBlock(DefaultCaseBlock))
+ if (badCFG)
return 0;
// Unlike case statements, we don't add the default block to the successors
CFGBlock* TrySuccessor = NULL;
if (Block) {
- if (!FinishBlock(Block))
+ if (badCFG)
return 0;
TrySuccessor = Block;
} else TrySuccessor = Succ;
CatchBlock->setLabel(CS);
- if (!FinishBlock(CatchBlock))
+ if (badCFG)
return 0;
// We set Block to NULL to allow lazy creation of a new block (if necessary)
// IndirectGoto is a control-flow statement. Thus we stop processing the
// current block and create a new one.
- if (Block && !FinishBlock(Block))
+ if (badCFG)
return 0;
Block = createBlock(false);