Move WalkAST logic for 'ConditionalOperator' into 'VisitConditionalOperator'.

llvm-svn: 76202
This commit is contained in:
Ted Kremenek 2009-07-17 18:15:54 +00:00
parent c3ccd180e7
commit 51d40b07a0
1 changed files with 61 additions and 58 deletions

View File

@ -102,6 +102,7 @@ public:
CFGBlock* VisitBreakStmt(BreakStmt* B); CFGBlock* VisitBreakStmt(BreakStmt* B);
CFGBlock* VisitCaseStmt(CaseStmt* Terminator); CFGBlock* VisitCaseStmt(CaseStmt* Terminator);
CFGBlock* VisitCompoundStmt(CompoundStmt* C); CFGBlock* VisitCompoundStmt(CompoundStmt* C);
CFGBlock* VisitConditionalOperator(ConditionalOperator *C);
CFGBlock* VisitContinueStmt(ContinueStmt* C); CFGBlock* VisitContinueStmt(ContinueStmt* C);
CFGBlock* VisitDefaultStmt(DefaultStmt* D); CFGBlock* VisitDefaultStmt(DefaultStmt* D);
CFGBlock* VisitDoStmt(DoStmt* D); CFGBlock* VisitDoStmt(DoStmt* D);
@ -145,7 +146,7 @@ public:
private: private:
CFGBlock* createBlock(bool add_successor = true); CFGBlock* createBlock(bool add_successor = true);
CFGBlock* addStmt(Stmt* Terminator); CFGBlock* addStmt(Stmt* Terminator);
CFGBlock* WalkAST(Stmt* Terminator, bool AlwaysAddStmt); CFGBlock* WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false);
CFGBlock* WalkAST_VisitChildren(Stmt* Terminator); CFGBlock* WalkAST_VisitChildren(Stmt* Terminator);
CFGBlock* WalkAST_VisitDeclSubExpr(Decl* D); CFGBlock* WalkAST_VisitDeclSubExpr(Decl* D);
CFGBlock* WalkAST_VisitStmtExpr(StmtExpr* Terminator); CFGBlock* WalkAST_VisitStmtExpr(StmtExpr* Terminator);
@ -272,68 +273,17 @@ bool CFGBuilder::FinishBlock(CFGBlock* B) {
/// called if no additional blocks are created. /// called if no additional blocks are created.
CFGBlock* CFGBuilder::addStmt(Stmt* Terminator) { CFGBlock* CFGBuilder::addStmt(Stmt* Terminator) {
if (!Block) Block = createBlock(); if (!Block) Block = createBlock();
return WalkAST(Terminator,true); return WalkAST(Terminator, true);
} }
/// WalkAST - Used by addStmt to walk the subtree of a statement and add extra /// WalkAST - Walk the subtree of a statement and add extra
/// blocks for ternary operators, &&, and ||. We also process "," and /// blocks for ternary operators, &&, and ||. We also process "," and
/// DeclStmts (which may contain nested control-flow). /// DeclStmts (which may contain nested control-flow).
CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) { CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt) {
switch (Terminator->getStmtClass()) { switch (Terminator->getStmtClass()) {
case Stmt::ConditionalOperatorClass: { case Stmt::ConditionalOperatorClass:
ConditionalOperator* C = cast<ConditionalOperator>(Terminator); return VisitConditionalOperator(cast<ConditionalOperator>(Terminator));
// Create the confluence block that will "merge" the results of the ternary
// expression.
CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock();
ConfluenceBlock->appendStmt(C);
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 be the
// value that is returned instead.
// e.g: x ?: y is shorthand for: x ? x : y;
Succ = ConfluenceBlock;
Block = NULL;
CFGBlock* LHSBlock = NULL;
if (C->getLHS()) {
LHSBlock = Visit(C->getLHS());
if (!FinishBlock(LHSBlock))
return 0;
Block = NULL;
}
// Create the block for the RHS expression.
Succ = ConfluenceBlock;
CFGBlock* RHSBlock = Visit(C->getRHS());
if (!FinishBlock(RHSBlock))
return 0;
// Create the block that will contain the condition.
Block = createBlock(false);
if (LHSBlock)
Block->addSuccessor(LHSBlock);
else {
// If we have no LHS expression, add the ConfluenceBlock as a direct
// successor for the block containing the condition. Moreover, we need to
// reverse the order of the predecessors in the ConfluenceBlock because
// the RHSBlock will have been added to the succcessors already, and we
// want the first predecessor to the the block containing the expression
// for the case when the ternary expression evaluates to true.
Block->addSuccessor(ConfluenceBlock);
assert (ConfluenceBlock->pred_size() == 2);
std::reverse(ConfluenceBlock->pred_begin(),
ConfluenceBlock->pred_end());
}
Block->addSuccessor(RHSBlock);
Block->setTerminator(C);
return addStmt(C->getCond());
}
case Stmt::ChooseExprClass: { case Stmt::ChooseExprClass: {
ChooseExpr* C = cast<ChooseExpr>(Terminator); ChooseExpr* C = cast<ChooseExpr>(Terminator);
@ -568,6 +518,59 @@ CFGBlock* CFGBuilder::VisitNullStmt(NullStmt* Statement) {
return Block; return Block;
} }
CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C) {
// Create the confluence block that will "merge" the results of the ternary
// expression.
CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
ConfluenceBlock->appendStmt(C);
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 be the
// value that is returned instead.
// e.g: x ?: y is shorthand for: x ? x : y;
Succ = ConfluenceBlock;
Block = NULL;
CFGBlock* LHSBlock = NULL;
if (C->getLHS()) {
LHSBlock = Visit(C->getLHS());
if (!FinishBlock(LHSBlock))
return 0;
Block = NULL;
}
// Create the block for the RHS expression.
Succ = ConfluenceBlock;
CFGBlock* RHSBlock = Visit(C->getRHS());
if (!FinishBlock(RHSBlock))
return 0;
// Create the block that will contain the condition.
Block = createBlock(false);
if (LHSBlock)
Block->addSuccessor(LHSBlock);
else {
// If we have no LHS expression, add the ConfluenceBlock as a direct
// successor for the block containing the condition. Moreover, we need to
// reverse the order of the predecessors in the ConfluenceBlock because
// the RHSBlock will have been added to the succcessors already, and we
// want the first predecessor to the the block containing the expression
// for the case when the ternary expression evaluates to true.
Block->addSuccessor(ConfluenceBlock);
assert (ConfluenceBlock->pred_size() == 2);
std::reverse(ConfluenceBlock->pred_begin(),
ConfluenceBlock->pred_end());
}
Block->addSuccessor(RHSBlock);
Block->setTerminator(C);
return addStmt(C->getCond());
}
CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) { CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
CFGBlock* LastBlock = Block; CFGBlock* LastBlock = Block;