Refactored all logic to run the GRSimpleVals and CFRef checker into a common
code path in the clang driver.

Renamed options --grsimple to -checker-simple and -check-cfref to -checker-cfref.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49500 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp
index 3c10415..4537a7f 100644
--- a/Driver/ASTConsumers.cpp
+++ b/Driver/ASTConsumers.cpp
@@ -22,6 +22,8 @@
 #include "clang/AST/CFG.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Analysis/LocalCheckers.h"
+#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
+#include "clang/Analysis/PathSensitive/GRExprEngine.h"
 #include "llvm/Support/Streams.h"
 #include "llvm/Support/Timer.h"
 #include "llvm/ADT/OwningPtr.h"
@@ -628,26 +630,105 @@
 }
 
 //===----------------------------------------------------------------------===//
+// CheckeRConsumer - Generic Driver for running intra-procedural path-sensitive
+//  analyses.
+
+namespace {
+  
+class CheckerConsumer : public CFGVisitor {
+  Diagnostic &Diags;
+  ASTContext* Ctx;
+  const std::string& HTMLDir;
+  bool Visualize;
+  bool TrimGraph;
+  llvm::OwningPtr<PathDiagnosticClient> PD;
+public:
+  CheckerConsumer(Diagnostic &diags, const std::string& fname,
+            const std::string& htmldir,
+            bool visualize, bool trim)
+    : CFGVisitor(fname), Diags(diags), HTMLDir(htmldir),
+      Visualize(visualize), TrimGraph(trim) {}
+  
+  virtual void Initialize(ASTContext &Context) { Ctx = &Context; }    
+  virtual void VisitCFG(CFG& C, Decl&);
+  virtual bool printFuncDeclStart() { return false; }
+
+  virtual const char* getCheckerName() = 0;
+  virtual GRTransferFuncs* getTransferFunctions() = 0;
+};
+} // end anonymous namespace
+
+void CheckerConsumer::VisitCFG(CFG& C, Decl& CD) {
+  
+  if (Diags.hasErrorOccurred())
+    return;
+  
+  SourceLocation Loc = CD.getLocation();
+  
+  if (!Loc.isFileID() ||
+      Loc.getFileID() != Ctx->getSourceManager().getMainFileID())
+    return;
+  
+  // Lazily create the diagnostic client.
+  
+  if (!HTMLDir.empty() && PD.get() == NULL)
+    PD.reset(CreateHTMLDiagnosticClient(HTMLDir));
+  
+
+  if (!Visualize) {
+    
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(&CD)) {
+      llvm::cerr << "ANALYZE: "
+      << Ctx->getSourceManager().getSourceName(FD->getLocation())
+      << ' '
+      << FD->getIdentifier()->getName()
+      << '\n';
+    }
+    else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(&CD)) {
+      llvm::cerr << "ANALYZE (ObjC Method): "
+      << Ctx->getSourceManager().getSourceName(MD->getLocation())
+      << " '"
+      << MD->getSelector().getName() << "'\n";
+    }
+  }
+  else
+    llvm::cerr << '\n';    
+  
+  // Construct the analysis engine.
+  GRExprEngine Eng(C, CD, *Ctx);
+  
+  // Set base transfer functions.
+  llvm::OwningPtr<GRTransferFuncs> TF(getTransferFunctions());
+  Eng.setTransferFunctions(TF.get());
+  
+  // Execute the worklist algorithm.
+  Eng.ExecuteWorkList();
+  
+  // Display warnings.
+  Eng.EmitWarnings(Diags, PD.get());
+  
+#ifndef NDEBUG
+  if (Visualize) Eng.ViewGraph(TrimGraph);
+#endif
+}
+
+//===----------------------------------------------------------------------===//
 // GRSimpleVals - Perform intra-procedural, path-sensitive constant propagation.
 
 namespace {
-  class GRSimpleValsVisitor : public CFGVisitor {
-    Diagnostic &Diags;
-    ASTContext* Ctx;
-    const std::string& HTMLDir;
-    bool Visualize;
-    bool TrimGraph;
-  public:
-    GRSimpleValsVisitor(Diagnostic &diags, const std::string& fname,
-                        const std::string& htmldir,
-                        bool visualize, bool trim)
-      : CFGVisitor(fname), Diags(diags), HTMLDir(htmldir),
-        Visualize(visualize), TrimGraph(trim) {}
-    
-    virtual void Initialize(ASTContext &Context) { Ctx = &Context; }    
-    virtual void VisitCFG(CFG& C, Decl&);
-    virtual bool printFuncDeclStart() { return false; }
-  };
+class GRSimpleValsVisitor : public CheckerConsumer {
+public:
+  GRSimpleValsVisitor(Diagnostic &diags, const std::string& fname,
+                      const std::string& htmldir,
+                      bool visualize, bool trim)
+  : CheckerConsumer(diags, fname, htmldir, visualize, trim) {}
+
+  virtual const char* getCheckerName() { return "GRSimpleVals"; }
+  
+  virtual GRTransferFuncs* getTransferFunctions() {
+    return MakeGRSimpleValsTF();
+  }
+};
 } // end anonymous namespace
 
 ASTConsumer* clang::CreateGRSimpleVals(Diagnostic &Diags,
@@ -659,92 +740,33 @@
                                  Visualize, TrimGraph);
 }
 
