[cfe-commits] r126658 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/CheckerManager.h include/clang/StaticAnalyzer/Core/CheckerV2.h lib/StaticAnalyzer/Core/CheckerManager.cpp lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp

Argyrios Kyrtzidis akyrtzi at gmail.com
Mon Feb 28 09:36:09 PST 2011


Author: akirtzidis
Date: Mon Feb 28 11:36:09 2011
New Revision: 126658

URL: http://llvm.org/viewvc/llvm-project?rev=126658&view=rev
Log:
[analyzer] Introduce "event" mechanism in CheckerManager.

A checker can register as receiver/listener of "events" (basically it registers a callback
with a function getting called with an argument of the event type) and other checkers can
register as "dispatchers" and can pass an event object to all the listeners.
This allows cooperation amongst checkers but with very loose coupling.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h
    cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
    cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h?rev=126658&r1=126657&r2=126658&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerManager.h Mon Feb 28 11:36:09 2011
@@ -97,6 +97,8 @@
   CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { }
   ~CheckerManager();
 
+  void finishedCheckerRegistration();
+
   const LangOptions &getLangOptions() const { return LangOpts; }
 
   typedef void *CheckerRef;
@@ -112,7 +114,7 @@
   /// \returns a pointer to the checker object.
   template <typename CHECKER>
   CHECKER *registerChecker() {
-    CheckerTag tag = getCheckerTag<CHECKER>();
+    CheckerTag tag = getTag<CHECKER>();
     CheckerRef &ref = CheckerTags[tag];
     if (ref)
       return static_cast<CHECKER *>(ref); // already registered.
@@ -350,6 +352,46 @@
   void _registerForEvalCall(EvalCallFunc checkfn);
 
 //===----------------------------------------------------------------------===//
+// Internal registration functions for events.
+//===----------------------------------------------------------------------===//
+
+  typedef void *EventTag;
+
+  class CheckEventFunc {
+    typedef void (*Func)(void *, const void *);
+    Func Fn;
+  public:
+    void *Checker;
+    CheckEventFunc(void *checker, Func fn)
+      : Fn(fn), Checker(checker) { }
+    void operator()(const void *event) const {
+      return Fn(Checker, event);
+    } 
+  };
+
+  template <typename EVENT>
+  void _registerListenerForEvent(CheckEventFunc checkfn) {
+    EventInfo &info = Events[getTag<EVENT>()];
+    info.Checkers.push_back(checkfn);    
+  }
+
+  template <typename EVENT>
+  void _registerDispatcherForEvent() {
+    EventInfo &info = Events[getTag<EVENT>()];
+    info.HasDispatcher = true;
+  }
+
+  template <typename EVENT>
+  void _dispatchEvent(const EVENT &event) const {
+    EventsTy::const_iterator I = Events.find(getTag<EVENT>());
+    if (I == Events.end())
+      return;
+    const EventInfo &info = I->second;
+    for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
+      info.Checkers[i](&event);
+  }
+
+//===----------------------------------------------------------------------===//
 // Implementation details.
 //===----------------------------------------------------------------------===//
 
@@ -357,8 +399,8 @@
   template <typename CHECKER>
   static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
 
-  template <typename CHECKER>
-  static CheckerTag getCheckerTag() { static int tag; return &tag; }
+  template <typename T>
+  static void *getTag() { static int tag; return &tag; }
 
   llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
 
@@ -439,6 +481,15 @@
   std::vector<EvalAssumeFunc> EvalAssumeCheckers;
 
   std::vector<EvalCallFunc> EvalCallCheckers;
+
+  struct EventInfo {
+    llvm::SmallVector<CheckEventFunc, 4> Checkers;
+    bool HasDispatcher;
+    EventInfo() : HasDispatcher(false) { }
+  };
+  
+  typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
+  EventsTy Events;
 };
 
 } // end ento namespace

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h?rev=126658&r1=126657&r2=126658&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/CheckerV2.h Mon Feb 28 11:36:09 2011
@@ -259,6 +259,20 @@
   }
 };
 
+template <typename EVENT>
+class Event {
+  template <typename CHECKER>
+  static void _checkEvent(void *checker, const void *event) {
+    ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
+  }
+public:
+  template <typename CHECKER>
+  static void _register(CHECKER *checker, CheckerManager &mgr) {
+    mgr._registerListenerForEvent<EVENT>(
+                 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
+  }
+};
+
 } // end check namespace
 
 namespace eval {
@@ -300,22 +314,47 @@
           typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
           typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
           typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck>
-class CheckerV2 {
+class CheckerV2;
+
+template <>
+class CheckerV2<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
+                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
+                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
+                check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> {
+public:
+  static void _register(void *checker, CheckerManager &mgr) { }
+};
+
+template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
+          typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
+          typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12>
+class CheckerV2
+    : public CHECK1,
+      public CheckerV2<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
+                       CHECK9, CHECK10, CHECK11, CHECK12> {
 public:
   template <typename CHECKER>
   static void _register(CHECKER *checker, CheckerManager &mgr) {
     CHECK1::_register(checker, mgr);
-    CHECK2::_register(checker, mgr);
-    CHECK3::_register(checker, mgr);
-    CHECK4::_register(checker, mgr);
-    CHECK5::_register(checker, mgr);
-    CHECK6::_register(checker, mgr);
-    CHECK7::_register(checker, mgr);
-    CHECK8::_register(checker, mgr);
-    CHECK9::_register(checker, mgr);
-    CHECK10::_register(checker, mgr);
-    CHECK11::_register(checker, mgr);
-    CHECK12::_register(checker, mgr);
+    CheckerV2<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9,
+              CHECK10, CHECK11,CHECK12>::_register(checker, mgr);
+  }
+};
+
+template <typename EVENT>
+class EventDispatcher {
+  CheckerManager *Mgr;
+public:
+  EventDispatcher() : Mgr(0) { }
+
+  template <typename CHECKER>
+  static void _register(CHECKER *checker, CheckerManager &mgr) {
+    mgr._registerDispatcherForEvent<EVENT>();
+    static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
+  }
+
+  void dispatchEvent(const EVENT &event) const {
+    Mgr->_dispatchEvent(event);
   }
 };
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp?rev=126658&r1=126657&r2=126658&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CheckerManager.cpp Mon Feb 28 11:36:09 2011
@@ -20,6 +20,16 @@
 using namespace clang;
 using namespace ento;
 
+void CheckerManager::finishedCheckerRegistration() {
+#ifndef NDEBUG
+  // Make sure that for every event that has listeners, there is at least
+  // one dispatcher registered for it.
+  for (llvm::DenseMap<EventTag, EventInfo>::iterator
+         I = Events.begin(), E = Events.end(); I != E; ++I)
+    assert(I->second.HasDispatcher && "No dispatcher registered for an event");
+#endif
+}
+
 //===----------------------------------------------------------------------===//
 // Functions for running checkers for AST traversing..
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp?rev=126658&r1=126657&r2=126658&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp Mon Feb 28 11:36:09 2011
@@ -43,6 +43,8 @@
 
   // FIXME: Load CheckerProviders from plugins.
 
+  checkerMgr->finishedCheckerRegistration();
+
   for (unsigned i = 0, e = checkerOpts.size(); i != e; ++i) {
     if (checkerOpts[i].isUnclaimed())
       diags.Report(diag::warn_unkwown_analyzer_checker)





More information about the cfe-commits mailing list