alexfh created this revision.
alexfh added a reviewer: george.karpenkov.
Herald added a subscriber: a.sidorin.

Add an extension point to allow registration of statically-linked Clang Static
Analyzer checkers that are not a part of the Clang tree. This extension point
employs the mechanism used when checkers are registered from dynamically loaded
plugins.


Repository:
  rC Clang

https://reviews.llvm.org/D45718

Files:
  include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
  include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
  lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
  lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp

Index: lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
===================================================================
--- lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -111,16 +111,21 @@
   return checkerOpts;
 }
 
-std::unique_ptr<CheckerManager>
-ento::createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
-                           ArrayRef<std::string> plugins,
-                           DiagnosticsEngine &diags) {
+std::unique_ptr<CheckerManager> ento::createCheckerManager(
+    AnalyzerOptions &opts, const LangOptions &langOpts,
+    ArrayRef<std::string> plugins,
+    ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
+    DiagnosticsEngine &diags) {
   std::unique_ptr<CheckerManager> checkerMgr(
       new CheckerManager(langOpts, opts));
 
   SmallVector<CheckerOptInfo, 8> checkerOpts = getCheckerOptList(opts);
 
   ClangCheckerRegistry allCheckers(plugins, &diags);
+
+  for (const auto &Fn : checkerRegistrationFns)
+    Fn(allCheckers);
+
   allCheckers.initializeManager(*checkerMgr, checkerOpts);
   allCheckers.validateCheckerOptions(opts, diags);
   checkerMgr->finishedCheckerRegistration();
Index: lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
===================================================================
--- lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -164,6 +164,8 @@
   /// Bug Reporter to use while recursively visiting Decls.
   BugReporter *RecVisitorBR;
 
+  std::vector<std::function<void(CheckerRegistry &)>> CheckerRegistrationFns;
+
 public:
   ASTContext *Ctx;
   const Preprocessor &PP;
@@ -293,8 +295,9 @@
 
   void Initialize(ASTContext &Context) override {
     Ctx = &Context;
-    checkerMgr = createCheckerManager(*Opts, PP.getLangOpts(), Plugins,
-                                      PP.getDiagnostics());
+    checkerMgr =
+        createCheckerManager(*Opts, PP.getLangOpts(), Plugins,
+                             CheckerRegistrationFns, PP.getDiagnostics());
 
     Mgr = llvm::make_unique<AnalysisManager>(
         *Ctx, PP.getDiagnostics(), PP.getLangOpts(), PathConsumers,
@@ -385,6 +388,10 @@
     PathConsumers.push_back(Consumer);
   }
 
+  void AddCheckerRegistrationFn(std::function<void(CheckerRegistry&)> Fn) override {
+    CheckerRegistrationFns.push_back(std::move(Fn));
+  }
+
 private:
   void storeTopLevelDecls(DeclGroupRef DG);
   std::string getFunctionName(const Decl *D);
Index: include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
===================================================================
--- include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
+++ include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
@@ -11,6 +11,7 @@
 #define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
 
 #include "clang/Basic/LLVM.h"
+#include <functional>
 #include <memory>
 #include <string>
 
@@ -21,10 +22,13 @@
 
 namespace ento {
   class CheckerManager;
+  class CheckerRegistry;
 
-  std::unique_ptr<CheckerManager>
-  createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
-                       ArrayRef<std::string> plugins, DiagnosticsEngine &diags);
+  std::unique_ptr<CheckerManager> createCheckerManager(
+      AnalyzerOptions &opts, const LangOptions &langOpts,
+      ArrayRef<std::string> plugins,
+      ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns,
+      DiagnosticsEngine &diags);
 
 } // end ento namespace
 
Index: include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
===================================================================
--- include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
+++ include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
@@ -17,6 +17,7 @@
 
 #include "clang/AST/ASTConsumer.h"
 #include "clang/Basic/LLVM.h"
+#include <functional>
 #include <memory>
 
 namespace clang {
@@ -29,10 +30,24 @@
 namespace ento {
 class PathDiagnosticConsumer;
 class CheckerManager;
+class CheckerRegistry;
 
 class AnalysisASTConsumer : public ASTConsumer {
 public:
   virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0;
+
+  /// This method allows registering statically linked custom checkers that are
+  /// not a part of the Clang tree. It employs the same mechanism that is used
+  /// by plugins.
+  ///
+  /// Example:
+  ///
+  ///   Consumer->AddCheckerRegistrationFn([] (CheckerRegistry& Registry) {
+  ///     Registry.addChecker<MyCustomChecker>("example.MyCustomChecker",
+  ///                                          "Description");
+  ///   });
+  virtual void
+  AddCheckerRegistrationFn(std::function<void(CheckerRegistry &)> Fn) = 0;
 };
 
 /// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to