summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp62
1 files changed, 55 insertions, 7 deletions
diff --git a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
index 7dc0a87..8f6c20a 100644
--- a/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
+++ b/contrib/llvm/tools/clang/lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp
@@ -17,22 +17,26 @@ using namespace clang;
using namespace ento;
namespace {
-class ExprInspectionChecker : public Checker< eval::Call > {
+class ExprInspectionChecker : public Checker<eval::Call, check::DeadSymbols> {
mutable std::unique_ptr<BugType> BT;
void analyzerEval(const CallExpr *CE, CheckerContext &C) const;
void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const;
void analyzerWarnIfReached(const CallExpr *CE, CheckerContext &C) const;
void analyzerCrash(const CallExpr *CE, CheckerContext &C) const;
+ void analyzerWarnOnDeadSymbol(const CallExpr *CE, CheckerContext &C) const;
typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
CheckerContext &C) const;
public:
bool evalCall(const CallExpr *CE, CheckerContext &C) const;
+ void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
};
}
+REGISTER_SET_WITH_PROGRAMSTATE(MarkedSymbols, const void *)
+
bool ExprInspectionChecker::evalCall(const CallExpr *CE,
CheckerContext &C) const {
// These checks should have no effect on the surrounding environment
@@ -42,7 +46,10 @@ bool ExprInspectionChecker::evalCall(const CallExpr *CE,
.Case("clang_analyzer_checkInlined",
&ExprInspectionChecker::analyzerCheckInlined)
.Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
- .Case("clang_analyzer_warnIfReached", &ExprInspectionChecker::analyzerWarnIfReached)
+ .Case("clang_analyzer_warnIfReached",
+ &ExprInspectionChecker::analyzerWarnIfReached)
+ .Case("clang_analyzer_warnOnDeadSymbol",
+ &ExprInspectionChecker::analyzerWarnOnDeadSymbol)
.Default(nullptr);
if (!Handler)
@@ -86,8 +93,7 @@ static const char *getArgumentValueString(const CallExpr *CE,
void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
CheckerContext &C) const {
- ExplodedNode *N = C.getPredecessor();
- const LocationContext *LC = N->getLocationContext();
+ const LocationContext *LC = C.getPredecessor()->getLocationContext();
// A specific instantiation of an inlined function may have more constrained
// values than can generally be assumed. Skip the check.
@@ -97,24 +103,28 @@ void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
C.emitReport(
llvm::make_unique<BugReport>(*BT, getArgumentValueString(CE, C), N));
}
void ExprInspectionChecker::analyzerWarnIfReached(const CallExpr *CE,
CheckerContext &C) const {
- ExplodedNode *N = C.getPredecessor();
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
C.emitReport(llvm::make_unique<BugReport>(*BT, "REACHABLE", N));
}
void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
CheckerContext &C) const {
- ExplodedNode *N = C.getPredecessor();
- const LocationContext *LC = N->getLocationContext();
+ const LocationContext *LC = C.getPredecessor()->getLocationContext();
// An inlined function could conceivably also be analyzed as a top-level
// function. We ignore this case and only emit a message (TRUE or FALSE)
@@ -127,10 +137,48 @@ void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
if (!BT)
BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
C.emitReport(
llvm::make_unique<BugReport>(*BT, getArgumentValueString(CE, C), N));
}
+void ExprInspectionChecker::analyzerWarnOnDeadSymbol(const CallExpr *CE,
+ CheckerContext &C) const {
+ if (CE->getNumArgs() == 0)
+ return;
+ SVal Val = C.getSVal(CE->getArg(0));
+ SymbolRef Sym = Val.getAsSymbol();
+ if (!Sym)
+ return;
+
+ ProgramStateRef State = C.getState();
+ State = State->add<MarkedSymbols>(Sym);
+ C.addTransition(State);
+}
+
+void ExprInspectionChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+ CheckerContext &C) const {
+ ProgramStateRef State = C.getState();
+ const MarkedSymbolsTy &Syms = State->get<MarkedSymbols>();
+ for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
+ SymbolRef Sym = static_cast<SymbolRef>(*I);
+ if (!SymReaper.isDead(Sym))
+ continue;
+
+ if (!BT)
+ BT.reset(new BugType(this, "Checking analyzer assumptions", "debug"));
+
+ ExplodedNode *N = C.generateNonFatalErrorNode();
+ if (!N)
+ return;
+
+ C.emitReport(llvm::make_unique<BugReport>(*BT, "SYMBOL DEAD", N));
+ C.addTransition(State->remove<MarkedSymbols>(Sym), N);
+ }
+}
+
void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,
CheckerContext &C) const {
LLVM_BUILTIN_TRAP;
OpenPOWER on IntegriCloud