Refactor bad callee check into a Checker.
Now bad callee is checked as a PreVisit to the CallExpr.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80771 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/BugReporterVisitors.cpp b/lib/Analysis/BugReporterVisitors.cpp
index 5c31066..fce31e7 100644
--- a/lib/Analysis/BugReporterVisitors.cpp
+++ b/lib/Analysis/BugReporterVisitors.cpp
@@ -63,7 +63,8 @@
const Stmt*
clang::bugreporter::GetCalleeExpr(const ExplodedNode *N) {
- const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
+ // Callee is checked as a PreVisit to the CallExpr.
+ const Stmt *S = N->getLocationAs<PreStmt>()->getStmt();
if (const CallExpr *CE = dyn_cast<CallExpr>(S))
return CE->getCallee();
return NULL;
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index d0b6bbf..a6b580b 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -1493,20 +1493,7 @@
// FIXME: Add support for symbolic function calls (calls involving
// function pointer values that are symbolic).
-
- // Check for undefined control-flow or calls to NULL.
-
- if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
- ExplodedNode* N = Builder->generateNode(CE, state, *DI);
-
- if (N) {
- N->markAsSink();
- BadCalls.insert(N);
- }
-
- continue;
- }
-
+
// Check for the "noreturn" attribute.
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index 91b7cf3..4c6371c 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -70,7 +70,7 @@
const std::string &getDescription() const { return desc; }
- virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) = 0;
+ virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
@@ -220,14 +220,10 @@
class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
public:
- BadCall(GRExprEngine *eng)
+ BadCall(GRExprEngine *eng = 0)
: BuiltinBug(eng, "Invalid function call",
"Called function pointer is a null or undefined pointer value") {}
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
- }
-
void registerInitialVisitors(BugReporterContext& BRC,
const ExplodedNode* N,
BuiltinBugReport *R) {
@@ -252,18 +248,12 @@
class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
public:
- BadArg() : BuiltinBug(0, "Uninitialized argument",
- "Pass-by-value argument in function call is undefined.") {}
-
- BadArg(GRExprEngine* eng) : BuiltinBug(eng,"Uninitialized argument",
+ BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
"Pass-by-value argument in function call is undefined.") {}
BadArg(GRExprEngine* eng, const char* d)
: BuiltinBug(eng,"Uninitialized argument", d) {}
- void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
- }
-
void registerInitialVisitors(BugReporterContext& BRC,
const ExplodedNode* N,
BuiltinBugReport *R) {
@@ -662,6 +652,34 @@
}
}
+class VISIBILITY_HIDDEN CheckBadCall : public CheckerVisitor<CheckBadCall> {
+ BadCall *BT;
+
+public:
+ CheckBadCall() : BT(0) {}
+ ~CheckBadCall() {}
+
+ const void *getTag() {
+ static int x = 0;
+ return &x;
+ }
+
+ void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
+ const Expr *Callee = CE->getCallee()->IgnoreParens();
+ SVal L = C.getState()->getSVal(Callee);
+
+ if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
+ if (ExplodedNode *N = C.generateNode(CE, C.getState(), true)) {
+ if (!BT)
+ BT = new BadCall();
+ C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
+ }
+ }
+}
+
}
//===----------------------------------------------------------------------===//
// Check registration.
@@ -678,7 +696,6 @@
BR.Register(new UndefBranch(this));
BR.Register(new DivZero(this));
BR.Register(new UndefResult(this));
- BR.Register(new BadCall(this));
BR.Register(new RetStack(this));
BR.Register(new RetUndef(this));
BR.Register(new BadMsgExprArg(this));
@@ -695,4 +712,5 @@
// object.
registerCheck(new CheckAttrNonNull());
registerCheck(new CheckUndefinedArg());
+ registerCheck(new CheckBadCall());
}