diff options
author | Ted Kremenek <kremenek@apple.com> | 2007-11-26 18:20:26 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2007-11-26 18:20:26 +0000 |
commit | ecc04c925412f935a936226452407bf8a51ed027 (patch) | |
tree | e227223e281e47471362050c9f484c2f448fc16d | |
parent | f5f20bdf918cedb47fdd33f5b634f4908cdd3f15 (diff) |
Fixed bug in CFG construction where we did not properly handle the GCC
extension "?:" for the ternary operator, e.g.: x ?: y; This expression is
represented in the clang ASTs as a ConditionalOperator whose LHS expression is
NULL. Now we handle this special case, causing the block containing the
condition to be a predecessor to the block that "merges" the values of the
ternary operator.
Thanks to Nuno Lopes for identifying and diagnosing this bug!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44327 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | AST/CFG.cpp | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/AST/CFG.cpp b/AST/CFG.cpp index f99de1cc79..0c8589b058 100644 --- a/AST/CFG.cpp +++ b/AST/CFG.cpp @@ -220,24 +220,53 @@ CFGBlock* CFGBuilder::WalkAST(Stmt* S, bool AlwaysAddStmt = false) { switch (S->getStmtClass()) { case Stmt::ConditionalOperatorClass: { ConditionalOperator* C = cast<ConditionalOperator>(S); - + + // Create the confluence block that will "merge" the results + // of the ternary expression. CFGBlock* ConfluenceBlock = (Block) ? Block : createBlock(); ConfluenceBlock->appendStmt(C); FinishBlock(ConfluenceBlock); + + // 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 = Visit(C->getLHS()); - FinishBlock(LHSBlock); + CFGBlock* LHSBlock = NULL; + if (C->getLHS()) { + LHSBlock = Visit(C->getLHS()); + FinishBlock(LHSBlock); + Block = NULL; + } + // Create the block for the RHS expression. Succ = ConfluenceBlock; - Block = NULL; CFGBlock* RHSBlock = Visit(C->getRHS()); FinishBlock(RHSBlock); + // Create the block that will contain the condition. Block = createBlock(false); - Block->addSuccessor(LHSBlock); + + 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()); } |