xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Analysis/ReachableCode.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===-- ReachableCode.cpp - Code Reachability Analysis --------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements a flow-sensitive, path-insensitive analysis of
107330f729Sjoerg // determining reachable blocks within a CFG.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg 
147330f729Sjoerg #include "clang/Analysis/Analyses/ReachableCode.h"
157330f729Sjoerg #include "clang/AST/Expr.h"
167330f729Sjoerg #include "clang/AST/ExprCXX.h"
177330f729Sjoerg #include "clang/AST/ExprObjC.h"
187330f729Sjoerg #include "clang/AST/ParentMap.h"
197330f729Sjoerg #include "clang/AST/StmtCXX.h"
207330f729Sjoerg #include "clang/Analysis/AnalysisDeclContext.h"
217330f729Sjoerg #include "clang/Analysis/CFG.h"
22*e038c9c4Sjoerg #include "clang/Basic/Builtins.h"
237330f729Sjoerg #include "clang/Basic/SourceManager.h"
247330f729Sjoerg #include "clang/Lex/Preprocessor.h"
257330f729Sjoerg #include "llvm/ADT/BitVector.h"
267330f729Sjoerg #include "llvm/ADT/SmallVector.h"
277330f729Sjoerg 
287330f729Sjoerg using namespace clang;
297330f729Sjoerg 
307330f729Sjoerg //===----------------------------------------------------------------------===//
317330f729Sjoerg // Core Reachability Analysis routines.
327330f729Sjoerg //===----------------------------------------------------------------------===//
337330f729Sjoerg 
isEnumConstant(const Expr * Ex)347330f729Sjoerg static bool isEnumConstant(const Expr *Ex) {
357330f729Sjoerg   const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex);
367330f729Sjoerg   if (!DR)
377330f729Sjoerg     return false;
387330f729Sjoerg   return isa<EnumConstantDecl>(DR->getDecl());
397330f729Sjoerg }
407330f729Sjoerg 
isTrivialExpression(const Expr * Ex)417330f729Sjoerg static bool isTrivialExpression(const Expr *Ex) {
427330f729Sjoerg   Ex = Ex->IgnoreParenCasts();
437330f729Sjoerg   return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||
447330f729Sjoerg          isa<CXXBoolLiteralExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
457330f729Sjoerg          isa<CharacterLiteral>(Ex) ||
467330f729Sjoerg          isEnumConstant(Ex);
477330f729Sjoerg }
487330f729Sjoerg 
isTrivialDoWhile(const CFGBlock * B,const Stmt * S)497330f729Sjoerg static bool isTrivialDoWhile(const CFGBlock *B, const Stmt *S) {
507330f729Sjoerg   // Check if the block ends with a do...while() and see if 'S' is the
517330f729Sjoerg   // condition.
527330f729Sjoerg   if (const Stmt *Term = B->getTerminatorStmt()) {
537330f729Sjoerg     if (const DoStmt *DS = dyn_cast<DoStmt>(Term)) {
547330f729Sjoerg       const Expr *Cond = DS->getCond()->IgnoreParenCasts();
557330f729Sjoerg       return Cond == S && isTrivialExpression(Cond);
567330f729Sjoerg     }
577330f729Sjoerg   }
587330f729Sjoerg   return false;
597330f729Sjoerg }
607330f729Sjoerg 
isBuiltinUnreachable(const Stmt * S)617330f729Sjoerg static bool isBuiltinUnreachable(const Stmt *S) {
627330f729Sjoerg   if (const auto *DRE = dyn_cast<DeclRefExpr>(S))
637330f729Sjoerg     if (const auto *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()))
647330f729Sjoerg       return FDecl->getIdentifier() &&
657330f729Sjoerg              FDecl->getBuiltinID() == Builtin::BI__builtin_unreachable;
667330f729Sjoerg   return false;
677330f729Sjoerg }
687330f729Sjoerg 
isBuiltinAssumeFalse(const CFGBlock * B,const Stmt * S,ASTContext & C)697330f729Sjoerg static bool isBuiltinAssumeFalse(const CFGBlock *B, const Stmt *S,
707330f729Sjoerg                                  ASTContext &C) {
717330f729Sjoerg   if (B->empty())  {
727330f729Sjoerg     // Happens if S is B's terminator and B contains nothing else
737330f729Sjoerg     // (e.g. a CFGBlock containing only a goto).
747330f729Sjoerg     return false;
757330f729Sjoerg   }
767330f729Sjoerg   if (Optional<CFGStmt> CS = B->back().getAs<CFGStmt>()) {
777330f729Sjoerg     if (const auto *CE = dyn_cast<CallExpr>(CS->getStmt())) {
787330f729Sjoerg       return CE->getCallee()->IgnoreCasts() == S && CE->isBuiltinAssumeFalse(C);
797330f729Sjoerg     }
807330f729Sjoerg   }
817330f729Sjoerg   return false;
827330f729Sjoerg }
837330f729Sjoerg 
isDeadReturn(const CFGBlock * B,const Stmt * S)847330f729Sjoerg static bool isDeadReturn(const CFGBlock *B, const Stmt *S) {
857330f729Sjoerg   // Look to see if the current control flow ends with a 'return', and see if
867330f729Sjoerg   // 'S' is a substatement. The 'return' may not be the last element in the
877330f729Sjoerg   // block, or may be in a subsequent block because of destructors.
887330f729Sjoerg   const CFGBlock *Current = B;
897330f729Sjoerg   while (true) {
907330f729Sjoerg     for (CFGBlock::const_reverse_iterator I = Current->rbegin(),
917330f729Sjoerg                                           E = Current->rend();
927330f729Sjoerg          I != E; ++I) {
937330f729Sjoerg       if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
947330f729Sjoerg         if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
957330f729Sjoerg           if (RS == S)
967330f729Sjoerg             return true;
977330f729Sjoerg           if (const Expr *RE = RS->getRetValue()) {
987330f729Sjoerg             RE = RE->IgnoreParenCasts();
997330f729Sjoerg             if (RE == S)
1007330f729Sjoerg               return true;
1017330f729Sjoerg             ParentMap PM(const_cast<Expr *>(RE));
1027330f729Sjoerg             // If 'S' is in the ParentMap, it is a subexpression of
1037330f729Sjoerg             // the return statement.
1047330f729Sjoerg             return PM.getParent(S);
1057330f729Sjoerg           }
1067330f729Sjoerg         }
1077330f729Sjoerg         break;
1087330f729Sjoerg       }
1097330f729Sjoerg     }
1107330f729Sjoerg     // Note also that we are restricting the search for the return statement
1117330f729Sjoerg     // to stop at control-flow; only part of a return statement may be dead,
1127330f729Sjoerg     // without the whole return statement being dead.
1137330f729Sjoerg     if (Current->getTerminator().isTemporaryDtorsBranch()) {
1147330f729Sjoerg       // Temporary destructors have a predictable control flow, thus we want to
1157330f729Sjoerg       // look into the next block for the return statement.
1167330f729Sjoerg       // We look into the false branch, as we know the true branch only contains
1177330f729Sjoerg       // the call to the destructor.
1187330f729Sjoerg       assert(Current->succ_size() == 2);
1197330f729Sjoerg       Current = *(Current->succ_begin() + 1);
1207330f729Sjoerg     } else if (!Current->getTerminatorStmt() && Current->succ_size() == 1) {
1217330f729Sjoerg       // If there is only one successor, we're not dealing with outgoing control
1227330f729Sjoerg       // flow. Thus, look into the next block.
1237330f729Sjoerg       Current = *Current->succ_begin();
1247330f729Sjoerg       if (Current->pred_size() > 1) {
1257330f729Sjoerg         // If there is more than one predecessor, we're dealing with incoming
1267330f729Sjoerg         // control flow - if the return statement is in that block, it might
1277330f729Sjoerg         // well be reachable via a different control flow, thus it's not dead.
1287330f729Sjoerg         return false;
1297330f729Sjoerg       }
1307330f729Sjoerg     } else {
1317330f729Sjoerg       // We hit control flow or a dead end. Stop searching.
1327330f729Sjoerg       return false;
1337330f729Sjoerg     }
1347330f729Sjoerg   }
1357330f729Sjoerg   llvm_unreachable("Broke out of infinite loop.");
1367330f729Sjoerg }
1377330f729Sjoerg 
getTopMostMacro(SourceLocation Loc,SourceManager & SM)1387330f729Sjoerg static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager &SM) {
1397330f729Sjoerg   assert(Loc.isMacroID());
1407330f729Sjoerg   SourceLocation Last;
141*e038c9c4Sjoerg   do {
1427330f729Sjoerg     Last = Loc;
1437330f729Sjoerg     Loc = SM.getImmediateMacroCallerLoc(Loc);
144*e038c9c4Sjoerg   } while (Loc.isMacroID());
1457330f729Sjoerg   return Last;
1467330f729Sjoerg }
1477330f729Sjoerg 
1487330f729Sjoerg /// Returns true if the statement is expanded from a configuration macro.
isExpandedFromConfigurationMacro(const Stmt * S,Preprocessor & PP,bool IgnoreYES_NO=false)1497330f729Sjoerg static bool isExpandedFromConfigurationMacro(const Stmt *S,
1507330f729Sjoerg                                              Preprocessor &PP,
1517330f729Sjoerg                                              bool IgnoreYES_NO = false) {
1527330f729Sjoerg   // FIXME: This is not very precise.  Here we just check to see if the
1537330f729Sjoerg   // value comes from a macro, but we can do much better.  This is likely
1547330f729Sjoerg   // to be over conservative.  This logic is factored into a separate function
1557330f729Sjoerg   // so that we can refine it later.
1567330f729Sjoerg   SourceLocation L = S->getBeginLoc();
1577330f729Sjoerg   if (L.isMacroID()) {
1587330f729Sjoerg     SourceManager &SM = PP.getSourceManager();
1597330f729Sjoerg     if (IgnoreYES_NO) {
1607330f729Sjoerg       // The Objective-C constant 'YES' and 'NO'
1617330f729Sjoerg       // are defined as macros.  Do not treat them
1627330f729Sjoerg       // as configuration values.
1637330f729Sjoerg       SourceLocation TopL = getTopMostMacro(L, SM);
1647330f729Sjoerg       StringRef MacroName = PP.getImmediateMacroName(TopL);
1657330f729Sjoerg       if (MacroName == "YES" || MacroName == "NO")
1667330f729Sjoerg         return false;
1677330f729Sjoerg     } else if (!PP.getLangOpts().CPlusPlus) {
1687330f729Sjoerg       // Do not treat C 'false' and 'true' macros as configuration values.
1697330f729Sjoerg       SourceLocation TopL = getTopMostMacro(L, SM);
1707330f729Sjoerg       StringRef MacroName = PP.getImmediateMacroName(TopL);
1717330f729Sjoerg       if (MacroName == "false" || MacroName == "true")
1727330f729Sjoerg         return false;
1737330f729Sjoerg     }
1747330f729Sjoerg     return true;
1757330f729Sjoerg   }
1767330f729Sjoerg   return false;
1777330f729Sjoerg }
1787330f729Sjoerg 
1797330f729Sjoerg static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP);
1807330f729Sjoerg 
1817330f729Sjoerg /// Returns true if the statement represents a configuration value.
1827330f729Sjoerg ///
1837330f729Sjoerg /// A configuration value is something usually determined at compile-time
1847330f729Sjoerg /// to conditionally always execute some branch.  Such guards are for
1857330f729Sjoerg /// "sometimes unreachable" code.  Such code is usually not interesting
1867330f729Sjoerg /// to report as unreachable, and may mask truly unreachable code within
1877330f729Sjoerg /// those blocks.
isConfigurationValue(const Stmt * S,Preprocessor & PP,SourceRange * SilenceableCondVal=nullptr,bool IncludeIntegers=true,bool WrappedInParens=false)1887330f729Sjoerg static bool isConfigurationValue(const Stmt *S,
1897330f729Sjoerg                                  Preprocessor &PP,
1907330f729Sjoerg                                  SourceRange *SilenceableCondVal = nullptr,
1917330f729Sjoerg                                  bool IncludeIntegers = true,
1927330f729Sjoerg                                  bool WrappedInParens = false) {
1937330f729Sjoerg   if (!S)
1947330f729Sjoerg     return false;
1957330f729Sjoerg 
1967330f729Sjoerg   if (const auto *Ex = dyn_cast<Expr>(S))
1977330f729Sjoerg     S = Ex->IgnoreImplicit();
1987330f729Sjoerg 
1997330f729Sjoerg   if (const auto *Ex = dyn_cast<Expr>(S))
2007330f729Sjoerg     S = Ex->IgnoreCasts();
2017330f729Sjoerg 
2027330f729Sjoerg   // Special case looking for the sigil '()' around an integer literal.
2037330f729Sjoerg   if (const ParenExpr *PE = dyn_cast<ParenExpr>(S))
2047330f729Sjoerg     if (!PE->getBeginLoc().isMacroID())
2057330f729Sjoerg       return isConfigurationValue(PE->getSubExpr(), PP, SilenceableCondVal,
2067330f729Sjoerg                                   IncludeIntegers, true);
2077330f729Sjoerg 
2087330f729Sjoerg   if (const Expr *Ex = dyn_cast<Expr>(S))
2097330f729Sjoerg     S = Ex->IgnoreCasts();
2107330f729Sjoerg 
2117330f729Sjoerg   bool IgnoreYES_NO = false;
2127330f729Sjoerg 
2137330f729Sjoerg   switch (S->getStmtClass()) {
2147330f729Sjoerg     case Stmt::CallExprClass: {
2157330f729Sjoerg       const FunctionDecl *Callee =
2167330f729Sjoerg         dyn_cast_or_null<FunctionDecl>(cast<CallExpr>(S)->getCalleeDecl());
2177330f729Sjoerg       return Callee ? Callee->isConstexpr() : false;
2187330f729Sjoerg     }
2197330f729Sjoerg     case Stmt::DeclRefExprClass:
2207330f729Sjoerg       return isConfigurationValue(cast<DeclRefExpr>(S)->getDecl(), PP);
2217330f729Sjoerg     case Stmt::ObjCBoolLiteralExprClass:
2227330f729Sjoerg       IgnoreYES_NO = true;
2237330f729Sjoerg       LLVM_FALLTHROUGH;
2247330f729Sjoerg     case Stmt::CXXBoolLiteralExprClass:
2257330f729Sjoerg     case Stmt::IntegerLiteralClass: {
2267330f729Sjoerg       const Expr *E = cast<Expr>(S);
2277330f729Sjoerg       if (IncludeIntegers) {
2287330f729Sjoerg         if (SilenceableCondVal && !SilenceableCondVal->getBegin().isValid())
2297330f729Sjoerg           *SilenceableCondVal = E->getSourceRange();
2307330f729Sjoerg         return WrappedInParens || isExpandedFromConfigurationMacro(E, PP, IgnoreYES_NO);
2317330f729Sjoerg       }
2327330f729Sjoerg       return false;
2337330f729Sjoerg     }
2347330f729Sjoerg     case Stmt::MemberExprClass:
2357330f729Sjoerg       return isConfigurationValue(cast<MemberExpr>(S)->getMemberDecl(), PP);
2367330f729Sjoerg     case Stmt::UnaryExprOrTypeTraitExprClass:
2377330f729Sjoerg       return true;
2387330f729Sjoerg     case Stmt::BinaryOperatorClass: {
2397330f729Sjoerg       const BinaryOperator *B = cast<BinaryOperator>(S);
2407330f729Sjoerg       // Only include raw integers (not enums) as configuration
2417330f729Sjoerg       // values if they are used in a logical or comparison operator
2427330f729Sjoerg       // (not arithmetic).
2437330f729Sjoerg       IncludeIntegers &= (B->isLogicalOp() || B->isComparisonOp());
2447330f729Sjoerg       return isConfigurationValue(B->getLHS(), PP, SilenceableCondVal,
2457330f729Sjoerg                                   IncludeIntegers) ||
2467330f729Sjoerg              isConfigurationValue(B->getRHS(), PP, SilenceableCondVal,
2477330f729Sjoerg                                   IncludeIntegers);
2487330f729Sjoerg     }
2497330f729Sjoerg     case Stmt::UnaryOperatorClass: {
2507330f729Sjoerg       const UnaryOperator *UO = cast<UnaryOperator>(S);
2517330f729Sjoerg       if (UO->getOpcode() != UO_LNot && UO->getOpcode() != UO_Minus)
2527330f729Sjoerg         return false;
2537330f729Sjoerg       bool SilenceableCondValNotSet =
2547330f729Sjoerg           SilenceableCondVal && SilenceableCondVal->getBegin().isInvalid();
2557330f729Sjoerg       bool IsSubExprConfigValue =
2567330f729Sjoerg           isConfigurationValue(UO->getSubExpr(), PP, SilenceableCondVal,
2577330f729Sjoerg                                IncludeIntegers, WrappedInParens);
2587330f729Sjoerg       // Update the silenceable condition value source range only if the range
2597330f729Sjoerg       // was set directly by the child expression.
2607330f729Sjoerg       if (SilenceableCondValNotSet &&
2617330f729Sjoerg           SilenceableCondVal->getBegin().isValid() &&
2627330f729Sjoerg           *SilenceableCondVal ==
2637330f729Sjoerg               UO->getSubExpr()->IgnoreCasts()->getSourceRange())
2647330f729Sjoerg         *SilenceableCondVal = UO->getSourceRange();
2657330f729Sjoerg       return IsSubExprConfigValue;
2667330f729Sjoerg     }
2677330f729Sjoerg     default:
2687330f729Sjoerg       return false;
2697330f729Sjoerg   }
2707330f729Sjoerg }
2717330f729Sjoerg 
isConfigurationValue(const ValueDecl * D,Preprocessor & PP)2727330f729Sjoerg static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP) {
2737330f729Sjoerg   if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D))
2747330f729Sjoerg     return isConfigurationValue(ED->getInitExpr(), PP);
2757330f729Sjoerg   if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
2767330f729Sjoerg     // As a heuristic, treat globals as configuration values.  Note
2777330f729Sjoerg     // that we only will get here if Sema evaluated this
2787330f729Sjoerg     // condition to a constant expression, which means the global
2797330f729Sjoerg     // had to be declared in a way to be a truly constant value.
2807330f729Sjoerg     // We could generalize this to local variables, but it isn't
2817330f729Sjoerg     // clear if those truly represent configuration values that
2827330f729Sjoerg     // gate unreachable code.
2837330f729Sjoerg     if (!VD->hasLocalStorage())
2847330f729Sjoerg       return true;
2857330f729Sjoerg 
2867330f729Sjoerg     // As a heuristic, locals that have been marked 'const' explicitly
2877330f729Sjoerg     // can be treated as configuration values as well.
2887330f729Sjoerg     return VD->getType().isLocalConstQualified();
2897330f729Sjoerg   }
2907330f729Sjoerg   return false;
2917330f729Sjoerg }
2927330f729Sjoerg 
2937330f729Sjoerg /// Returns true if we should always explore all successors of a block.
shouldTreatSuccessorsAsReachable(const CFGBlock * B,Preprocessor & PP)2947330f729Sjoerg static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B,
2957330f729Sjoerg                                              Preprocessor &PP) {
2967330f729Sjoerg   if (const Stmt *Term = B->getTerminatorStmt()) {
2977330f729Sjoerg     if (isa<SwitchStmt>(Term))
2987330f729Sjoerg       return true;
2997330f729Sjoerg     // Specially handle '||' and '&&'.
3007330f729Sjoerg     if (isa<BinaryOperator>(Term)) {
3017330f729Sjoerg       return isConfigurationValue(Term, PP);
3027330f729Sjoerg     }
3037330f729Sjoerg   }
3047330f729Sjoerg 
3057330f729Sjoerg   const Stmt *Cond = B->getTerminatorCondition(/* stripParens */ false);
3067330f729Sjoerg   return isConfigurationValue(Cond, PP);
3077330f729Sjoerg }
3087330f729Sjoerg 
scanFromBlock(const CFGBlock * Start,llvm::BitVector & Reachable,Preprocessor * PP,bool IncludeSometimesUnreachableEdges)3097330f729Sjoerg static unsigned scanFromBlock(const CFGBlock *Start,
3107330f729Sjoerg                               llvm::BitVector &Reachable,
3117330f729Sjoerg                               Preprocessor *PP,
3127330f729Sjoerg                               bool IncludeSometimesUnreachableEdges) {
3137330f729Sjoerg   unsigned count = 0;
3147330f729Sjoerg 
3157330f729Sjoerg   // Prep work queue
3167330f729Sjoerg   SmallVector<const CFGBlock*, 32> WL;
3177330f729Sjoerg 
3187330f729Sjoerg   // The entry block may have already been marked reachable
3197330f729Sjoerg   // by the caller.
3207330f729Sjoerg   if (!Reachable[Start->getBlockID()]) {
3217330f729Sjoerg     ++count;
3227330f729Sjoerg     Reachable[Start->getBlockID()] = true;
3237330f729Sjoerg   }
3247330f729Sjoerg 
3257330f729Sjoerg   WL.push_back(Start);
3267330f729Sjoerg 
3277330f729Sjoerg   // Find the reachable blocks from 'Start'.
3287330f729Sjoerg   while (!WL.empty()) {
3297330f729Sjoerg     const CFGBlock *item = WL.pop_back_val();
3307330f729Sjoerg 
3317330f729Sjoerg     // There are cases where we want to treat all successors as reachable.
3327330f729Sjoerg     // The idea is that some "sometimes unreachable" code is not interesting,
3337330f729Sjoerg     // and that we should forge ahead and explore those branches anyway.
3347330f729Sjoerg     // This allows us to potentially uncover some "always unreachable" code
3357330f729Sjoerg     // within the "sometimes unreachable" code.
3367330f729Sjoerg     // Look at the successors and mark then reachable.
3377330f729Sjoerg     Optional<bool> TreatAllSuccessorsAsReachable;
3387330f729Sjoerg     if (!IncludeSometimesUnreachableEdges)
3397330f729Sjoerg       TreatAllSuccessorsAsReachable = false;
3407330f729Sjoerg 
3417330f729Sjoerg     for (CFGBlock::const_succ_iterator I = item->succ_begin(),
3427330f729Sjoerg          E = item->succ_end(); I != E; ++I) {
3437330f729Sjoerg       const CFGBlock *B = *I;
3447330f729Sjoerg       if (!B) do {
3457330f729Sjoerg         const CFGBlock *UB = I->getPossiblyUnreachableBlock();
3467330f729Sjoerg         if (!UB)
3477330f729Sjoerg           break;
3487330f729Sjoerg 
3497330f729Sjoerg         if (!TreatAllSuccessorsAsReachable.hasValue()) {
3507330f729Sjoerg           assert(PP);
3517330f729Sjoerg           TreatAllSuccessorsAsReachable =
3527330f729Sjoerg             shouldTreatSuccessorsAsReachable(item, *PP);
3537330f729Sjoerg         }
3547330f729Sjoerg 
3557330f729Sjoerg         if (TreatAllSuccessorsAsReachable.getValue()) {
3567330f729Sjoerg           B = UB;
3577330f729Sjoerg           break;
3587330f729Sjoerg         }
3597330f729Sjoerg       }
3607330f729Sjoerg       while (false);
3617330f729Sjoerg 
3627330f729Sjoerg       if (B) {
3637330f729Sjoerg         unsigned blockID = B->getBlockID();
3647330f729Sjoerg         if (!Reachable[blockID]) {
3657330f729Sjoerg           Reachable.set(blockID);
3667330f729Sjoerg           WL.push_back(B);
3677330f729Sjoerg           ++count;
3687330f729Sjoerg         }
3697330f729Sjoerg       }
3707330f729Sjoerg     }
3717330f729Sjoerg   }
3727330f729Sjoerg   return count;
3737330f729Sjoerg }
3747330f729Sjoerg 
scanMaybeReachableFromBlock(const CFGBlock * Start,Preprocessor & PP,llvm::BitVector & Reachable)3757330f729Sjoerg static unsigned scanMaybeReachableFromBlock(const CFGBlock *Start,
3767330f729Sjoerg                                             Preprocessor &PP,
3777330f729Sjoerg                                             llvm::BitVector &Reachable) {
3787330f729Sjoerg   return scanFromBlock(Start, Reachable, &PP, true);
3797330f729Sjoerg }
3807330f729Sjoerg 
3817330f729Sjoerg //===----------------------------------------------------------------------===//
3827330f729Sjoerg // Dead Code Scanner.
3837330f729Sjoerg //===----------------------------------------------------------------------===//
3847330f729Sjoerg 
3857330f729Sjoerg namespace {
3867330f729Sjoerg   class DeadCodeScan {
3877330f729Sjoerg     llvm::BitVector Visited;
3887330f729Sjoerg     llvm::BitVector &Reachable;
3897330f729Sjoerg     SmallVector<const CFGBlock *, 10> WorkList;
3907330f729Sjoerg     Preprocessor &PP;
3917330f729Sjoerg     ASTContext &C;
3927330f729Sjoerg 
3937330f729Sjoerg     typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
3947330f729Sjoerg     DeferredLocsTy;
3957330f729Sjoerg 
3967330f729Sjoerg     DeferredLocsTy DeferredLocs;
3977330f729Sjoerg 
3987330f729Sjoerg   public:
DeadCodeScan(llvm::BitVector & reachable,Preprocessor & PP,ASTContext & C)3997330f729Sjoerg     DeadCodeScan(llvm::BitVector &reachable, Preprocessor &PP, ASTContext &C)
4007330f729Sjoerg     : Visited(reachable.size()),
4017330f729Sjoerg       Reachable(reachable),
4027330f729Sjoerg       PP(PP), C(C) {}
4037330f729Sjoerg 
4047330f729Sjoerg     void enqueue(const CFGBlock *block);
4057330f729Sjoerg     unsigned scanBackwards(const CFGBlock *Start,
4067330f729Sjoerg     clang::reachable_code::Callback &CB);
4077330f729Sjoerg 
4087330f729Sjoerg     bool isDeadCodeRoot(const CFGBlock *Block);
4097330f729Sjoerg 
4107330f729Sjoerg     const Stmt *findDeadCode(const CFGBlock *Block);
4117330f729Sjoerg 
4127330f729Sjoerg     void reportDeadCode(const CFGBlock *B,
4137330f729Sjoerg                         const Stmt *S,
4147330f729Sjoerg                         clang::reachable_code::Callback &CB);
4157330f729Sjoerg   };
4167330f729Sjoerg }
4177330f729Sjoerg 
enqueue(const CFGBlock * block)4187330f729Sjoerg void DeadCodeScan::enqueue(const CFGBlock *block) {
4197330f729Sjoerg   unsigned blockID = block->getBlockID();
4207330f729Sjoerg   if (Reachable[blockID] || Visited[blockID])
4217330f729Sjoerg     return;
4227330f729Sjoerg   Visited[blockID] = true;
4237330f729Sjoerg   WorkList.push_back(block);
4247330f729Sjoerg }
4257330f729Sjoerg 
isDeadCodeRoot(const clang::CFGBlock * Block)4267330f729Sjoerg bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {
4277330f729Sjoerg   bool isDeadRoot = true;
4287330f729Sjoerg 
4297330f729Sjoerg   for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
4307330f729Sjoerg        E = Block->pred_end(); I != E; ++I) {
4317330f729Sjoerg     if (const CFGBlock *PredBlock = *I) {
4327330f729Sjoerg       unsigned blockID = PredBlock->getBlockID();
4337330f729Sjoerg       if (Visited[blockID]) {
4347330f729Sjoerg         isDeadRoot = false;
4357330f729Sjoerg         continue;
4367330f729Sjoerg       }
4377330f729Sjoerg       if (!Reachable[blockID]) {
4387330f729Sjoerg         isDeadRoot = false;
4397330f729Sjoerg         Visited[blockID] = true;
4407330f729Sjoerg         WorkList.push_back(PredBlock);
4417330f729Sjoerg         continue;
4427330f729Sjoerg       }
4437330f729Sjoerg     }
4447330f729Sjoerg   }
4457330f729Sjoerg 
4467330f729Sjoerg   return isDeadRoot;
4477330f729Sjoerg }
4487330f729Sjoerg 
isValidDeadStmt(const Stmt * S)4497330f729Sjoerg static bool isValidDeadStmt(const Stmt *S) {
4507330f729Sjoerg   if (S->getBeginLoc().isInvalid())
4517330f729Sjoerg     return false;
4527330f729Sjoerg   if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S))
4537330f729Sjoerg     return BO->getOpcode() != BO_Comma;
4547330f729Sjoerg   return true;
4557330f729Sjoerg }
4567330f729Sjoerg 
findDeadCode(const clang::CFGBlock * Block)4577330f729Sjoerg const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) {
4587330f729Sjoerg   for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I)
4597330f729Sjoerg     if (Optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
4607330f729Sjoerg       const Stmt *S = CS->getStmt();
4617330f729Sjoerg       if (isValidDeadStmt(S))
4627330f729Sjoerg         return S;
4637330f729Sjoerg     }
4647330f729Sjoerg 
4657330f729Sjoerg   CFGTerminator T = Block->getTerminator();
4667330f729Sjoerg   if (T.isStmtBranch()) {
4677330f729Sjoerg     const Stmt *S = T.getStmt();
4687330f729Sjoerg     if (S && isValidDeadStmt(S))
4697330f729Sjoerg       return S;
4707330f729Sjoerg   }
4717330f729Sjoerg 
4727330f729Sjoerg   return nullptr;
4737330f729Sjoerg }
4747330f729Sjoerg 
SrcCmp(const std::pair<const CFGBlock *,const Stmt * > * p1,const std::pair<const CFGBlock *,const Stmt * > * p2)4757330f729Sjoerg static int SrcCmp(const std::pair<const CFGBlock *, const Stmt *> *p1,
4767330f729Sjoerg                   const std::pair<const CFGBlock *, const Stmt *> *p2) {
4777330f729Sjoerg   if (p1->second->getBeginLoc() < p2->second->getBeginLoc())
4787330f729Sjoerg     return -1;
4797330f729Sjoerg   if (p2->second->getBeginLoc() < p1->second->getBeginLoc())
4807330f729Sjoerg     return 1;
4817330f729Sjoerg   return 0;
4827330f729Sjoerg }
4837330f729Sjoerg 
scanBackwards(const clang::CFGBlock * Start,clang::reachable_code::Callback & CB)4847330f729Sjoerg unsigned DeadCodeScan::scanBackwards(const clang::CFGBlock *Start,
4857330f729Sjoerg                                      clang::reachable_code::Callback &CB) {
4867330f729Sjoerg 
4877330f729Sjoerg   unsigned count = 0;
4887330f729Sjoerg   enqueue(Start);
4897330f729Sjoerg 
4907330f729Sjoerg   while (!WorkList.empty()) {
4917330f729Sjoerg     const CFGBlock *Block = WorkList.pop_back_val();
4927330f729Sjoerg 
4937330f729Sjoerg     // It is possible that this block has been marked reachable after
4947330f729Sjoerg     // it was enqueued.
4957330f729Sjoerg     if (Reachable[Block->getBlockID()])
4967330f729Sjoerg       continue;
4977330f729Sjoerg 
4987330f729Sjoerg     // Look for any dead code within the block.
4997330f729Sjoerg     const Stmt *S = findDeadCode(Block);
5007330f729Sjoerg 
5017330f729Sjoerg     if (!S) {
5027330f729Sjoerg       // No dead code.  Possibly an empty block.  Look at dead predecessors.
5037330f729Sjoerg       for (CFGBlock::const_pred_iterator I = Block->pred_begin(),
5047330f729Sjoerg            E = Block->pred_end(); I != E; ++I) {
5057330f729Sjoerg         if (const CFGBlock *predBlock = *I)
5067330f729Sjoerg           enqueue(predBlock);
5077330f729Sjoerg       }
5087330f729Sjoerg       continue;
5097330f729Sjoerg     }
5107330f729Sjoerg 
5117330f729Sjoerg     // Specially handle macro-expanded code.
5127330f729Sjoerg     if (S->getBeginLoc().isMacroID()) {
5137330f729Sjoerg       count += scanMaybeReachableFromBlock(Block, PP, Reachable);
5147330f729Sjoerg       continue;
5157330f729Sjoerg     }
5167330f729Sjoerg 
5177330f729Sjoerg     if (isDeadCodeRoot(Block)) {
5187330f729Sjoerg       reportDeadCode(Block, S, CB);
5197330f729Sjoerg       count += scanMaybeReachableFromBlock(Block, PP, Reachable);
5207330f729Sjoerg     }
5217330f729Sjoerg     else {
5227330f729Sjoerg       // Record this statement as the possibly best location in a
5237330f729Sjoerg       // strongly-connected component of dead code for emitting a
5247330f729Sjoerg       // warning.
5257330f729Sjoerg       DeferredLocs.push_back(std::make_pair(Block, S));
5267330f729Sjoerg     }
5277330f729Sjoerg   }
5287330f729Sjoerg 
5297330f729Sjoerg   // If we didn't find a dead root, then report the dead code with the
5307330f729Sjoerg   // earliest location.
5317330f729Sjoerg   if (!DeferredLocs.empty()) {
5327330f729Sjoerg     llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(), SrcCmp);
5337330f729Sjoerg     for (DeferredLocsTy::iterator I = DeferredLocs.begin(),
5347330f729Sjoerg          E = DeferredLocs.end(); I != E; ++I) {
5357330f729Sjoerg       const CFGBlock *Block = I->first;
5367330f729Sjoerg       if (Reachable[Block->getBlockID()])
5377330f729Sjoerg         continue;
5387330f729Sjoerg       reportDeadCode(Block, I->second, CB);
5397330f729Sjoerg       count += scanMaybeReachableFromBlock(Block, PP, Reachable);
5407330f729Sjoerg     }
5417330f729Sjoerg   }
5427330f729Sjoerg 
5437330f729Sjoerg   return count;
5447330f729Sjoerg }
5457330f729Sjoerg 
GetUnreachableLoc(const Stmt * S,SourceRange & R1,SourceRange & R2)5467330f729Sjoerg static SourceLocation GetUnreachableLoc(const Stmt *S,
5477330f729Sjoerg                                         SourceRange &R1,
5487330f729Sjoerg                                         SourceRange &R2) {
5497330f729Sjoerg   R1 = R2 = SourceRange();
5507330f729Sjoerg 
5517330f729Sjoerg   if (const Expr *Ex = dyn_cast<Expr>(S))
5527330f729Sjoerg     S = Ex->IgnoreParenImpCasts();
5537330f729Sjoerg 
5547330f729Sjoerg   switch (S->getStmtClass()) {
5557330f729Sjoerg     case Expr::BinaryOperatorClass: {
5567330f729Sjoerg       const BinaryOperator *BO = cast<BinaryOperator>(S);
5577330f729Sjoerg       return BO->getOperatorLoc();
5587330f729Sjoerg     }
5597330f729Sjoerg     case Expr::UnaryOperatorClass: {
5607330f729Sjoerg       const UnaryOperator *UO = cast<UnaryOperator>(S);
5617330f729Sjoerg       R1 = UO->getSubExpr()->getSourceRange();
5627330f729Sjoerg       return UO->getOperatorLoc();
5637330f729Sjoerg     }
5647330f729Sjoerg     case Expr::CompoundAssignOperatorClass: {
5657330f729Sjoerg       const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);
5667330f729Sjoerg       R1 = CAO->getLHS()->getSourceRange();
5677330f729Sjoerg       R2 = CAO->getRHS()->getSourceRange();
5687330f729Sjoerg       return CAO->getOperatorLoc();
5697330f729Sjoerg     }
5707330f729Sjoerg     case Expr::BinaryConditionalOperatorClass:
5717330f729Sjoerg     case Expr::ConditionalOperatorClass: {
5727330f729Sjoerg       const AbstractConditionalOperator *CO =
5737330f729Sjoerg       cast<AbstractConditionalOperator>(S);
5747330f729Sjoerg       return CO->getQuestionLoc();
5757330f729Sjoerg     }
5767330f729Sjoerg     case Expr::MemberExprClass: {
5777330f729Sjoerg       const MemberExpr *ME = cast<MemberExpr>(S);
5787330f729Sjoerg       R1 = ME->getSourceRange();
5797330f729Sjoerg       return ME->getMemberLoc();
5807330f729Sjoerg     }
5817330f729Sjoerg     case Expr::ArraySubscriptExprClass: {
5827330f729Sjoerg       const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);
5837330f729Sjoerg       R1 = ASE->getLHS()->getSourceRange();
5847330f729Sjoerg       R2 = ASE->getRHS()->getSourceRange();
5857330f729Sjoerg       return ASE->getRBracketLoc();
5867330f729Sjoerg     }
5877330f729Sjoerg     case Expr::CStyleCastExprClass: {
5887330f729Sjoerg       const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);
5897330f729Sjoerg       R1 = CSC->getSubExpr()->getSourceRange();
5907330f729Sjoerg       return CSC->getLParenLoc();
5917330f729Sjoerg     }
5927330f729Sjoerg     case Expr::CXXFunctionalCastExprClass: {
5937330f729Sjoerg       const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);
5947330f729Sjoerg       R1 = CE->getSubExpr()->getSourceRange();
5957330f729Sjoerg       return CE->getBeginLoc();
5967330f729Sjoerg     }
5977330f729Sjoerg     case Stmt::CXXTryStmtClass: {
5987330f729Sjoerg       return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
5997330f729Sjoerg     }
6007330f729Sjoerg     case Expr::ObjCBridgedCastExprClass: {
6017330f729Sjoerg       const ObjCBridgedCastExpr *CSC = cast<ObjCBridgedCastExpr>(S);
6027330f729Sjoerg       R1 = CSC->getSubExpr()->getSourceRange();
6037330f729Sjoerg       return CSC->getLParenLoc();
6047330f729Sjoerg     }
6057330f729Sjoerg     default: ;
6067330f729Sjoerg   }
6077330f729Sjoerg   R1 = S->getSourceRange();
6087330f729Sjoerg   return S->getBeginLoc();
6097330f729Sjoerg }
6107330f729Sjoerg 
reportDeadCode(const CFGBlock * B,const Stmt * S,clang::reachable_code::Callback & CB)6117330f729Sjoerg void DeadCodeScan::reportDeadCode(const CFGBlock *B,
6127330f729Sjoerg                                   const Stmt *S,
6137330f729Sjoerg                                   clang::reachable_code::Callback &CB) {
6147330f729Sjoerg   // Classify the unreachable code found, or suppress it in some cases.
6157330f729Sjoerg   reachable_code::UnreachableKind UK = reachable_code::UK_Other;
6167330f729Sjoerg 
6177330f729Sjoerg   if (isa<BreakStmt>(S)) {
6187330f729Sjoerg     UK = reachable_code::UK_Break;
6197330f729Sjoerg   } else if (isTrivialDoWhile(B, S) || isBuiltinUnreachable(S) ||
6207330f729Sjoerg              isBuiltinAssumeFalse(B, S, C)) {
6217330f729Sjoerg     return;
6227330f729Sjoerg   }
6237330f729Sjoerg   else if (isDeadReturn(B, S)) {
6247330f729Sjoerg     UK = reachable_code::UK_Return;
6257330f729Sjoerg   }
6267330f729Sjoerg 
6277330f729Sjoerg   SourceRange SilenceableCondVal;
6287330f729Sjoerg 
6297330f729Sjoerg   if (UK == reachable_code::UK_Other) {
6307330f729Sjoerg     // Check if the dead code is part of the "loop target" of
6317330f729Sjoerg     // a for/for-range loop.  This is the block that contains
6327330f729Sjoerg     // the increment code.
6337330f729Sjoerg     if (const Stmt *LoopTarget = B->getLoopTarget()) {
6347330f729Sjoerg       SourceLocation Loc = LoopTarget->getBeginLoc();
6357330f729Sjoerg       SourceRange R1(Loc, Loc), R2;
6367330f729Sjoerg 
6377330f729Sjoerg       if (const ForStmt *FS = dyn_cast<ForStmt>(LoopTarget)) {
6387330f729Sjoerg         const Expr *Inc = FS->getInc();
6397330f729Sjoerg         Loc = Inc->getBeginLoc();
6407330f729Sjoerg         R2 = Inc->getSourceRange();
6417330f729Sjoerg       }
6427330f729Sjoerg 
6437330f729Sjoerg       CB.HandleUnreachable(reachable_code::UK_Loop_Increment,
6447330f729Sjoerg                            Loc, SourceRange(), SourceRange(Loc, Loc), R2);
6457330f729Sjoerg       return;
6467330f729Sjoerg     }
6477330f729Sjoerg 
6487330f729Sjoerg     // Check if the dead block has a predecessor whose branch has
6497330f729Sjoerg     // a configuration value that *could* be modified to
6507330f729Sjoerg     // silence the warning.
6517330f729Sjoerg     CFGBlock::const_pred_iterator PI = B->pred_begin();
6527330f729Sjoerg     if (PI != B->pred_end()) {
6537330f729Sjoerg       if (const CFGBlock *PredBlock = PI->getPossiblyUnreachableBlock()) {
6547330f729Sjoerg         const Stmt *TermCond =
6557330f729Sjoerg             PredBlock->getTerminatorCondition(/* strip parens */ false);
6567330f729Sjoerg         isConfigurationValue(TermCond, PP, &SilenceableCondVal);
6577330f729Sjoerg       }
6587330f729Sjoerg     }
6597330f729Sjoerg   }
6607330f729Sjoerg 
6617330f729Sjoerg   SourceRange R1, R2;
6627330f729Sjoerg   SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
6637330f729Sjoerg   CB.HandleUnreachable(UK, Loc, SilenceableCondVal, R1, R2);
6647330f729Sjoerg }
6657330f729Sjoerg 
6667330f729Sjoerg //===----------------------------------------------------------------------===//
6677330f729Sjoerg // Reachability APIs.
6687330f729Sjoerg //===----------------------------------------------------------------------===//
6697330f729Sjoerg 
6707330f729Sjoerg namespace clang { namespace reachable_code {
6717330f729Sjoerg 
anchor()6727330f729Sjoerg void Callback::anchor() { }
6737330f729Sjoerg 
ScanReachableFromBlock(const CFGBlock * Start,llvm::BitVector & Reachable)6747330f729Sjoerg unsigned ScanReachableFromBlock(const CFGBlock *Start,
6757330f729Sjoerg                                 llvm::BitVector &Reachable) {
6767330f729Sjoerg   return scanFromBlock(Start, Reachable, /* SourceManager* */ nullptr, false);
6777330f729Sjoerg }
6787330f729Sjoerg 
FindUnreachableCode(AnalysisDeclContext & AC,Preprocessor & PP,Callback & CB)6797330f729Sjoerg void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,
6807330f729Sjoerg                          Callback &CB) {
6817330f729Sjoerg 
6827330f729Sjoerg   CFG *cfg = AC.getCFG();
6837330f729Sjoerg   if (!cfg)
6847330f729Sjoerg     return;
6857330f729Sjoerg 
6867330f729Sjoerg   // Scan for reachable blocks from the entrance of the CFG.
6877330f729Sjoerg   // If there are no unreachable blocks, we're done.
6887330f729Sjoerg   llvm::BitVector reachable(cfg->getNumBlockIDs());
6897330f729Sjoerg   unsigned numReachable =
6907330f729Sjoerg     scanMaybeReachableFromBlock(&cfg->getEntry(), PP, reachable);
6917330f729Sjoerg   if (numReachable == cfg->getNumBlockIDs())
6927330f729Sjoerg     return;
6937330f729Sjoerg 
6947330f729Sjoerg   // If there aren't explicit EH edges, we should include the 'try' dispatch
6957330f729Sjoerg   // blocks as roots.
6967330f729Sjoerg   if (!AC.getCFGBuildOptions().AddEHEdges) {
6977330f729Sjoerg     for (CFG::try_block_iterator I = cfg->try_blocks_begin(),
6987330f729Sjoerg          E = cfg->try_blocks_end() ; I != E; ++I) {
6997330f729Sjoerg       numReachable += scanMaybeReachableFromBlock(*I, PP, reachable);
7007330f729Sjoerg     }
7017330f729Sjoerg     if (numReachable == cfg->getNumBlockIDs())
7027330f729Sjoerg       return;
7037330f729Sjoerg   }
7047330f729Sjoerg 
7057330f729Sjoerg   // There are some unreachable blocks.  We need to find the root blocks that
7067330f729Sjoerg   // contain code that should be considered unreachable.
7077330f729Sjoerg   for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
7087330f729Sjoerg     const CFGBlock *block = *I;
7097330f729Sjoerg     // A block may have been marked reachable during this loop.
7107330f729Sjoerg     if (reachable[block->getBlockID()])
7117330f729Sjoerg       continue;
7127330f729Sjoerg 
7137330f729Sjoerg     DeadCodeScan DS(reachable, PP, AC.getASTContext());
7147330f729Sjoerg     numReachable += DS.scanBackwards(block, CB);
7157330f729Sjoerg 
7167330f729Sjoerg     if (numReachable == cfg->getNumBlockIDs())
7177330f729Sjoerg       return;
7187330f729Sjoerg   }
7197330f729Sjoerg }
7207330f729Sjoerg 
7217330f729Sjoerg }} // end namespace clang::reachable_code
722