-void GRSimpleValsVisitor::VisitCFG(CFG& C, Decl& CD) {
-  
-  if (Diags.hasErrorOccurred())
-    return;
-  
-  SourceLocation Loc = CD.getLocation();
-
-  if (!Loc.isFileID() ||
-       Loc.getFileID() != Ctx->getSourceManager().getMainFileID())
-    return;
-
-  if (!Visualize) {
-    
-    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(&CD)) {
-      llvm::cerr << "ANALYZE: "
-                 << Ctx->getSourceManager().getSourceName(FD->getLocation())
-                 << ' '
-                 << FD->getIdentifier()->getName()
-                 << '\n';
-    }
-    else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(&CD)) {
-      llvm::cerr << "ANALYZE (ObjC Method): "
-        << Ctx->getSourceManager().getSourceName(MD->getLocation())
-        << " '"
-        << MD->getSelector().getName() << "'\n";
-    }
-
-#if 0
-    llvm::Timer T("GRSimpleVals");
-    T.startTimer();
-    unsigned size = RunGRSimpleVals(C, CD, *Ctx, Diags, NULL, false, false);
-    T.stopTimer();    
-    llvm::cerr << size << ' ' << T.getWallTime() << '\n';
-#else
-    llvm::OwningPtr<PathDiagnosticClient> PD;
-    
-    if (!HTMLDir.empty())
-      PD.reset(CreateHTMLDiagnosticClient(HTMLDir));
-    
-    RunGRSimpleVals(C, CD, *Ctx, Diags, PD.get(), false, false);
-#endif
-  }
-  else {  
-    llvm::cerr << '\n';    
-    RunGRSimpleVals(C, CD, *Ctx, Diags, NULL, Visualize, TrimGraph);
-  }    
-}
-
 
 //===----------------------------------------------------------------------===//
 // Core Foundation Reference Counting Checker
 
 namespace {
-  class CFRefCountCheckerVisitor : public CFGVisitor {
-    Diagnostic &Diags;
-    ASTContext* Ctx;
-    const std::string& HTMLDir;
-    
-  public:
-    CFRefCountCheckerVisitor(Diagnostic &diags, const std::string& fname,
-                             const std::string& htmldir)
-      : CFGVisitor(fname), Diags(diags), HTMLDir(htmldir) {}
-    
-    virtual void Initialize(ASTContext &Context) { Ctx = &Context; }    
-    virtual void VisitCFG(CFG& C, Decl&);
-    virtual bool printFuncDeclStart() { return false; }
-  };
+class CFRefCountCheckerVisitor : public CheckerConsumer {
+public:
+  CFRefCountCheckerVisitor(Diagnostic &diags, const std::string& fname,
+                      const std::string& htmldir,
+                      bool visualize, bool trim)
+  : CheckerConsumer(diags, fname, htmldir, visualize, trim) {}
+  
+  virtual const char* getCheckerName() { return "CFRefCountChecker"; }
+  
+  virtual GRTransferFuncs* getTransferFunctions() {
+    return MakeCFRefCountTF();
+  }
+};
 } // end anonymous namespace
 
