25 #include "llvm/ADT/BitVector.h" 26 #include "llvm/ADT/SmallVector.h" 28 using namespace clang;
38 return isa<EnumConstantDecl>(DR->
getDecl());
43 return isa<IntegerLiteral>(Ex) || isa<StringLiteral>(Ex) ||
44 isa<CXXBoolLiteralExpr>(Ex) || isa<ObjCBoolLiteralExpr>(Ex) ||
45 isa<CharacterLiteral>(Ex) ||
53 if (
const DoStmt *DS = dyn_cast<DoStmt>(Term)) {
62 if (
const auto *DRE = dyn_cast<DeclRefExpr>(S))
63 if (
const auto *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()))
64 return FDecl->getIdentifier() &&
65 FDecl->getBuiltinID() == Builtin::BI__builtin_unreachable;
77 if (
const auto *CE = dyn_cast<CallExpr>(CS->getStmt())) {
78 return CE->getCallee()->IgnoreCasts() == S && CE->isBuiltinAssumeFalse(C);
94 if (
const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
97 if (
const Expr *RE = RS->getRetValue()) {
98 RE = RE->IgnoreParenCasts();
119 Current = *(Current->succ_begin() + 1);
135 llvm_unreachable(
"Broke out of infinite loop.");
151 bool IgnoreYES_NO =
false) {
165 if (MacroName ==
"YES" || MacroName ==
"NO")
171 if (MacroName ==
"false" || MacroName ==
"true")
191 bool IncludeIntegers =
true,
192 bool WrappedInParens =
false) {
198 if (
const Expr *Ex = dyn_cast<Expr>(S))
199 S = Ex->IgnoreCasts();
202 if (
const ParenExpr *PE = dyn_cast<ParenExpr>(S))
203 if (!PE->getLocStart().isMacroID())
205 IncludeIntegers,
true);
207 if (
const Expr *Ex = dyn_cast<Expr>(S))
208 S = Ex->IgnoreCasts();
210 bool IgnoreYES_NO =
false;
213 case Stmt::CallExprClass: {
215 dyn_cast_or_null<FunctionDecl>(cast<CallExpr>(S)->getCalleeDecl());
218 case Stmt::DeclRefExprClass:
220 case Stmt::ObjCBoolLiteralExprClass:
223 case Stmt::CXXBoolLiteralExprClass:
224 case Stmt::IntegerLiteralClass: {
225 const Expr *E = cast<Expr>(S);
226 if (IncludeIntegers) {
227 if (SilenceableCondVal && !SilenceableCondVal->getBegin().isValid())
233 case Stmt::MemberExprClass:
235 case Stmt::UnaryExprOrTypeTraitExprClass:
237 case Stmt::BinaryOperatorClass: {
248 case Stmt::UnaryOperatorClass: {
252 bool SilenceableCondValNotSet =
253 SilenceableCondVal && SilenceableCondVal->getBegin().isInvalid();
254 bool IsSubExprConfigValue =
256 IncludeIntegers, WrappedInParens);
259 if (SilenceableCondValNotSet &&
260 SilenceableCondVal->getBegin().isValid() &&
261 *SilenceableCondVal ==
264 return IsSubExprConfigValue;
274 if (
const VarDecl *VD = dyn_cast<VarDecl>(D)) {
282 if (!VD->hasLocalStorage())
287 return VD->getType().isLocalConstQualified();
296 if (isa<SwitchStmt>(Term))
299 if (isa<BinaryOperator>(Term)) {
309 llvm::BitVector &Reachable,
311 bool IncludeSometimesUnreachableEdges) {
327 while (!WL.empty()) {
328 const CFGBlock *item = WL.pop_back_val();
337 if (!IncludeSometimesUnreachableEdges)
338 TreatAllSuccessorsAsReachable =
false;
341 E = item->
succ_end(); I != E; ++I) {
344 const CFGBlock *UB = I->getPossiblyUnreachableBlock();
348 if (!TreatAllSuccessorsAsReachable.hasValue()) {
350 TreatAllSuccessorsAsReachable =
354 if (TreatAllSuccessorsAsReachable.getValue()) {
363 if (!Reachable[blockID]) {
364 Reachable.set(blockID);
376 llvm::BitVector &Reachable) {
386 llvm::BitVector Visited;
387 llvm::BitVector &Reachable;
395 DeferredLocsTy DeferredLocs;
399 : Visited(reachable.size()),
400 Reachable(reachable),
403 void enqueue(
const CFGBlock *block);
404 unsigned scanBackwards(
const CFGBlock *Start,
407 bool isDeadCodeRoot(
const CFGBlock *Block);
411 void reportDeadCode(
const CFGBlock *B,
417 void DeadCodeScan::enqueue(
const CFGBlock *block) {
419 if (Reachable[blockID] || Visited[blockID])
421 Visited[blockID] =
true;
422 WorkList.push_back(block);
426 bool isDeadRoot =
true;
429 E = Block->
pred_end(); I != E; ++I) {
430 if (
const CFGBlock *PredBlock = *I) {
431 unsigned blockID = PredBlock->getBlockID();
432 if (Visited[blockID]) {
436 if (!Reachable[blockID]) {
438 Visited[blockID] =
true;
439 WorkList.push_back(PredBlock);
452 return BO->getOpcode() != BO_Comma;
459 const Stmt *S = CS->getStmt();
465 if (!T.isTemporaryDtorsBranch()) {
466 const Stmt *S = T.getStmt();
475 static int SrcCmp(
const std::pair<const CFGBlock *, const Stmt *> *p1,
476 const std::pair<const CFGBlock *, const Stmt *> *p2) {
477 if (p1->second->getLocStart() < p2->second->getLocStart())
479 if (p2->second->getLocStart() < p1->second->getLocStart())
490 while (!WorkList.empty()) {
491 const CFGBlock *Block = WorkList.pop_back_val();
499 const Stmt *S = findDeadCode(Block);
504 E = Block->
pred_end(); I != E; ++I) {
517 if (isDeadCodeRoot(Block)) {
518 reportDeadCode(Block, S, CB);
525 DeferredLocs.push_back(std::make_pair(Block, S));
531 if (!DeferredLocs.empty()) {
532 llvm::array_pod_sort(DeferredLocs.begin(), DeferredLocs.end(),
SrcCmp);
533 for (DeferredLocsTy::iterator I = DeferredLocs.begin(),
534 E = DeferredLocs.end(); I != E; ++I) {
538 reportDeadCode(Block, I->second, CB);
551 if (
const Expr *Ex = dyn_cast<Expr>(S))
552 S = Ex->IgnoreParenImpCasts();
555 case Expr::BinaryOperatorClass: {
559 case Expr::UnaryOperatorClass: {
564 case Expr::CompoundAssignOperatorClass: {
570 case Expr::BinaryConditionalOperatorClass:
571 case Expr::ConditionalOperatorClass: {
573 cast<AbstractConditionalOperator>(S);
576 case Expr::MemberExprClass: {
581 case Expr::ArraySubscriptExprClass: {
587 case Expr::CStyleCastExprClass: {
592 case Expr::CXXFunctionalCastExprClass: {
597 case Stmt::CXXTryStmtClass: {
598 return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
600 case Expr::ObjCBridgedCastExprClass: {
611 void DeadCodeScan::reportDeadCode(
const CFGBlock *B,
617 if (isa<BreakStmt>(S)) {
637 if (
const ForStmt *FS = dyn_cast<ForStmt>(LoopTarget)) {
638 const Expr *Inc = FS->getInc();
653 if (
const CFGBlock *PredBlock = PI->getPossiblyUnreachableBlock()) {
654 const Stmt *TermCond =
655 PredBlock->getTerminatorCondition(
false);
670 namespace clang {
namespace reachable_code {
672 void Callback::anchor() { }
675 llvm::BitVector &Reachable) {
689 unsigned numReachable =
714 numReachable += DS.scanBackwards(block, CB);
Represents a function declaration or definition.
static bool isBuiltinUnreachable(const Stmt *S)
AdjacentBlocks::const_iterator const_pred_iterator
static bool isValidDeadStmt(const Stmt *S)
virtual void HandleUnreachable(UnreachableKind UK, SourceLocation L, SourceRange ConditionVal, SourceRange R1, SourceRange R2)=0
succ_iterator succ_begin()
static bool isBuiltinAssumeFalse(const CFGBlock *B, const Stmt *S, ASTContext &C)
Stmt - This represents one statement.
An instance of this object exists for each enum constant that is defined.
Defines the SourceManager interface.
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
static bool isEnumConstant(const Expr *Ex)
unsigned getBlockID() const
static int SrcCmp(const std::pair< const CFGBlock *, const Stmt *> *p1, const std::pair< const CFGBlock *, const Stmt *> *p2)
ParenExpr - This represents a parethesized expression, e.g.
const Stmt * getLoopTarget() const
Stmt * getParent(Stmt *) const
SourceLocation getLParenLoc() const
Stmt * IgnoreImplicit()
Skip past any implicit AST nodes which might surround this statement, such as ExprWithCleanups or Imp...
unsigned succ_size() const
SourceLocation getImmediateMacroCallerLoc(SourceLocation Loc) const
Gets the location of the immediate macro caller, one level up the stack toward the initial macro type...
Represents a variable declaration or definition.
ASTContext & getASTContext() const
static bool isConfigurationValue(const ValueDecl *D, Preprocessor &PP)
Defines the clang::Expr interface and subclasses for C++ expressions.
std::vector< const CFGBlock * >::const_iterator try_block_iterator
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
AnalysisDeclContext contains the context data for the function or method under analysis.
SourceLocation getLocStart() const LLVM_READONLY
SourceLocation getQuestionLoc() const
const LangOptions & getLangOpts() const
AdjacentBlocks::const_iterator const_succ_iterator
ForStmt - This represents a 'for (init;cond;inc)' stmt.
A builtin binary operation expression such as "x + y" or "x <= y".
CFGBlockListTy::iterator iterator
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
static unsigned scanMaybeReachableFromBlock(const CFGBlock *Start, Preprocessor &PP, llvm::BitVector &Reachable)
SourceLocation getOperatorLoc() const
getOperatorLoc - Return the location of the operator.
static bool isDeadReturn(const CFGBlock *B, const Stmt *S)
static bool isTrivialExpression(const Expr *Ex)
Represents a single basic block in a source-level CFG.
static SourceLocation GetUnreachableLoc(const Stmt *S, SourceRange &R1, SourceRange &R2)
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Expr - This represents one expression.
Stmt * getTerminatorCondition(bool StripParens=true)
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
Defines the clang::Preprocessor interface.
ElementList::const_iterator const_iterator
bool isTemporaryDtorsBranch() const
void FindUnreachableCode(AnalysisDeclContext &AC, Preprocessor &PP, Callback &CB)
unsigned ScanReachableFromBlock(const CFGBlock *Start, llvm::BitVector &Reachable)
ScanReachableFromBlock - Mark all blocks reachable from Start.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
SourceLocation getRBracketLoc() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
SourceLocation getMemberLoc() const
getMemberLoc - Return the location of the "member", in X->F, it is the location of 'F'...
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr.cast]), which uses the syntax (Type)expr.
Expr * getLHS()
An array access can be written A[4] or 4[A] (both are equivalent).
reverse_iterator rbegin()
DoStmt - This represents a 'do/while' stmt.
try_block_iterator try_blocks_begin() const
SourceManager & getSourceManager() const
static bool isExpandedFromConfigurationMacro(const Stmt *S, Preprocessor &PP, bool IgnoreYES_NO=false)
Returns true if the statement is expanded from a configuration macro.
Expr * IgnoreCasts() LLVM_READONLY
Ignore casts. Strip off any CastExprs, returning their operand.
CFGTerminator getTerminator()
Encodes a location in the source.
SourceLocation getOperatorLoc() const
Expr * getSubExpr() const
SourceLocation getLocStart() const LLVM_READONLY
static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager &SM)
unsigned getNumBlockIDs() const
Returns the total number of BlockIDs allocated (which start at 0).
static bool isLogicalOp(Opcode Opc)
Optional< T > getAs() const
Convert to the specified CFGElement type, returning None if this CFGElement is not of the desired typ...
CompoundAssignOperator - For compound assignments (e.g.
An Objective-C "bridged" cast expression, which casts between Objective-C pointers and C pointers...
pred_iterator pred_begin()
Dataflow Directional Tag Classes.
CFG::BuildOptions & getCFGBuildOptions()
Return the build options used to construct the CFG.
unsigned pred_size() const
StmtClass getStmtClass() const
static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B, Preprocessor &PP)
Returns true if we should always explore all successors of a block.
SourceLocation getLParenLoc() const
UnreachableKind
Classifications of unreachable code.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
try_block_iterator try_blocks_end() const
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
static unsigned scanFromBlock(const CFGBlock *Start, llvm::BitVector &Reachable, Preprocessor *PP, bool IncludeSometimesUnreachableEdges)
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr.type.conv]).
Represents a top-level expression in a basic block.
Represents CFGBlock terminator statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
StringRef getImmediateMacroName(SourceLocation Loc)
Retrieve the name of the immediate macro expansion.
A reference to a declared variable, function, enum, etc.
static bool isTrivialDoWhile(const CFGBlock *B, const Stmt *S)
A trivial tuple used to represent a source range.
static bool isComparisonOp(Opcode Opc)
This class handles loading and caching of source files into memory.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.