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);
}
//===----------------------------------------------------------------------===//