-
 ASTConsumer* clang::CreateCFRefChecker(Diagnostic &Diags,
                                        const std::string& FunctionName,
-                                       const std::string& HTMLDir) {
+                                       const std::string& HTMLDir,
+                                       bool Visualize, bool TrimGraph) {
   
-  return new CFRefCountCheckerVisitor(Diags, FunctionName, HTMLDir);
-}
-
-void CFRefCountCheckerVisitor::VisitCFG(CFG& C, Decl& CD) {
-    
-  SourceLocation Loc = CD.getLocation();
-  
-  if (!Loc.isFileID() ||
-      Loc.getFileID() != Ctx->getSourceManager().getMainFileID())
-    return;
-     
-  CheckCFRefCount(C, CD, *Ctx, Diags, NULL);
+  return new CFRefCountCheckerVisitor(Diags, FunctionName, HTMLDir,
+                                      Visualize, TrimGraph);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h
index a38d427..0c0cf58 100644
--- a/Driver/ASTConsumers.h
+++ b/Driver/ASTConsumers.h
@@ -47,9 +47,10 @@
                                 const std::string& HTMLDir,
                                 bool Visualize = false, bool TrimGraph = false);
   
-ASTConsumer* CreateCFRefChecker(Diagnostic &Diags,
-                                const std::string& FunctionName,
-                                const std::string& HTMLDir); 
+ASTConsumer *CreateCFRefChecker(Diagnostic &Diags,
+                                const std::string& Function,
+                                const std::string& HTMLDir,
+                                bool Visualize = false, bool TrimGraph = false);
 
 ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
                                     const std::string& OutFile,
diff --git a/Driver/clang.cpp b/Driver/clang.cpp
index 6c82f19..4c8a352 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -122,11 +122,9 @@
                         "Flag warnings of stores to dead variables."),
              clEnumValN(WarnUninitVals, "warn-uninit-values",
                         "Flag warnings of uses of unitialized variables."),
-             clEnumValN(AnalysisGRSimpleVals, "grsimple",
+             clEnumValN(AnalysisGRSimpleVals, "checker-simple",
                         "Perform path-sensitive constant propagation."),
-             clEnumValN(AnalysisGRSimpleValsView, "grsimple-view",
-                        "View results of path-sensitive constant propagation."),
-             clEnumValN(CheckerCFRef, "check-cfref",
+             clEnumValN(CheckerCFRef, "checker-cfref",
                         "Run the Core Foundation reference count checker."),
              clEnumValN(TestSerialization, "test-pickling",
                         "Run prototype serialization code."),
@@ -153,6 +151,10 @@
 VerifyDiagnostics("verify",
                   llvm::cl::desc("Verify emitted diagnostics and warnings."));
 
+static llvm::cl::opt<bool>
+VisualizeEG("visualize-egraph",
+            llvm::cl::desc("Display static analysis Exploded Graph."));
+
 static llvm::cl::opt<std::string>
 HTMLDiag("html-diags",
          llvm::cl::desc("Generate HTML to report diagnostics"),
@@ -480,10 +482,9 @@
                 llvm::cl::desc("Run analysis on specific function."));
 
 static llvm::cl::opt<bool>
-TrimGraph("trim-path-graph",
+TrimGraph("trim-egraph",
       llvm::cl::desc("Only show error-related paths in the analysis graph."));
 
-
 //===----------------------------------------------------------------------===//
 // Target Triple Processing.
 //===----------------------------------------------------------------------===//
@@ -1052,14 +1053,12 @@
       return CreateUnitValsChecker(Diag);
       
     case AnalysisGRSimpleVals:
-      return CreateGRSimpleVals(Diag, AnalyzeSpecificFunction, OutputFile);
-      
-    case AnalysisGRSimpleValsView:
       return CreateGRSimpleVals(Diag, AnalyzeSpecificFunction, OutputFile,
-                                true, TrimGraph);
+                                VisualizeEG, TrimGraph);
       
     case CheckerCFRef:
-      return CreateCFRefChecker(Diag, AnalyzeSpecificFunction, OutputFile);
+      return CreateCFRefChecker(Diag, AnalyzeSpecificFunction, OutputFile,
+                                VisualizeEG, TrimGraph);
       
     case TestSerialization:
       return CreateSerializationTest(Diag, FileMgr, LangOpts);
diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h
index 00fb06e..96fd588 100644
--- a/include/clang/Analysis/LocalCheckers.h
+++ b/include/clang/Analysis/LocalCheckers.h
@@ -22,19 +22,16 @@
 class Diagnostic;
 class ASTContext;
 class PathDiagnosticClient;
+class GRTransferFuncs;
 
 void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags); 
   
 void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
                               bool FullUninitTaint=false);
   
-void CheckCFRefCount(CFG& cfg, Decl& CodeDecl, ASTContext& Ctx,
-                     Diagnostic& Diag, PathDiagnosticClient* PD);
+GRTransferFuncs* MakeGRSimpleValsTF();
+GRTransferFuncs* MakeCFRefCountTF();
   
-unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx,
-                         Diagnostic& Diag, PathDiagnosticClient* PD,
-                         bool Visualize, bool TrimGraph);
-
 } // end namespace clang
 
 #endif
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index efd4821..85c8e86 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -874,22 +874,7 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Driver for the CFRefCount Checker.
+// Transfer function creation for external clients.
 //===----------------------------------------------------------------------===//
 
-namespace clang {
-  
-void CheckCFRefCount(CFG& cfg, Decl& CD, ASTContext& Ctx,
-                     Diagnostic& Diag, PathDiagnosticClient* PD) {
-  
-  if (Diag.hasErrorOccurred())
-    return;
-  
-  GRExprEngine Eng(cfg, CD, Ctx);
-  CFRefCount TF;
-  Eng.setTransferFunctions(TF);
-  Eng.ExecuteWorkList();
-  Eng.EmitWarnings(Diag, PD);
-}
-
-} // end clang namespace
+GRTransferFuncs* clang::MakeCFRefCountTF() { return new CFRefCount(); }  
diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp
index 960476d..c350ab9 100644
--- a/lib/Analysis/GRSimpleVals.cpp
+++ b/lib/Analysis/GRSimpleVals.cpp
@@ -19,6 +19,7 @@
 #include "clang/Analysis/PathDiagnostic.h"
 #include "clang/Analysis/PathSensitive/ValueState.h"
 #include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/LocalCheckers.h"
 #include "llvm/Support/Compiler.h"
 #include <sstream>
 
@@ -310,36 +311,10 @@
 }
 
 //===----------------------------------------------------------------------===//
-// Analysis Driver.
+// Transfer Function creation for External clients.
 //===----------------------------------------------------------------------===//
 
-namespace clang {
-  
-unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx,
-                         Diagnostic& Diag, PathDiagnosticClient* PD,
-                         bool Visualize, bool TrimGraph) {
-
-  // Construct the analysis engine.
-  GRExprEngine Eng(cfg, CD, Ctx);
-  
-  // Set base transfer functions.
-  GRSimpleVals GRSV;
-  Eng.setTransferFunctions(GRSV);
-  
-  // Execute the worklist algorithm.
-  Eng.ExecuteWorkList();
-  
-  // Display warnings.
-  Eng.EmitWarnings(Diag, PD);
-  
-#ifndef NDEBUG
-  if (Visualize) Eng.ViewGraph(TrimGraph);
-#endif
-  
-  return Eng.getGraph().size();
-}
-  
-} // end clang namespace
+GRTransferFuncs* clang::MakeGRSimpleValsTF() { return new GRSimpleVals(); }  
 
 //===----------------------------------------------------------------------===//
 // Transfer function for Casts.
diff --git a/test/Analysis-Apple/NSString.m b/test/Analysis-Apple/NSString.m
index d562a2b..7662766 100644
--- a/test/Analysis-Apple/NSString.m
+++ b/test/Analysis-Apple/NSString.m
@@ -1,4 +1,4 @@
-// RUN: clang -grsimple -verify %s
+// RUN: clang -checker-simple -verify %s
 
 #include <Foundation/NSString.h>
 #include <Foundation/NSObjCRuntime.h>
diff --git a/test/Analysis-Apple/uninit-msg-expr.m b/test/Analysis-Apple/uninit-msg-expr.m
index 9ce4589..b7ff790 100644
--- a/test/Analysis-Apple/uninit-msg-expr.m
+++ b/test/Analysis-Apple/uninit-msg-expr.m
@@ -1,4 +1,4 @@
-// RUN: clang -grsimple -verify %s
+// RUN: clang -checker-simple -verify %s
 
 #include <Foundation/NSString.h>
 #include <Foundation/NSArray.h>
diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c
index c0a2606..c73a038 100644
--- a/test/Analysis/null-deref-ps.c
+++ b/test/Analysis/null-deref-ps.c
@@ -1,4 +1,4 @@
-// RUN: clang -grsimple -verify %s
+// RUN: clang -checker-simple -verify %s
 
 void f1(int *p) {  
   if (p) *p = 1;
diff --git a/test/Analysis/stack-addr-ps.c b/test/Analysis/stack-addr-ps.c
index 55c542c..c59df09 100644
--- a/test/Analysis/stack-addr-ps.c
+++ b/test/Analysis/stack-addr-ps.c
@@ -1,4 +1,4 @@
-// RUN: clang -grsimple -verify %s
+// RUN: clang -checker-simple -verify %s
 
 int* f1() {
   int x = 0;