26 #include "llvm/ADT/SmallSet.h" 28 using namespace clang;
32 class UnreachableCodeChecker :
public Checker<check::EndAnalysis> {
34 void checkEndAnalysis(ExplodedGraph &G, BugReporter &B,
35 ExprEngine &Eng)
const;
37 typedef llvm::SmallSet<unsigned, 32> CFGBlocksSet;
39 static inline const Stmt *getUnreachableStmt(
const CFGBlock *CB);
40 static void FindUnreachableEntryPoints(
const CFGBlock *CB,
41 CFGBlocksSet &reachable,
42 CFGBlocksSet &visited);
44 static inline bool isEmptyCFGBlock(
const CFGBlock *CB);
48 void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
50 ExprEngine &Eng)
const {
51 CFGBlocksSet reachable, visited;
53 if (Eng.hasWorkRemaining())
56 const Decl *D =
nullptr;
91 if (FD->isTemplateInstantiation())
102 if (isEmptyCFGBlock(CB))
107 FindUnreachableEntryPoints(CB, reachable, visited);
114 if (isInvalidPath(CB, *PM))
122 if (label->getStmtClass() == Stmt::DefaultStmtClass)
129 bool foundUnreachable =
false;
133 if (
const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
134 if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable ||
135 CE->isBuiltinAssumeFalse(Eng.getContext())) {
136 foundUnreachable =
true;
141 if (foundUnreachable)
147 PathDiagnosticLocation DL;
149 if (
const Stmt *S = getUnreachableStmt(CB)) {
152 if (S->getBeginLoc().isMacroID())
153 if (
const auto *I = dyn_cast<IntegerLiteral>(S))
154 if (I->getValue() == 0ULL)
158 SR = S->getSourceRange();
160 SL = DL.asLocation();
172 B.EmitBasicReport(D,
this,
"Unreachable code",
"Dead code",
173 "This statement is never executed", DL, SR);
178 void UnreachableCodeChecker::FindUnreachableEntryPoints(
const CFGBlock *CB,
179 CFGBlocksSet &reachable,
180 CFGBlocksSet &visited) {
188 if (!reachable.count((*I)->getBlockID())) {
192 if (!visited.count((*I)->getBlockID()))
194 FindUnreachableEntryPoints(*I, reachable, visited);
200 const Stmt *UnreachableCodeChecker::getUnreachableStmt(
const CFGBlock *CB) {
203 if (!isa<DeclStmt>(S->getStmt()))
218 bool UnreachableCodeChecker::isInvalidPath(
const CFGBlock *CB,
246 containsStmt<UnaryExprOrTypeTraitExpr>(cond);
250 bool UnreachableCodeChecker::isEmptyCFGBlock(
const CFGBlock *CB) {
256 void ento::registerUnreachableCodeChecker(CheckerManager &mgr) {
257 mgr.registerChecker<UnreachableCodeChecker>();
260 bool ento::shouldRegisterUnreachableCodeChecker(
const LangOptions &LO) {
Represents a function declaration or definition.
bool containsStaticLocal(const Stmt *S)
AdjacentBlocks::const_iterator const_pred_iterator
Stmt - This represents one statement.
Defines the SourceManager interface.
unsigned getBlockID() const
Decl - This represents one declaration (or definition), e.g.
Stmt * getParent(Stmt *) const
bool containsBuiltinOffsetOf(const Stmt *S)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
virtual bool inTopFrame() const
Return true if the current LocationContext has no caller context.
CFGBlockListTy::const_iterator const_iterator
Represents a single basic block in a source-level CFG.
AllNodesTy::iterator node_iterator
Stmt * getTerminatorCondition(bool StripParens=true)
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
ElementList::const_iterator const_iterator
ParentMap & getParentMap() const
CFG * getUnoptimizedCFG()
Return a version of the CFG without any edges pruned.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
Encodes a location in the source.
const Decl * getDecl() const
bool isInExternCSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in an "extern C" system header.
pred_iterator pred_begin()
Dataflow Directional Tag Classes.
unsigned pred_size() const
Stmt * getTerminatorStmt()
const LocationContext * getLocationContext() const
bool containsMacro(const Stmt *S)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A trivial tuple used to represent a source range.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
AnalysisDeclContext * getAnalysisDeclContext() const
bool containsEnum(const Stmt *S)
This class handles loading and caching of source files into memory.
Defines enum values for all the target-independent builtin functions.