No functionality change. Moved visitor methods for CFGBuilder out-of-line

from the class declaration.  This enables a nice view of what visitor methods
have been implemented.

llvm-svn: 41337
This commit is contained in:
Ted Kremenek 2007-08-23 21:42:29 +00:00
parent 1aaab49a3e
commit 9aae513318
1 changed files with 592 additions and 567 deletions

View File

@ -75,12 +75,39 @@ public:
~CFGBuilder() { delete cfg; }
/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can
/// represent an arbitrary statement. Examples include a single expression
/// or a function body (compound statement). The ownership of the returned
/// CFG is transferred to the caller. If CFG construction fails, this method
/// returns NULL.
CFG* buildCFG(Stmt* Statement) {
// buildCFG - Used by external clients to construct the CFG.
CFG* buildCFG(Stmt* Statement);
// Visitors to walk an AST and construct the CFG. Called by
// buildCFG. Do not call directly!
CFGBlock* VisitStmt(Stmt* Statement);
CFGBlock* VisitNullStmt(NullStmt* Statement);
CFGBlock* VisitCompoundStmt(CompoundStmt* C);
CFGBlock* VisitIfStmt(IfStmt* I);
CFGBlock* VisitReturnStmt(ReturnStmt* R);
CFGBlock* VisitLabelStmt(LabelStmt* L);
CFGBlock* VisitGotoStmt(GotoStmt* G);
CFGBlock* VisitForStmt(ForStmt* F);
CFGBlock* VisitWhileStmt(WhileStmt* W);
CFGBlock* VisitDoStmt(DoStmt* D);
CFGBlock* VisitContinueStmt(ContinueStmt* C);
CFGBlock* VisitBreakStmt(BreakStmt* B);
CFGBlock* VisitSwitchStmt(SwitchStmt* S);
CFGBlock* VisitSwitchCase(SwitchCase* S);
private:
CFGBlock* createBlock(bool add_successor = true);
void FinishBlock(CFGBlock* B);
};
/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can
/// represent an arbitrary statement. Examples include a single expression
/// or a function body (compound statement). The ownership of the returned
/// CFG is transferred to the caller. If CFG construction fails, this method
/// returns NULL.
CFG* CFGBuilder::buildCFG(Stmt* Statement) {
if (!Statement) return NULL;
// Create an empty block that will serve as the exit block for the CFG.
@ -118,24 +145,24 @@ public:
return t;
}
else return NULL;
}
}
// createBlock - Used to lazily create blocks that are connected
// to the current (global) succcessor.
CFGBlock* createBlock( bool add_successor = true ) {
/// createBlock - Used to lazily create blocks that are connected
/// to the current (global) succcessor.
CFGBlock* CFGBuilder::createBlock(bool add_successor) {
CFGBlock* B = cfg->createBlock(NumBlocks++);
if (add_successor && Succ) B->addSuccessor(Succ);
return B;
}
}
// FinishBlock - When the last statement has been added to the block,
// usually we must reverse the statements because they have been inserted
// in reverse order. When processing labels, however, there are cases
// in the recursion where we may have already reversed the statements
// in a block. This method safely tidies up a block: if the block
// has a label at the front, it has already been reversed. Otherwise,
// we reverse it.
void FinishBlock(CFGBlock* B) {
/// FinishBlock - When the last statement has been added to the block,
/// usually we must reverse the statements because they have been inserted
/// in reverse order. When processing labels, however, there are cases
/// in the recursion where we may have already reversed the statements
/// in a block. This method safely tidies up a block: if the block
/// has a label at the front, it has already been reversed. Otherwise,
/// we reverse it.
void CFGBuilder::FinishBlock(CFGBlock* B) {
assert (B);
CFGBlock::iterator I = B->begin();
if (I != B->end()) {
@ -146,10 +173,10 @@ public:
B->reverseStmts();
}
}
}
/// Here we handle statements with no branching control flow.
CFGBlock* VisitStmt(Stmt* Statement) {
/// VisitStmt - Handle statements with no branching control flow.
CFGBlock* CFGBuilder::VisitStmt(Stmt* Statement) {
// We cannot assume that we are in the middle of a basic block, since
// the CFG might only be constructed for this single statement. If
// we have no current basic block, just create one lazily.
@ -161,13 +188,13 @@ public:
Block->appendStmt(Statement);
return Block;
}
}
CFGBlock* VisitNullStmt(NullStmt* Statement) {
CFGBlock* CFGBuilder::VisitNullStmt(NullStmt* Statement) {
return Block;
}
}
CFGBlock* VisitCompoundStmt(CompoundStmt* C) {
CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
// The value returned from this function is the last created CFGBlock
// that represents the "entry" point for the translated AST node.
CFGBlock* LastBlock;
@ -179,10 +206,9 @@ public:
return NULL;
return LastBlock;
}
CFGBlock* VisitIfStmt(IfStmt* I) {
}
CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
// We may see an if statement in the middle of a basic block, or
// it may be the first statement we are processing. In either case,
// we create a new basic block. First, we create the blocks for
@ -242,9 +268,9 @@ public:
Block->addSuccessor(ElseBlock);
return Block;
}
}
CFGBlock* VisitReturnStmt(ReturnStmt* R) {
CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) {
// If we were in the middle of a block we stop processing that block
// and reverse its statements.
//
@ -268,9 +294,9 @@ public:
Block->setTerminator(R);
return Block;
}
}
CFGBlock* VisitLabelStmt(LabelStmt* L) {
CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) {
// Get the block of the labeled statement. Add it to our map.
CFGBlock* LabelBlock = Visit(L->getSubStmt());
assert (LabelBlock);
@ -291,9 +317,9 @@ public:
Succ = LabelBlock;
return LabelBlock;
}
}
CFGBlock* VisitGotoStmt(GotoStmt* G) {
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);
@ -311,9 +337,9 @@ public:
Block->addSuccessor(I->second);
return Block;
}
}
CFGBlock* VisitForStmt(ForStmt* F) {
CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
// "for" is a control-flow statement. Thus we stop processing the
// current block.
@ -383,9 +409,9 @@ public:
Block = NULL;
return ConditionBlock;
}
}
}
CFGBlock* VisitWhileStmt(WhileStmt* W) {
CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
// "while" is a control-flow statement. Thus we stop processing the
// current block.
@ -444,9 +470,9 @@ public:
// Return the condition block, which is the dominating block for the loop.
return ConditionBlock;
}
}
CFGBlock* VisitDoStmt(DoStmt* D) {
CFGBlock* CFGBuilder::VisitDoStmt(DoStmt* D) {
// "do...while" is a control-flow statement. Thus we stop processing the
// current block.
@ -505,9 +531,9 @@ public:
// Return the loop body, which is the dominating block for the loop.
return BodyBlock;
}
}
CFGBlock* VisitContinueStmt(ContinueStmt* C) {
CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
// "continue" is a control-flow statement. Thus we stop processing the
// current block.
if (Block) FinishBlock(Block);
@ -521,9 +547,9 @@ public:
if (ContinueTargetBlock) Block->addSuccessor(ContinueTargetBlock);
return Block;
}
}
CFGBlock* VisitBreakStmt(BreakStmt* B) {
CFGBlock* CFGBuilder::VisitBreakStmt(BreakStmt* B) {
// "break" is a control-flow statement. Thus we stop processing the
// current block.
if (Block) FinishBlock(Block);
@ -537,9 +563,9 @@ public:
if (BreakTargetBlock) Block->addSuccessor(BreakTargetBlock);
return Block;
}
}
CFGBlock* VisitSwitchStmt(SwitchStmt* S) {
CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* S) {
// "switch" is a control-flow statement. Thus we stop processing the
// current block.
CFGBlock* SwitchSuccessor = NULL;
@ -578,9 +604,9 @@ public:
Block = SwitchTerminatedBlock;
return SwitchTerminatedBlock;
}
}
CFGBlock* VisitSwitchCase(SwitchCase* S) {
CFGBlock* CFGBuilder::VisitSwitchCase(SwitchCase* S) {
// A SwitchCase is either a "default" or "case" statement. We handle
// both in the same way. They are essentially labels, so they are the
// first statement in a block.
@ -603,9 +629,9 @@ public:
Succ = CaseBlock;
return CaseBlock;
}
}
};
} // end anonymous namespace
/// createBlock - Constructs and adds a new CFGBlock to the CFG. The
@ -640,7 +666,6 @@ void CFG::dump() { print(std::cerr); }
/// print - A simple pretty printer of a CFG that outputs to an ostream.
void CFG::print(std::ostream& OS) {
// Print the Entry block.
if (begin() != end()) {
CFGBlock& Entry = getEntry();
@ -670,10 +695,10 @@ void CFG::print(std::ostream& OS) {
namespace {
class CFGBlockTerminatorPrint : public StmtVisitor<CFGBlockTerminatorPrint,
class CFGBlockTerminatorPrint : public StmtVisitor<CFGBlockTerminatorPrint,
void > {
std::ostream& OS;
public:
public:
CFGBlockTerminatorPrint(std::ostream& os) : OS(os) {}
void VisitIfStmt(IfStmt* I) {
@ -706,8 +731,8 @@ namespace {
if (Stmt* C = D->getCond()) C->printPretty(OS);
OS << "\n";
}
};
}
};
} // end anonymous namespace
/// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
void CFGBlock::dump() { print(std::cerr); }