15 #include "llvm/ADT/StringSwitch.h"
17 using namespace clang;
21 class ExprInspectionChecker :
public Checker<eval::Call, check::DeadSymbols> {
22 mutable std::unique_ptr<BugType> BT;
32 typedef void (ExprInspectionChecker::*FnCheck)(
const CallExpr *,
49 FnCheck Handler = llvm::StringSwitch<FnCheck>(C.getCalleeName(CE))
50 .Case(
"clang_analyzer_eval", &ExprInspectionChecker::analyzerEval)
51 .Case(
"clang_analyzer_checkInlined",
52 &ExprInspectionChecker::analyzerCheckInlined)
53 .Case(
"clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
54 .Case(
"clang_analyzer_warnIfReached",
55 &ExprInspectionChecker::analyzerWarnIfReached)
56 .Case(
"clang_analyzer_warnOnDeadSymbol",
57 &ExprInspectionChecker::analyzerWarnOnDeadSymbol)
58 .Case(
"clang_analyzer_explain", &ExprInspectionChecker::analyzerExplain)
59 .Case(
"clang_analyzer_getExtent", &ExprInspectionChecker::analyzerGetExtent)
65 (this->*Handler)(CE, C);
72 return "Missing assertion argument";
79 SVal AssertionVal = State->getSVal(Assertion, LC);
85 std::tie(StTrue, StFalse) =
97 llvm_unreachable(
"Invalid constraint; neither true or false.");
101 void ExprInspectionChecker::reportBug(llvm::StringRef Msg,
104 BT.reset(
new BugType(
this,
"Checking analyzer assumptions",
"debug"));
110 C.
emitReport(llvm::make_unique<BugReport>(*BT, Msg, N));
113 void ExprInspectionChecker::analyzerEval(
const CallExpr *CE,
125 void ExprInspectionChecker::analyzerWarnIfReached(
const CallExpr *CE,
127 reportBug(
"REACHABLE", C);
130 void ExprInspectionChecker::analyzerCheckInlined(
const CallExpr *CE,
145 void ExprInspectionChecker::analyzerExplain(
const CallExpr *CE,
148 reportBug(
"Missing argument for explaining", C);
152 reportBug(Ex.Visit(V), C);
155 void ExprInspectionChecker::analyzerGetExtent(
const CallExpr *CE,
158 reportBug(
"Missing region for obtaining extent", C);
160 auto MR = dyn_cast_or_null<SubRegion>(C.
getSVal(CE->
getArg(0)).getAsRegion());
162 reportBug(
"Obtaining extent of a non-region", C);
170 void ExprInspectionChecker::analyzerWarnOnDeadSymbol(
const CallExpr *CE,
180 State = State->add<MarkedSymbols>(Sym);
184 void ExprInspectionChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
187 const MarkedSymbolsTy &Syms = State->get<MarkedSymbols>();
188 for (
auto I = Syms.begin(),
E = Syms.end();
I !=
E; ++
I) {
190 if (!SymReaper.
isDead(Sym))
193 reportBug(
"SYMBOL DEAD", C);
194 State = State->remove<MarkedSymbols>(Sym);
199 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
ASTContext & getASTContext()
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.
SValBuilder & getSValBuilder()
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.
const LocationContext * getLocationContext() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.