14 #include "llvm/ADT/StringSwitch.h"
16 using namespace clang;
20 class ExprInspectionChecker :
public Checker<eval::Call, check::DeadSymbols> {
21 mutable std::unique_ptr<BugType> BT;
29 typedef void (ExprInspectionChecker::*FnCheck)(
const CallExpr *,
44 FnCheck Handler = llvm::StringSwitch<FnCheck>(C.getCalleeName(CE))
45 .Case(
"clang_analyzer_eval", &ExprInspectionChecker::analyzerEval)
46 .Case(
"clang_analyzer_checkInlined",
47 &ExprInspectionChecker::analyzerCheckInlined)
48 .Case(
"clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
49 .Case(
"clang_analyzer_warnIfReached",
50 &ExprInspectionChecker::analyzerWarnIfReached)
51 .Case(
"clang_analyzer_warnOnDeadSymbol",
52 &ExprInspectionChecker::analyzerWarnOnDeadSymbol)
58 (this->*Handler)(CE, C);
65 return "Missing assertion argument";
72 SVal AssertionVal = State->getSVal(Assertion, LC);
78 std::tie(StTrue, StFalse) =
90 llvm_unreachable(
"Invalid constraint; neither true or false.");
94 void ExprInspectionChecker::analyzerEval(
const CallExpr *CE,
104 BT.reset(
new BugType(
this,
"Checking analyzer assumptions",
"debug"));
113 void ExprInspectionChecker::analyzerWarnIfReached(
const CallExpr *CE,
117 BT.reset(
new BugType(
this,
"Checking analyzer assumptions",
"debug"));
122 C.
emitReport(llvm::make_unique<BugReport>(*BT,
"REACHABLE", N));
125 void ExprInspectionChecker::analyzerCheckInlined(
const CallExpr *CE,
138 BT.reset(
new BugType(
this,
"Checking analyzer assumptions",
"debug"));
147 void ExprInspectionChecker::analyzerWarnOnDeadSymbol(
const CallExpr *CE,
157 State = State->add<MarkedSymbols>(Sym);
161 void ExprInspectionChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
164 const MarkedSymbolsTy &Syms = State->get<MarkedSymbols>();
165 for (
auto I = Syms.begin(),
E = Syms.end();
I !=
E; ++
I) {
167 if (!SymReaper.
isDead(Sym))
171 BT.reset(
new BugType(
this,
"Checking analyzer assumptions",
"debug"));
177 C.
emitReport(llvm::make_unique<BugReport>(*BT,
"SYMBOL DEAD", N));
182 void ExprInspectionChecker::analyzerCrash(
const CallExpr *CE,
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
#define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set of type NameTy, suitable for placement into the ProgramState.
detail::InMemoryDirectory::const_iterator I
const LocationContext * getLocationContext() const
bool isDead(SymbolRef sym) const
Returns whether or not a symbol has been confirmed dead.
Expr - This represents one expression.
const ProgramStateRef & getState() const
const ProgramStateRef & getState() const
ExplodedNode * generateNonFatalErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
CHECKER * registerChecker()
Used to register checkers.
const StackFrameContext * getCurrentStackFrame() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
A class responsible for cleaning up unused symbols.
const LocationContext * getParent() const
static const char * getArgumentValueString(const CallExpr *CE, CheckerContext &C)
detail::InMemoryDirectory::const_iterator E
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.