27 #include "llvm/ADT/SmallSet.h" 29 using namespace clang;
33 class UnreachableCodeChecker :
public Checker<check::EndAnalysis> {
38 typedef llvm::SmallSet<unsigned, 32> CFGBlocksSet;
40 static inline const Stmt *getUnreachableStmt(
const CFGBlock *CB);
41 static void FindUnreachableEntryPoints(
const CFGBlock *CB,
42 CFGBlocksSet &reachable,
43 CFGBlocksSet &visited);
45 static inline bool isEmptyCFGBlock(
const CFGBlock *CB);
49 void UnreachableCodeChecker::checkEndAnalysis(
ExplodedGraph &G,
52 CFGBlocksSet reachable, visited;
57 const Decl *D =
nullptr;
92 if (FD->isTemplateInstantiation())
103 if (isEmptyCFGBlock(CB))
108 FindUnreachableEntryPoints(CB, reachable, visited);
115 if (isInvalidPath(CB, *PM))
123 if (label->getStmtClass() == Stmt::DefaultStmtClass)
130 bool foundUnreachable =
false;
134 if (
const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
135 if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable) {
136 foundUnreachable =
true;
141 if (foundUnreachable)
149 if (
const Stmt *S = getUnreachableStmt(CB)) {
152 if (S->getLocStart().isMacroID())
153 if (
const auto *I = dyn_cast<IntegerLiteral>(S))
154 if (I->getValue() == 0ULL)
158 SR = S->getSourceRange();
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) {
An instance of this class is created to represent 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)
virtual bool inTopFrame() const
Return true if the current LocationContext has no caller context.
CFGBlockListTy::const_iterator const_iterator
CFGBlock - Represents a single basic block in a source-level CFG.
Stmt * getTerminatorCondition(bool StripParens=true)
CFG - 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.
BugReporter is a utility class for generating PathDiagnostics for analysis.
CFGTerminator getTerminator()
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
CHECKER * registerChecker()
Used to register checkers.
node_iterator nodes_begin()
Encodes a location in the source.
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
node_iterator nodes_end()
const Decl * getDecl() const
FullSourceLoc asLocation() 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
bool hasWorkRemaining() const
const LocationContext * getLocationContext() const
SourceManager & getSourceManager()
bool containsMacro(const Stmt *S)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
AllNodesTy::iterator node_iterator
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.