27 #include "llvm/ADT/SmallSet.h"
31 #define DEFAULT_CFGBLOCKS 256
33 using namespace clang;
37 class UnreachableCodeChecker :
public Checker<check::EndAnalysis> {
42 typedef llvm::SmallSet<unsigned, DEFAULT_CFGBLOCKS> CFGBlocksSet;
44 static inline const Stmt *getUnreachableStmt(
const CFGBlock *CB);
45 static void FindUnreachableEntryPoints(
const CFGBlock *CB,
46 CFGBlocksSet &reachable,
47 CFGBlocksSet &visited);
49 static inline bool isEmptyCFGBlock(
const CFGBlock *CB);
53 void UnreachableCodeChecker::checkEndAnalysis(
ExplodedGraph &G,
56 CFGBlocksSet reachable, visited;
61 const Decl *D =
nullptr;
96 if (FD->isTemplateInstantiation())
107 if (isEmptyCFGBlock(CB))
112 FindUnreachableEntryPoints(CB, reachable, visited);
119 if (CB->
size() > 0 && isInvalidPath(CB, *PM))
127 if (label->getStmtClass() == Stmt::DefaultStmtClass)
134 bool foundUnreachable =
false;
138 if (
const CallExpr *CE = dyn_cast<CallExpr>(
S->getStmt())) {
139 if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable) {
140 foundUnreachable =
true;
145 if (foundUnreachable)
153 if (
const Stmt *
S = getUnreachableStmt(CB)) {
154 SR =
S->getSourceRange();
169 "This statement is never executed", DL, SR);
174 void UnreachableCodeChecker::FindUnreachableEntryPoints(
const CFGBlock *CB,
175 CFGBlocksSet &reachable,
176 CFGBlocksSet &visited) {
184 if (!reachable.count((*I)->getBlockID())) {
188 if (!visited.count((*I)->getBlockID()))
190 FindUnreachableEntryPoints(*I, reachable, visited);
196 const Stmt *UnreachableCodeChecker::getUnreachableStmt(
const CFGBlock *CB) {
212 bool UnreachableCodeChecker::isInvalidPath(
const CFGBlock *CB,
240 || containsStmt<UnaryExprOrTypeTraitExpr>(cond))
247 bool UnreachableCodeChecker::isEmptyCFGBlock(
const CFGBlock *CB) {
bool containsStaticLocal(const Stmt *S)
Defines the SourceManager interface.
virtual bool inTopFrame() const
Return true if the current LocationContext has no caller context.
bool containsBuiltinOffsetOf(const Stmt *S)
FullSourceLoc asLocation() const
AnalysisDeclContext * getAnalysisDeclContext() const
unsigned pred_size() const
ElementList::const_iterator const_iterator
const Decl * getDecl() const
Stmt * getTerminatorCondition(bool StripParens=true)
ParentMap & getParentMap() const
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
AdjacentBlocks::const_iterator const_pred_iterator
unsigned getBlockID() const
bool hasWorkRemaining() const
CFG * getUnoptimizedCFG()
Return a version of the CFG without any edges pruned.
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. The SourceManager can decode this to get at the full include stack...
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
node_iterator nodes_end()
pred_iterator pred_begin()
const LocationContext * getLocationContext() const
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
SourceManager & getSourceManager()
bool containsMacro(const Stmt *S)
AllNodesTy::iterator node_iterator
bool isInExternCSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in an "extern C" system header.
A trivial tuple used to represent a source range.
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.