forked from OSchip/llvm-project
Move WalkAST logic for 'ConditionalOperator' into 'VisitConditionalOperator'.
llvm-svn: 76202
This commit is contained in:
parent
c3ccd180e7
commit
51d40b07a0
|
@ -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,67 +273,16 @@ 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;
|
||||||
|
|
Loading…
Reference in New Issue