blob: 94f200f3e8929b12f7a00bb7660693f51d330266 [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;
Argyrios Kyrtzidis695fb502011-02-17 21:39:17 +000043 void (*RegFunc)(CheckerManager &mgr);
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +000044 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;
Argyrios Kyrtzidis26c05b12011-02-15 07:42:38 +000065 bool Hidden;
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +000066};
67
68} // end anonymous namespace.
69
70#define GET_MEMBER_ARRAYS
71#include "Checkers.inc"
72#undef GET_MEMBER_ARRAYS
73
74// The table of check name options, sorted by name for fast binary lookup.
75static const CheckNameOption CheckNameTable[] = {
76#define GET_CHECKNAME_TABLE
77#include "Checkers.inc"
78#undef GET_CHECKNAME_TABLE
79};
80static const size_t
81 CheckNameTableSize = sizeof(CheckNameTable) / sizeof(CheckNameTable[0]);
82
83static bool CheckNameOptionCompare(const CheckNameOption &LHS,
84 const CheckNameOption &RHS) {
85 return strcmp(LHS.Name, RHS.Name) < 0;
86}
87
88static void collectCheckers(const CheckNameOption *checkName,
89 bool enable,
90 llvm::DenseSet<const StaticCheckerInfoRec *> &checkers,
91 bool collectHidden) {
Argyrios Kyrtzidis26c05b12011-02-15 07:42:38 +000092 if (checkName->Hidden && !collectHidden)
93 return;
94
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +000095 if (const short *member = checkName->Members) {
96 if (enable) {
97 if (collectHidden || !StaticCheckerInfo[*member].Hidden)
98 checkers.insert(&StaticCheckerInfo[*member]);
99 } else {
100 for (; *member != -1; ++member)
101 checkers.erase(&StaticCheckerInfo[*member]);
102 }
103 }
104
105 // Enable/disable all subgroups along with this one.
106 if (const short *subGroups = checkName->SubGroups) {
107 for (; *subGroups != -1; ++subGroups)
108 collectCheckers(&CheckNameTable[*subGroups], enable, checkers,
Argyrios Kyrtzidis26c05b12011-02-15 07:42:38 +0000109 collectHidden && checkName->Hidden);
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +0000110 }
111}
112
113static void collectCheckers(CheckerOptInfo &opt,
114 llvm::DenseSet<const StaticCheckerInfoRec *> &checkers) {
115 const char *optName = opt.getName();
Argyrios Kyrtzidis26c05b12011-02-15 07:42:38 +0000116 CheckNameOption key = { optName, 0, 0, false };
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +0000117 const CheckNameOption *found =
118 std::lower_bound(CheckNameTable, CheckNameTable + CheckNameTableSize, key,
119 CheckNameOptionCompare);
120 if (found == CheckNameTable + CheckNameTableSize ||
121 strcmp(found->Name, optName) != 0)
122 return; // Check name not found.
123
124 opt.claim();
125 collectCheckers(found, opt.isEnabled(), checkers, /*collectHidden=*/true);
126}
127
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +0000128void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr,
129 CheckerOptInfo *checkOpts, unsigned numCheckOpts) {
130 llvm::DenseSet<const StaticCheckerInfoRec *> enabledCheckers;
131 for (unsigned i = 0; i != numCheckOpts; ++i)
132 collectCheckers(checkOpts[i], enabledCheckers);
133 for (llvm::DenseSet<const StaticCheckerInfoRec *>::iterator
134 I = enabledCheckers.begin(), E = enabledCheckers.end(); I != E; ++I) {
Argyrios Kyrtzidis695fb502011-02-17 21:39:17 +0000135 (*I)->RegFunc(checkerMgr);
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +0000136 }
137}