Path: blob/main/contrib/llvm-project/clang/lib/Analysis/ReachableCode.cpp
35233 views
//===-- ReachableCode.cpp - Code Reachability Analysis --------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements a flow-sensitive, path-insensitive analysis of9// determining reachable blocks within a CFG.10//11//===----------------------------------------------------------------------===//1213#include "clang/Analysis/Analyses/ReachableCode.h"14#include "clang/AST/Attr.h"15#include "clang/AST/Expr.h"16#include "clang/AST/ExprCXX.h"17#include "clang/AST/ExprObjC.h"18#include "clang/AST/ParentMap.h"19#include "clang/AST/RecursiveASTVisitor.h"20#include "clang/AST/StmtCXX.h"21#include "clang/Analysis/AnalysisDeclContext.h"22#include "clang/Analysis/CFG.h"23#include "clang/Basic/Builtins.h"24#include "clang/Basic/SourceManager.h"25#include "clang/Lex/Preprocessor.h"26#include "llvm/ADT/BitVector.h"27#include "llvm/ADT/SmallVector.h"28#include <optional>2930using namespace clang;3132//===----------------------------------------------------------------------===//33// Core Reachability Analysis routines.34//===----------------------------------------------------------------------===//3536static bool isEnumConstant(const Expr *Ex) {37const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex);38if (!DR)39return false;40return isa<EnumConstantDecl>(DR->getDecl());41}4243static bool isTrivialExpression(const Expr *Ex) {44Ex = Ex->IgnoreParenCasts();45return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||46isa<CXXBoolLiteralExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||47isa<CharacterLiteral>(Ex) ||48isEnumConstant(Ex);49}5051static bool isTrivialDoWhile(const CFGBlock *B, const Stmt *S) {52// Check if the block ends with a do...while() and see if 'S' is the53// condition.54if (const Stmt *Term = B->getTerminatorStmt()) {55if (const DoStmt *DS = dyn_cast<DoStmt>(Term)) {56const Expr *Cond = DS->getCond()->IgnoreParenCasts();57return Cond == S && isTrivialExpression(Cond);58}59}60return false;61}6263static bool isBuiltinUnreachable(const Stmt *S) {64if (const auto *DRE = dyn_cast<DeclRefExpr>(S))65if (const auto *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()))66return FDecl->getIdentifier() &&67FDecl->getBuiltinID() == Builtin::BI__builtin_unreachable;68return false;69}7071static bool isBuiltinAssumeFalse(const CFGBlock *B, const Stmt *S,72ASTContext &C) {73if (B->empty()) {74// Happens if S is B's terminator and B contains nothing else75// (e.g. a CFGBlock containing only a goto).76return false;77}78if (std::optional<CFGStmt> CS = B->back().getAs<CFGStmt>()) {79if (const auto *CE = dyn_cast<CallExpr>(CS->getStmt())) {80return CE->getCallee()->IgnoreCasts() == S && CE->isBuiltinAssumeFalse(C);81}82}83return false;84}8586static bool isDeadReturn(const CFGBlock *B, const Stmt *S) {87// Look to see if the current control flow ends with a 'return', and see if88// 'S' is a substatement. The 'return' may not be the last element in the89// block, or may be in a subsequent block because of destructors.90const CFGBlock *Current = B;91while (true) {92for (const CFGElement &CE : llvm::reverse(*Current)) {93if (std::optional<CFGStmt> CS = CE.getAs<CFGStmt>()) {94if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {95if (RS == S)96return true;97if (const Expr *RE = RS->getRetValue()) {98RE = RE->IgnoreParenCasts();99if (RE == S)100return true;101ParentMap PM(const_cast<Expr *>(RE));102// If 'S' is in the ParentMap, it is a subexpression of103// the return statement.104return PM.getParent(S);105}106}107break;108}109}110// Note also that we are restricting the search for the return statement111// to stop at control-flow; only part of a return statement may be dead,112// without the whole return statement being dead.113if (Current->getTerminator().isTemporaryDtorsBranch()) {114// Temporary destructors have a predictable control flow, thus we want to115// look into the next block for the return statement.116// We look into the false branch, as we know the true branch only contains117// the call to the destructor.118assert(Current->succ_size() == 2);119Current = *(Current->succ_begin() + 1);120} else if (!Current->getTerminatorStmt() && Current->succ_size() == 1) {121// If there is only one successor, we're not dealing with outgoing control122// flow. Thus, look into the next block.123Current = *Current->succ_begin();124if (Current->pred_size() > 1) {125// If there is more than one predecessor, we're dealing with incoming126// control flow - if the return statement is in that block, it might127// well be reachable via a different control flow, thus it's not dead.128return false;129}130} else {131// We hit control flow or a dead end. Stop searching.132return false;133}134}135llvm_unreachable("Broke out of infinite loop.");136}137138static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager &SM) {139assert(Loc.isMacroID());140SourceLocation Last;141do {142Last = Loc;143Loc = SM.getImmediateMacroCallerLoc(Loc);144} while (Loc.isMacroID());145return Last;146}147148/// Returns true if the statement is expanded from a configuration macro.149static bool isExpandedFromConfigurationMacro(const Stmt *S,150Preprocessor &PP,151bool IgnoreYES_NO = false) {152// FIXME: This is not very precise. Here we just check to see if the153// value comes from a macro, but we can do much better. This is likely154// to be over conservative. This logic is factored into a separate function155// so that we can refine it later.156SourceLocation L = S->getBeginLoc();157if (L.isMacroID()) {158SourceManager &SM = PP.getSourceManager();159if (IgnoreYES_NO) {160// The Objective-C constant 'YES' and 'NO'161// are defined as macros. Do not treat them162// as configuration values.163SourceLocation TopL = getTopMostMacro(L, SM);164StringRef MacroName = PP.getImmediateMacroName(TopL);165if (MacroName == "YES" || MacroName == "NO")166return false;167} else if (!PP.getLangOpts().CPlusPlus) {168// Do not treat C 'false' and 'true' macros as configuration values.169SourceLocation TopL = getTopMostMacro(L, SM);170StringRef MacroName = PP.getImmediateMacroName(TopL);171if (MacroName == "false" || MacroName == "true")172return false;173}174return true;175}176return false;177}178179static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP);180181/// Returns true if the statement represents a configuration value.182///183/// A configuration value is something usually determined at compile-time184/// to conditionally always execute some branch. Such guards are for185/// "sometimes unreachable" code. Such code is usually not interesting186/// to report as unreachable, and may mask truly unreachable code within187/// those blocks.188static bool isConfigurationValue(const Stmt *S,189Preprocessor &PP,190SourceRange *SilenceableCondVal = nullptr,191bool IncludeIntegers = true,192bool WrappedInParens = false) {193if (!S)194return false;195196if (const auto *Ex = dyn_cast<Expr>(S))197S = Ex->IgnoreImplicit();198199if (const auto *Ex = dyn_cast<Expr>(S))200S = Ex->IgnoreCasts();201202// Special case looking for the sigil '()' around an integer literal.203if (const ParenExpr *PE = dyn_cast<ParenExpr>(S))204if (!PE->getBeginLoc().isMacroID())205return isConfigurationValue(PE->getSubExpr(), PP, SilenceableCondVal,206IncludeIntegers, true);207208if (const Expr *Ex = dyn_cast<Expr>(S))209S = Ex->IgnoreCasts();210211bool IgnoreYES_NO = false;212213switch (S->getStmtClass()) {214case Stmt::CallExprClass: {215const FunctionDecl *Callee =216dyn_cast_or_null<FunctionDecl>(cast<CallExpr>(S)->getCalleeDecl());217return Callee ? Callee->isConstexpr() : false;218}219case Stmt::DeclRefExprClass:220return isConfigurationValue(cast<DeclRefExpr>(S)->getDecl(), PP);221case Stmt::ObjCBoolLiteralExprClass:222IgnoreYES_NO = true;223[[fallthrough]];224case Stmt::CXXBoolLiteralExprClass:225case Stmt::IntegerLiteralClass: {226const Expr *E = cast<Expr>(S);227if (IncludeIntegers) {228if (SilenceableCondVal && !SilenceableCondVal->getBegin().isValid())229*SilenceableCondVal = E->getSourceRange();230return WrappedInParens ||231isExpandedFromConfigurationMacro(E, PP, IgnoreYES_NO);232}233return false;234}235case Stmt::MemberExprClass:236return isConfigurationValue(cast<MemberExpr>(S)->getMemberDecl(), PP);237case Stmt::UnaryExprOrTypeTraitExprClass:238return true;239case Stmt::BinaryOperatorClass: {240const BinaryOperator *B = cast<BinaryOperator>(S);241// Only include raw integers (not enums) as configuration242// values if they are used in a logical or comparison operator243// (not arithmetic).244IncludeIntegers &= (B->isLogicalOp() || B->isComparisonOp());245return isConfigurationValue(B->getLHS(), PP, SilenceableCondVal,246IncludeIntegers) ||247isConfigurationValue(B->getRHS(), PP, SilenceableCondVal,248IncludeIntegers);249}250case Stmt::UnaryOperatorClass: {251const UnaryOperator *UO = cast<UnaryOperator>(S);252if (UO->getOpcode() != UO_LNot && UO->getOpcode() != UO_Minus)253return false;254bool SilenceableCondValNotSet =255SilenceableCondVal && SilenceableCondVal->getBegin().isInvalid();256bool IsSubExprConfigValue =257isConfigurationValue(UO->getSubExpr(), PP, SilenceableCondVal,258IncludeIntegers, WrappedInParens);259// Update the silenceable condition value source range only if the range260// was set directly by the child expression.261if (SilenceableCondValNotSet &&262SilenceableCondVal->getBegin().isValid() &&263*SilenceableCondVal ==264UO->getSubExpr()->IgnoreCasts()->getSourceRange())265*SilenceableCondVal = UO->getSourceRange();266return IsSubExprConfigValue;267}268default:269return false;270}271}272273static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP) {274if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D))275return isConfigurationValue(ED->getInitExpr(), PP);276if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {277// As a heuristic, treat globals as configuration values. Note278// that we only will get here if Sema evaluated this279// condition to a constant expression, which means the global280// had to be declared in a way to be a truly constant value.281// We could generalize this to local variables, but it isn't282// clear if those truly represent configuration values that283// gate unreachable code.284if (!VD->hasLocalStorage())285return true;286287// As a heuristic, locals that have been marked 'const' explicitly288// can be treated as configuration values as well.289return VD->getType().isLocalConstQualified();290}291return false;292}293294/// Returns true if we should always explore all successors of a block.295static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B,296Preprocessor &PP) {297if (const Stmt *Term = B->getTerminatorStmt()) {298if (isa<SwitchStmt>(Term))299return true;300// Specially handle '||' and '&&'.301if (isa<BinaryOperator>(Term)) {302return isConfigurationValue(Term, PP);303}304// Do not treat constexpr if statement successors as unreachable in warnings305// since the point of these statements is to determine branches at compile306// time.307if (const auto *IS = dyn_cast<IfStmt>(Term);308IS != nullptr && IS->isConstexpr())309return true;310}311312const Stmt *Cond = B->getTerminatorCondition(/* stripParens */ false);313return isConfigurationValue(Cond, PP);314}315316static unsigned scanFromBlock(const CFGBlock *Start,317llvm::BitVector &Reachable,318Preprocessor *PP,319bool IncludeSometimesUnreachableEdges) {320unsigned count = 0;321322// Prep work queue323SmallVector<const CFGBlock*, 32> WL;324325// The entry block may have already been marked reachable326// by the caller.327if (!Reachable[Start->getBlockID()]) {328++count;329Reachable[Start->getBlockID()] = true;330}331332WL.push_back(Start);333334// Find the reachable blocks from 'Start'.335while (!WL.empty()) {336const CFGBlock *item = WL.pop_back_val();337338// There are cases where we want to treat all successors as reachable.339// The idea is that some "sometimes unreachable" code is not interesting,340// and that we should forge ahead and explore those branches anyway.341// This allows us to potentially uncover some "always unreachable" code342// within the "sometimes unreachable" code.343// Look at the successors and mark then reachable.344std::optional<bool> TreatAllSuccessorsAsReachable;345if (!IncludeSometimesUnreachableEdges)346TreatAllSuccessorsAsReachable = false;347348for (CFGBlock::const_succ_iterator I = item->succ_begin(),349E = item->succ_end(); I != E; ++I) {350const CFGBlock *B = *I;351if (!B) do {352const CFGBlock *UB = I->getPossiblyUnreachableBlock();353if (!UB)354break;355356if (!TreatAllSuccessorsAsReachable) {357assert(PP);358TreatAllSuccessorsAsReachable =359shouldTreatSuccessorsAsReachable(item, *PP);360}361362if (*TreatAllSuccessorsAsReachable) {363B = UB;364break;365}366}367while (false);368369if (B) {370unsigned blockID = B->getBlockID();371if (!Reachable[blockID]) {372Reachable.set(blockID);373WL.push_back(B);374++count;375}376}377}378}379return count;380}381382static unsigned scanMaybeReachableFromBlock(const CFGBlock *Start,383Preprocessor &PP,384llvm::BitVector &Reachable) {385return scanFromBlock(Start, Reachable, &PP, true);386}387388//===----------------------------------------------------------------------===//389// Dead Code Scanner.390//===----------------------------------------------------------------------===//391392namespace {393class DeadCodeScan {394llvm::BitVector Visited;395llvm::BitVector &Reachable;396SmallVector<const CFGBlock *, 10> WorkList;397Preprocessor &PP;398ASTContext &C;399400typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>401DeferredLocsTy;402403DeferredLocsTy DeferredLocs;404405public:406DeadCodeScan(llvm::BitVector &reachable, Preprocessor &PP, ASTContext &C)407: Visited(reachable.size()),408Reachable(reachable),409PP(PP), C(C) {}410411void enqueue(const CFGBlock *block);412unsigned scanBackwards(const CFGBlock *Start,413clang::reachable_code::Callback &CB);414415bool isDeadCodeRoot(const CFGBlock *Block);416417const Stmt *findDeadCode(const CFGBlock *Block);418419void reportDeadCode(const CFGBlock *B,420const Stmt *S,421clang::reachable_code::Callback &CB);422};423}424425void DeadCodeScan::enqueue(const CFGBlock *block) {426unsigned blockID = block->getBlockID();427if (Reachable[blockID] || Visited[blockID])428return;429Visited[blockID] = true;430WorkList.push_back(block);431}432433bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {434bool isDeadRoot = true;435436for (CFGBlock::const_pred_iterator I = Block->pred_begin(),437E = Block->pred_end(); I != E; ++I) {438if (const CFGBlock *PredBlock = *I) {439unsigned blockID = PredBlock->getBlockID();440if (Visited[blockID]) {441isDeadRoot = false;442continue;443}444if (!Reachable[blockID]) {445isDeadRoot = false;446Visited[blockID] = true;447WorkList.push_back(PredBlock);448continue;449}450}451}452453return isDeadRoot;454}455456// Check if the given `DeadStmt` is a coroutine statement and is a substmt of457// the coroutine statement. `Block` is the CFGBlock containing the `DeadStmt`.458static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) {459// The coroutine statement, co_return, co_await, or co_yield.460const Stmt *CoroStmt = nullptr;461// Find the first coroutine statement after the DeadStmt in the block.462bool AfterDeadStmt = false;463for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I != E;464++I)465if (std::optional<CFGStmt> CS = I->getAs<CFGStmt>()) {466const Stmt *S = CS->getStmt();467if (S == DeadStmt)468AfterDeadStmt = true;469if (AfterDeadStmt &&470// For simplicity, we only check simple coroutine statements.471(llvm::isa<CoreturnStmt>(S) || llvm::isa<CoroutineSuspendExpr>(S))) {472CoroStmt = S;473break;474}475}476if (!CoroStmt)477return false;478struct Checker : RecursiveASTVisitor<Checker> {479const Stmt *DeadStmt;480bool CoroutineSubStmt = false;481Checker(const Stmt *S) : DeadStmt(S) {}482bool VisitStmt(const Stmt *S) {483if (S == DeadStmt)484CoroutineSubStmt = true;485return true;486}487// Statements captured in the CFG can be implicit.488bool shouldVisitImplicitCode() const { return true; }489};490Checker checker(DeadStmt);491checker.TraverseStmt(const_cast<Stmt *>(CoroStmt));492return checker.CoroutineSubStmt;493}494495static bool isValidDeadStmt(const Stmt *S, const clang::CFGBlock *Block) {496if (S->getBeginLoc().isInvalid())497return false;498if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S))499return BO->getOpcode() != BO_Comma;500// Coroutine statements are never considered dead statements, because removing501// them may change the function semantic if it is the only coroutine statement502// of the coroutine.503return !isInCoroutineStmt(S, Block);504}505506const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) {507for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I)508if (std::optional<CFGStmt> CS = I->getAs<CFGStmt>()) {509const Stmt *S = CS->getStmt();510if (isValidDeadStmt(S, Block))511return S;512}513514CFGTerminator T = Block->getTerminator();515if (T.isStmtBranch()) {516const Stmt *S = T.getStmt();517if (S && isValidDeadStmt(S, Block))518return S;519}520521return nullptr;522}523524static int SrcCmp(const std::pair<const CFGBlock *, const Stmt *> *p1,525const std::pair<const CFGBlock *, const Stmt *> *p2) {526if (p1->second->getBeginLoc() < p2->second->getBeginLoc())527return -1;528if (p2->second->getBeginLoc() < p1->second->getBeginLoc())529return 1;530return 0;531}532533unsigned DeadCodeScan::scanBackwards(const clang::CFGBlock *Start,534clang::reachable_code::Callback &CB) {535536unsigned count = 0;537enqueue(Start);538539while (!WorkList.empty()) {540const CFGBlock *Block = WorkList.pop_back_val();541542// It is possible that this block has been marked reachable after543// it was enqueued.544if (Reachable[Block->getBlockID()])545continue;546547// Look for any dead code within the block.548const Stmt *S = findDeadCode(Block);549550if (!S) {551// No dead code. Possibly an empty block. Look at dead predecessors.552for (CFGBlock::const_pred_iterator I = Block->pred_begin(),553E = Block->pred_end(); I != E; ++I) {554if (const CFGBlock *predBlock = *I)555enqueue(predBlock);556}557continue;558}559560// Specially handle macro-expanded code.561if (S->getBeginLoc().isMacroID()) {562count += scanMaybeReachableFromBlock(Block, PP, Reachable);563continue;564}565566if (isDeadCodeRoot(Block)) {567reportDeadCode(Block, S, CB);568count += scanMaybeReachableFromBlock(Block, PP, Reachable);569}570else {571// Record this statement as the possibly best location in a572// strongly-connected component of dead code for emitting a573// warning.574DeferredLocs.push_back(std::make_pair(Block, S));575}576}577578// If we didn't find a dead root, then report the dead code with the579// earliest location.580if (!DeferredLocs.empty()) {581llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(), SrcCmp);582for (const auto &I : DeferredLocs) {583const CFGBlock *Block = I.first;584if (Reachable[Block->getBlockID()])585continue;586reportDeadCode(Block, I.second, CB);587count += scanMaybeReachableFromBlock(Block, PP, Reachable);588}589}590591return count;592}593594static SourceLocation GetUnreachableLoc(const Stmt *S,595SourceRange &R1,596SourceRange &R2) {597R1 = R2 = SourceRange();598599if (const Expr *Ex = dyn_cast<Expr>(S))600S = Ex->IgnoreParenImpCasts();601602switch (S->getStmtClass()) {603case Expr::BinaryOperatorClass: {604const BinaryOperator *BO = cast<BinaryOperator>(S);605return BO->getOperatorLoc();606}607case Expr::UnaryOperatorClass: {608const UnaryOperator *UO = cast<UnaryOperator>(S);609R1 = UO->getSubExpr()->getSourceRange();610return UO->getOperatorLoc();611}612case Expr::CompoundAssignOperatorClass: {613const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S);614R1 = CAO->getLHS()->getSourceRange();615R2 = CAO->getRHS()->getSourceRange();616return CAO->getOperatorLoc();617}618case Expr::BinaryConditionalOperatorClass:619case Expr::ConditionalOperatorClass: {620const AbstractConditionalOperator *CO =621cast<AbstractConditionalOperator>(S);622return CO->getQuestionLoc();623}624case Expr::MemberExprClass: {625const MemberExpr *ME = cast<MemberExpr>(S);626R1 = ME->getSourceRange();627return ME->getMemberLoc();628}629case Expr::ArraySubscriptExprClass: {630const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S);631R1 = ASE->getLHS()->getSourceRange();632R2 = ASE->getRHS()->getSourceRange();633return ASE->getRBracketLoc();634}635case Expr::CStyleCastExprClass: {636const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S);637R1 = CSC->getSubExpr()->getSourceRange();638return CSC->getLParenLoc();639}640case Expr::CXXFunctionalCastExprClass: {641const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S);642R1 = CE->getSubExpr()->getSourceRange();643return CE->getBeginLoc();644}645case Stmt::CXXTryStmtClass: {646return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();647}648case Expr::ObjCBridgedCastExprClass: {649const ObjCBridgedCastExpr *CSC = cast<ObjCBridgedCastExpr>(S);650R1 = CSC->getSubExpr()->getSourceRange();651return CSC->getLParenLoc();652}653default: ;654}655R1 = S->getSourceRange();656return S->getBeginLoc();657}658659void DeadCodeScan::reportDeadCode(const CFGBlock *B,660const Stmt *S,661clang::reachable_code::Callback &CB) {662// Classify the unreachable code found, or suppress it in some cases.663reachable_code::UnreachableKind UK = reachable_code::UK_Other;664665if (isa<BreakStmt>(S)) {666UK = reachable_code::UK_Break;667} else if (isTrivialDoWhile(B, S) || isBuiltinUnreachable(S) ||668isBuiltinAssumeFalse(B, S, C)) {669return;670}671else if (isDeadReturn(B, S)) {672UK = reachable_code::UK_Return;673}674675const auto *AS = dyn_cast<AttributedStmt>(S);676bool HasFallThroughAttr =677AS && hasSpecificAttr<FallThroughAttr>(AS->getAttrs());678679SourceRange SilenceableCondVal;680681if (UK == reachable_code::UK_Other) {682// Check if the dead code is part of the "loop target" of683// a for/for-range loop. This is the block that contains684// the increment code.685if (const Stmt *LoopTarget = B->getLoopTarget()) {686SourceLocation Loc = LoopTarget->getBeginLoc();687SourceRange R1(Loc, Loc), R2;688689if (const ForStmt *FS = dyn_cast<ForStmt>(LoopTarget)) {690const Expr *Inc = FS->getInc();691Loc = Inc->getBeginLoc();692R2 = Inc->getSourceRange();693}694695CB.HandleUnreachable(reachable_code::UK_Loop_Increment, Loc,696SourceRange(), SourceRange(Loc, Loc), R2,697HasFallThroughAttr);698return;699}700701// Check if the dead block has a predecessor whose branch has702// a configuration value that *could* be modified to703// silence the warning.704CFGBlock::const_pred_iterator PI = B->pred_begin();705if (PI != B->pred_end()) {706if (const CFGBlock *PredBlock = PI->getPossiblyUnreachableBlock()) {707const Stmt *TermCond =708PredBlock->getTerminatorCondition(/* strip parens */ false);709isConfigurationValue(TermCond, PP, &SilenceableCondVal);710}711}712}713714SourceRange R1, R2;715SourceLocation Loc = GetUnreachableLoc(S, R1, R2);716CB.HandleUnreachable(UK, Loc, SilenceableCondVal, R1, R2, HasFallThroughAttr);717}718719//===----------------------------------------------------------------------===//720// Reachability APIs.721//===----------------------------------------------------------------------===//722723namespace clang { namespace reachable_code {724725void Callback::anchor() { }726727unsigned ScanReachableFromBlock(const CFGBlock *Start,728llvm::BitVector &Reachable) {729return scanFromBlock(Start, Reachable, /* SourceManager* */ nullptr, false);730}731732void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP,733Callback &CB) {734735CFG *cfg = AC.getCFG();736if (!cfg)737return;738739// Scan for reachable blocks from the entrance of the CFG.740// If there are no unreachable blocks, we're done.741llvm::BitVector reachable(cfg->getNumBlockIDs());742unsigned numReachable =743scanMaybeReachableFromBlock(&cfg->getEntry(), PP, reachable);744if (numReachable == cfg->getNumBlockIDs())745return;746747// If there aren't explicit EH edges, we should include the 'try' dispatch748// blocks as roots.749if (!AC.getCFGBuildOptions().AddEHEdges) {750for (const CFGBlock *B : cfg->try_blocks())751numReachable += scanMaybeReachableFromBlock(B, PP, reachable);752if (numReachable == cfg->getNumBlockIDs())753return;754}755756// There are some unreachable blocks. We need to find the root blocks that757// contain code that should be considered unreachable.758for (const CFGBlock *block : *cfg) {759// A block may have been marked reachable during this loop.760if (reachable[block->getBlockID()])761continue;762763DeadCodeScan DS(reachable, PP, AC.getASTContext());764numReachable += DS.scanBackwards(block, CB);765766if (numReachable == cfg->getNumBlockIDs())767return;768}769}770771}} // end namespace clang::reachable_code772773774