blob: aefaf5480204eaff330723a043f6ab5972e1800c [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) {
Argyrios Kyrtzidis08099ad2011-02-24 21:42:52 +0000107 for (; *subGroups != -1; ++subGroups) {
108 const CheckNameOption *sub = &CheckNameTable[*subGroups];
109 collectCheckers(sub, enable, checkers, collectHidden && !sub->Hidden);
110 }
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +0000111 }
112}
113
114static void collectCheckers(CheckerOptInfo &opt,
115 llvm::DenseSet<const StaticCheckerInfoRec *> &checkers) {
116 const char *optName = opt.getName();
Argyrios Kyrtzidis26c05b12011-02-15 07:42:38 +0000117 CheckNameOption key = { optName, 0, 0, false };
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +0000118 const CheckNameOption *found =
119 std::lower_bound(CheckNameTable, CheckNameTable + CheckNameTableSize, key,
120 CheckNameOptionCompare);
121 if (found == CheckNameTable + CheckNameTableSize ||
122 strcmp(found->Name, optName) != 0)
123 return; // Check name not found.
124
125 opt.claim();
126 collectCheckers(found, opt.isEnabled(), checkers, /*collectHidden=*/true);
127}
128
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +0000129void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr,
130 CheckerOptInfo *checkOpts, unsigned numCheckOpts) {
131 llvm::DenseSet<const StaticCheckerInfoRec *> enabledCheckers;
132 for (unsigned i = 0; i != numCheckOpts; ++i)
133 collectCheckers(checkOpts[i], enabledCheckers);
134 for (llvm::DenseSet<const StaticCheckerInfoRec *>::iterator
135 I = enabledCheckers.begin(), E = enabledCheckers.end(); I != E; ++I) {
Argyrios Kyrtzidis695fb502011-02-17 21:39:17 +0000136 (*I)->RegFunc(checkerMgr);
Argyrios Kyrtzidis43dee222011-02-14 18:13:31 +0000137 }
138}