Refactor undefined argument checking into a Checker.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80417 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index de0209a..d66dfff 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -1626,30 +1626,7 @@
           default:
             break;
         }
-    }
-
-    // Check any arguments passed-by-value against being undefined.
-
-    bool badArg = false;
-    
-    for (CallExpr::arg_iterator I = CE->arg_begin(), E = CE->arg_end();
-         I != E; ++I) {
-
-      if (GetState(*DI)->getSVal(*I).isUndef()) {        
-        ExplodedNode* N = Builder->generateNode(CE, GetState(*DI), *DI);
-      
-        if (N) {
-          N->markAsSink();
-          UndefArgs[N] = *I;
-        }
-        
-        badArg = true;
-        break;
-      }
-    }
-    
-    if (badArg)
-      continue;        
+    }       
 
     // Dispatch to the plug-in transfer function.      
     
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index 1b2fd1c..35ca0c5 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -245,7 +245,12 @@
                    ExplodedNode *n, const Stmt *arg)
   : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}  
   
-  const Stmt *getArg() const { return Arg; }    
+  const Stmt *getArg() const { return Arg; }  
+
+  void registerInitialVisitors(BugReporterContext& BRC,
+                               const ExplodedNode* N) {
+    registerTrackNullOrUndefValue(BRC, getArg(), N);
+  }    
 };
 
 class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
@@ -629,6 +634,44 @@
 };
 } // end anonymous namespace
 
+// Undefined arguments checking.
+namespace {
+class VISIBILITY_HIDDEN CheckUndefinedArg 
+  : public CheckerVisitor<CheckUndefinedArg> {
+
+  BugType *BT;
+
+public:
+  CheckUndefinedArg() : BT(0) {}
+  ~CheckUndefinedArg() {}
+
+  const void *getTag() {
+    static int x = 0;
+    return &x;
+  }
+
+  void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
+};
+
+void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
+  for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
+       I != E; ++I) {
+    if (C.getState()->getSVal(*I).isUndef()) {
+      if (ExplodedNode *ErrorNode = C.generateNode(CE, C.getState(), true)) {
+        if (!BT)
+          BT = new BugType("Uninitialized argument.", "Logic Errors.");
+        // Generate a report for this bug.
+        ArgReport *Report = new ArgReport(*BT, 
+                     "Pass-by-value argument in function call is undefined.",
+                                          ErrorNode, *I);
+        Report->addRange((*I)->getSourceRange());
+        C.EmitReport(Report);
+      }
+    }
+  }
+}
+
+}
 //===----------------------------------------------------------------------===//
 // Check registration.
 //===----------------------------------------------------------------------===//
@@ -647,7 +690,6 @@
   BR.Register(new BadCall(this));
   BR.Register(new RetStack(this));
   BR.Register(new RetUndef(this));
-  BR.Register(new BadArg(this));
   BR.Register(new BadMsgExprArg(this));
   BR.Register(new BadReceiver(this));
   BR.Register(new OutOfBoundMemoryAccess(this));
@@ -661,4 +703,5 @@
   // automatically.  Note that the check itself is owned by the GRExprEngine
   // object.
   registerCheck(new CheckAttrNonNull());
+  registerCheck(new CheckUndefinedArg());
 }