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());
 }