diff options
-rw-r--r-- | include/clang/StaticAnalyzer/Core/CheckerManager.h | 57 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/CheckerV2.h | 63 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CheckerManager.cpp | 10 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp | 2 |
4 files changed, 117 insertions, 15 deletions
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 3c23cbd29f..d57b55f5f7 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -97,6 +97,8 @@ public: CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { } ~CheckerManager(); + void finishedCheckerRegistration(); + const LangOptions &getLangOptions() const { return LangOpts; } typedef void *CheckerRef; @@ -112,7 +114,7 @@ public: /// \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 @@ public: 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 @@ private: 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 @@ private: 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 diff --git a/include/clang/StaticAnalyzer/Core/CheckerV2.h b/include/clang/StaticAnalyzer/Core/CheckerV2.h index 931cee9931..a4c7c7d806 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerV2.h +++ b/include/clang/StaticAnalyzer/Core/CheckerV2.h @@ -259,6 +259,20 @@ public: } }; +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 @@ template <typename CHECK1, typename CHECK2=check::_VoidCheck, 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); } }; diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp index 4776f5702d..74f47e4f77 100644 --- a/lib/StaticAnalyzer/Core/CheckerManager.cpp +++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp @@ -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.. //===----------------------------------------------------------------------===// diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index 677e20cd9c..0484cbed3b 100644 --- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp @@ -43,6 +43,8 @@ CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts, // 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) |