blob: 12178fcd8c7041e78fdd9d8a2f088341367a755b [file] [log] [blame]
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +00001//===--- ClangSACheckerProvider.cpp - Clang SA Checkers Provider ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Defines the CheckerProvider for the checkers defined in
11// libclangStaticAnalyzerCheckers.
12//
13//===----------------------------------------------------------------------===//
14
15#include "ClangSACheckerProvider.h"
16#include "ClangSACheckers.h"
17#include "clang/StaticAnalyzer/Core/CheckerManager.h"
18#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
19#include "llvm/ADT/DenseSet.h"
20
21using namespace clang;
22using namespace ento;
23
24namespace {
25
26/// \brief Provider for all the checkers in libclangStaticAnalyzerCheckers.
27class ClangSACheckerProvider : public CheckerProvider {
28public:
29 virtual void registerCheckers(CheckerManager &checkerMgr,
30 CheckerOptInfo *checkOpts, unsigned numCheckOpts);
31};
32
33}
34
35CheckerProvider *ento::createClangSACheckerProvider() {
36 return new ClangSACheckerProvider();
37}
38
39namespace {
40
41struct StaticCheckerInfoRec {
42 const char *FullName;
43 CheckerManager::RegisterFunc RegFunc;
44 bool Hidden;
45};
46
47} // end anonymous namespace.
48
49static const StaticCheckerInfoRec StaticCheckerInfo[] = {
50#define GET_CHECKERS
51#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,HIDDEN) \
52 { FULLNAME, register##CLASS, HIDDEN },
53#include "Checkers.inc"
54 { 0, 0, 0}
55#undef CHECKER
56#undef GET_CHECKERS
57};
58
59namespace {
60
61struct CheckNameOption {
62 const char *Name;
63 const short *Members;
64 const short *SubGroups;
65};
66
67} // end anonymous namespace.
68
69#define GET_MEMBER_ARRAYS
70#include "Checkers.inc"
71#undef GET_MEMBER_ARRAYS
72
73// The table of check name options, sorted by name for fast binary lookup.
74static const CheckNameOption CheckNameTable[] = {
75#define GET_CHECKNAME_TABLE
76#include "Checkers.inc"
77#undef GET_CHECKNAME_TABLE
78};
79static const size_t
80 CheckNameTableSize = sizeof(CheckNameTable) / sizeof(CheckNameTable[0]);
81
82static bool CheckNameOptionCompare(const CheckNameOption &LHS,
83 const CheckNameOption &RHS) {
84 return strcmp(LHS.Name, RHS.Name) < 0;
85}
86
87static void collectCheckers(const CheckNameOption *checkName,
88 bool enable,
89 llvm::DenseSet<const StaticCheckerInfoRec *> &checkers,
90 bool collectHidden) {
91 if (const short *member = checkName->Members) {
92 if (enable) {
93 if (collectHidden || !StaticCheckerInfo[*member].Hidden)
94 checkers.insert(&StaticCheckerInfo[*member]);
95 } else {
96 for (; *member != -1; ++member)
97 checkers.erase(&StaticCheckerInfo[*member]);
98 }
99 }
100
101 // Enable/disable all subgroups along with this one.
102 if (const short *subGroups = checkName->SubGroups) {
103 for (; *subGroups != -1; ++subGroups)
104 collectCheckers(&CheckNameTable[*subGroups], enable, checkers,
105 /*don't enable hidden in subgroups*/ false);
106 }
107}
108
109static void collectCheckers(CheckerOptInfo &opt,
110 llvm::DenseSet<const StaticCheckerInfoRec *> &checkers) {
111 const char *optName = opt.getName();
112 CheckNameOption key = { optName, 0, 0 };
113 const CheckNameOption *found =
114 std::lower_bound(CheckNameTable, CheckNameTable + CheckNameTableSize, key,
115 CheckNameOptionCompare);
116 if (found == CheckNameTable + CheckNameTableSize ||
117 strcmp(found->Name, optName) != 0)
118 return; // Check name not found.
119
120 opt.claim();
121 collectCheckers(found, opt.isEnabled(), checkers, /*collectHidden=*/true);
122}
123
124#include "llvm/Support/raw_ostream.h"
125
126void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr,
127 CheckerOptInfo *checkOpts, unsigned numCheckOpts) {
128 llvm::DenseSet<const StaticCheckerInfoRec *> enabledCheckers;
129 for (unsigned i = 0; i != numCheckOpts; ++i)
130 collectCheckers(checkOpts[i], enabledCheckers);
131 for (llvm::DenseSet<const StaticCheckerInfoRec *>::iterator
132 I = enabledCheckers.begin(), E = enabledCheckers.end(); I != E; ++I) {
133 checkerMgr.addCheckerRegisterFunction((*I)->RegFunc);
134 }
135}