[PATCH] Make dead return statement detection more robust against changes in the CFG.
Manuel Klimek
klimek at google.com
Wed May 21 07:03:52 PDT 2014
Ping.
On Wed, May 7, 2014 at 12:10 PM, Manuel Klimek <klimek at google.com> wrote:
> Wordsmithing.
>
> http://reviews.llvm.org/D3638
>
> Files:
> lib/Analysis/ReachableCode.cpp
>
> Index: lib/Analysis/ReachableCode.cpp
> ===================================================================
> --- lib/Analysis/ReachableCode.cpp
> +++ lib/Analysis/ReachableCode.cpp
> @@ -59,32 +59,57 @@
> }
>
> static bool isDeadReturn(const CFGBlock *B, const Stmt *S) {
> - // Look to see if the block ends with a 'return', and see if 'S'
> - // is a substatement. The 'return' may not be the last element in
> - // the block because of destructors.
> - for (CFGBlock::const_reverse_iterator I = B->rbegin(), E = B->rend();
> - I != E; ++I) {
> - if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
> - if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
> - if (RS == S)
> - return true;
> - if (const Expr *RE = RS->getRetValue()) {
> - RE = RE->IgnoreParenCasts();
> - if (RE == S)
> + // Look to see if the current control flow ends with a 'return', and
> see if
> + // 'S' is a substatement. The 'return' may not be the last element in
> the
> + // block, or may be in a subsequent block because of destructors.
> + const CFGBlock *Current = B;
> + while (true) {
> + for (CFGBlock::const_reverse_iterator I = Current->rbegin(),
> + E = Current->rend();
> + I != E; ++I) {
> + if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
> + if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
> + if (RS == S)
> return true;
> - ParentMap PM(const_cast<Expr*>(RE));
> - // If 'S' is in the ParentMap, it is a subexpression of
> - // the return statement. Note also that we are restricting
> - // to looking at return statements in the same CFGBlock,
> - // so this will intentionally not catch cases where the
> - // return statement contains nested control-flow.
> - return PM.getParent(S);
> + if (const Expr *RE = RS->getRetValue()) {
> + RE = RE->IgnoreParenCasts();
> + if (RE == S)
> + return true;
> + ParentMap PM(const_cast<Expr *>(RE));
> + // If 'S' is in the ParentMap, it is a subexpression of
> + // the return statement.
> + return PM.getParent(S);
> + }
> }
> + break;
> + }
> + }
> + // Note also that we are restricting the search for the return
> statement
> + // to stop at control-flow; only part of a return statement may be
> dead,
> + // without the whole return statement being dead.
> + if (Current->getTerminator().isTemporaryDtorsBranch()) {
> + // Temporary destructors have a predictable control flow, thus we
> want to
> + // look into the next block for the return statement.
> + // We look into the false branch, as we know the true branch only
> contains
> + // the call to the destructor.
> + assert(Current->succ_size() == 2);
> + Current = *(Current->succ_begin() + 1);
> + } else if (!Current->getTerminator() && Current->succ_size() == 1) {
> + // If there is only one successor, we're not dealing with outgoing
> control
> + // flow. Thus, look into the next block.
> + Current = *Current->succ_begin();
> + if (Current->pred_size() > 1) {
> + // If there is more than one predecessor, we're dealing with
> incoming
> + // control flow - if the return statement is in that block, it
> might
> + // well be reachable via a different control flow, thus it's not
> dead.
> + return false;
> }
> - break;
> + } else {
> + // We hit control flow or a dead end. Stop searching.
> + return false;
> }
> }
> - return false;
> + llvm_unreachable("Broke out of infinite loop.");
> }
>
> static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager
> &SM) {
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140521/bf663f3d/attachment.html>
More information about the cfe-commits
mailing list