[analyzer] Overhaul of checker registration in preparation for basic plugin support. Removes support for checker groups (we can add them back in later if we decide they are still useful), and -analyzer-checker-help output is a little worse for the time being (no packages).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137758 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index 33d2c31..d8e982b 100644
--- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -22,7 +22,7 @@
CheckSecuritySyntaxOnly.cpp
CheckSizeofPointer.cpp
ChrootChecker.cpp
- ClangSACheckerProvider.cpp
+ ClangCheckers.cpp
DeadStoresChecker.cpp
DebugCheckers.cpp
DereferenceChecker.cpp
diff --git a/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp b/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp
new file mode 100644
index 0000000..77a5a72
--- /dev/null
+++ b/lib/StaticAnalyzer/Checkers/ClangCheckers.cpp
@@ -0,0 +1,32 @@
+//===--- ClangCheckers.h - Provides builtin checkers ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h"
+#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
+
+// FIXME: This is only necessary as long as there are checker registration
+// functions that do additional work besides mgr.registerChecker<CLASS>().
+// The only checkers that currently do this are:
+// - NSAutoreleasePoolChecker
+// - NSErrorChecker
+// - ObjCAtSyncChecker
+// It's probably worth including this information in Checkers.td to minimize
+// boilerplate code.
+#include "ClangSACheckers.h"
+
+using namespace clang;
+using namespace ento;
+
+void ento::registerBuiltinCheckers(CheckerRegistry ®istry) {
+#define GET_CHECKERS
+#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,GROUPINDEX,HIDDEN) \
+ registry.addChecker(register##CLASS, FULLNAME, HELPTEXT);
+#include "Checkers.inc"
+#undef GET_CHECKERS
+}
diff --git a/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp b/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
deleted file mode 100644
index a6286cb..0000000
--- a/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
+++ /dev/null
@@ -1,289 +0,0 @@
-//===--- ClangSACheckerProvider.cpp - Clang SA Checkers Provider ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines the CheckerProvider for the checkers defined in
-// libclangStaticAnalyzerCheckers.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ClangSACheckerProvider.h"
-#include "ClangSACheckers.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/ADT/DenseSet.h"
-#include "map"
-
-using namespace clang;
-using namespace ento;
-
-namespace {
-
-/// \brief Provider for all the checkers in libclangStaticAnalyzerCheckers.
-class ClangSACheckerProvider : public CheckerProvider {
-public:
- virtual void registerCheckers(CheckerManager &checkerMgr,
- CheckerOptInfo *checkOpts, unsigned numCheckOpts);
- virtual void printHelp(raw_ostream &OS);
-};
-
-}
-
-CheckerProvider *ento::createClangSACheckerProvider() {
- return new ClangSACheckerProvider();
-}
-
-namespace {
-
-struct StaticCheckerInfoRec {
- const char *FullName;
- void (*RegFunc)(CheckerManager &mgr);
- const char *HelpText;
- int GroupIndex;
- bool Hidden;
-};
-
-struct StaticPackageInfoRec {
- const char *FullName;
- int GroupIndex;
- bool Hidden;
-};
-
-struct StaticGroupInfoRec {
- const char *FullName;
-};
-
-} // end anonymous namespace.
-
-static const StaticPackageInfoRec StaticPackageInfo[] = {
-#define GET_PACKAGES
-#define PACKAGE(FULLNAME, GROUPINDEX, HIDDEN) \
- { FULLNAME, GROUPINDEX, HIDDEN },
-#include "Checkers.inc"
- { 0, -1, 0 }
-#undef PACKAGE
-#undef GET_PACKAGES
-};
-
-static const unsigned NumPackages = sizeof(StaticPackageInfo)
- / sizeof(StaticPackageInfoRec) - 1;
-
-static const StaticGroupInfoRec StaticGroupInfo[] = {
-#define GET_GROUPS
-#define GROUP(FULLNAME) \
- { FULLNAME },
-#include "Checkers.inc"
- { 0 }
-#undef GROUP
-#undef GET_GROUPS
-};
-
-static const unsigned NumGroups = sizeof(StaticGroupInfo)
- / sizeof(StaticGroupInfoRec) - 1;
-
-static const StaticCheckerInfoRec StaticCheckerInfo[] = {
-#define GET_CHECKERS
-#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,GROUPINDEX,HIDDEN) \
- { FULLNAME, register##CLASS, HELPTEXT, GROUPINDEX, HIDDEN },
-#include "Checkers.inc"
- { 0, 0, 0, -1, 0}
-#undef CHECKER
-#undef GET_CHECKERS
-};
-
-static const unsigned NumCheckers = sizeof(StaticCheckerInfo)
- / sizeof(StaticCheckerInfoRec) - 1;
-
-namespace {
-
-struct CheckNameOption {
- const char *Name;
- const short *Members;
- const short *SubGroups;
- bool Hidden;
-};
-
-} // end anonymous namespace.
-
-#define GET_MEMBER_ARRAYS
-#include "Checkers.inc"
-#undef GET_MEMBER_ARRAYS
-
-// The table of check name options, sorted by name for fast binary lookup.
-static const CheckNameOption CheckNameTable[] = {
-#define GET_CHECKNAME_TABLE
-#include "Checkers.inc"
-#undef GET_CHECKNAME_TABLE
-};
-static const size_t
- CheckNameTableSize = sizeof(CheckNameTable) / sizeof(CheckNameTable[0]);
-
-static bool CheckNameOptionCompare(const CheckNameOption &LHS,
- const CheckNameOption &RHS) {
- return strcmp(LHS.Name, RHS.Name) < 0;
-}
-
-static void collectCheckers(const CheckNameOption *checkName,
- bool enable,
- llvm::DenseSet<const StaticCheckerInfoRec *> &checkers,
- bool collectHidden) {
- if (checkName->Hidden && !collectHidden)
- return;
-
- if (const short *member = checkName->Members) {
- if (enable) {
- for (; *member != -1; ++member)
- if (collectHidden || !StaticCheckerInfo[*member].Hidden)
- checkers.insert(&StaticCheckerInfo[*member]);
- } else {
- for (; *member != -1; ++member)
- checkers.erase(&StaticCheckerInfo[*member]);
- }
- }
-
- // Enable/disable all subgroups along with this one.
- if (const short *subGroups = checkName->SubGroups) {
- for (; *subGroups != -1; ++subGroups) {
- const CheckNameOption *sub = &CheckNameTable[*subGroups];
- collectCheckers(sub, enable, checkers, collectHidden && !sub->Hidden);
- }
- }
-}
-
-static void collectCheckers(CheckerOptInfo &opt,
- llvm::DenseSet<const StaticCheckerInfoRec *> &checkers) {
- const char *optName = opt.getName();
- CheckNameOption key = { optName, 0, 0, false };
- const CheckNameOption *found =
- std::lower_bound(CheckNameTable, CheckNameTable + CheckNameTableSize, key,
- CheckNameOptionCompare);
- if (found == CheckNameTable + CheckNameTableSize ||
- strcmp(found->Name, optName) != 0)
- return; // Check name not found.
-
- opt.claim();
- collectCheckers(found, opt.isEnabled(), checkers, /*collectHidden=*/true);
-}
-
-void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr,
- CheckerOptInfo *checkOpts, unsigned numCheckOpts) {
- llvm::DenseSet<const StaticCheckerInfoRec *> enabledCheckers;
- for (unsigned i = 0; i != numCheckOpts; ++i)
- collectCheckers(checkOpts[i], enabledCheckers);
- for (llvm::DenseSet<const StaticCheckerInfoRec *>::iterator
- I = enabledCheckers.begin(), E = enabledCheckers.end(); I != E; ++I) {
- (*I)->RegFunc(checkerMgr);
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Printing Help.
-//===----------------------------------------------------------------------===//
-
-static void printPackageOption(raw_ostream &OS) {
- // Find the maximum option length.
- unsigned OptionFieldWidth = 0;
- for (unsigned i = 0; i != NumPackages; ++i) {
- // Limit the amount of padding we are willing to give up for alignment.
- unsigned Length = strlen(StaticPackageInfo[i].FullName);
- if (Length <= 30)
- OptionFieldWidth = std::max(OptionFieldWidth, Length);
- }
-
- const unsigned InitialPad = 2;
- for (unsigned i = 0; i != NumPackages; ++i) {
- const StaticPackageInfoRec &package = StaticPackageInfo[i];
- const std::string &Option = package.FullName;
- int Pad = OptionFieldWidth - int(Option.size());
- OS.indent(InitialPad) << Option;
-
- if (package.GroupIndex != -1 || package.Hidden) {
- // Break on long option names.
- if (Pad < 0) {
- OS << "\n";
- Pad = OptionFieldWidth + InitialPad;
- }
- OS.indent(Pad + 1) << "[";
- if (package.GroupIndex != -1) {
- OS << "Group=" << StaticGroupInfo[package.GroupIndex].FullName;
- if (package.Hidden)
- OS << ", ";
- }
- if (package.Hidden)
- OS << "Hidden";
- OS << "]";
- }
-
- OS << "\n";
- }
-}
-
-typedef std::map<std::string, const StaticCheckerInfoRec *> SortedCheckers;
-
-static void printCheckerOption(raw_ostream &OS,SortedCheckers &checkers) {
- // Find the maximum option length.
- unsigned OptionFieldWidth = 0;
- for (SortedCheckers::iterator
- I = checkers.begin(), E = checkers.end(); I != E; ++I) {
- // Limit the amount of padding we are willing to give up for alignment.
- unsigned Length = strlen(I->second->FullName);
- if (Length <= 30)
- OptionFieldWidth = std::max(OptionFieldWidth, Length);
- }
-
- const unsigned InitialPad = 2;
- for (SortedCheckers::iterator
- I = checkers.begin(), E = checkers.end(); I != E; ++I) {
- const std::string &Option = I->first;
- const StaticCheckerInfoRec &checker = *I->second;
- int Pad = OptionFieldWidth - int(Option.size());
- OS.indent(InitialPad) << Option;
-
- // Break on long option names.
- if (Pad < 0) {
- OS << "\n";
- Pad = OptionFieldWidth + InitialPad;
- }
- OS.indent(Pad + 1) << checker.HelpText;
-
- if (checker.GroupIndex != -1 || checker.Hidden) {
- OS << " [";
- if (checker.GroupIndex != -1) {
- OS << "Group=" << StaticGroupInfo[checker.GroupIndex].FullName;
- if (checker.Hidden)
- OS << ", ";
- }
- if (checker.Hidden)
- OS << "Hidden";
- OS << "]";
- }
-
- OS << "\n";
- }
-}
-
-void ClangSACheckerProvider::printHelp(raw_ostream &OS) {
- OS << "USAGE: -analyzer-checker <CHECKER or PACKAGE or GROUP,...>\n";
-
- OS << "\nGROUPS:\n";
- for (unsigned i = 0; i != NumGroups; ++i)
- OS.indent(2) << StaticGroupInfo[i].FullName << "\n";
-
- OS << "\nPACKAGES:\n";
- printPackageOption(OS);
-
- OS << "\nCHECKERS:\n";
-
- // Sort checkers according to their full name.
- SortedCheckers checkers;
- for (unsigned i = 0; i != NumCheckers; ++i)
- checkers[StaticCheckerInfo[i].FullName] = &StaticCheckerInfo[i];
-
- printCheckerOption(OS, checkers);
-}
diff --git a/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h b/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h
deleted file mode 100644
index f6c8011..0000000
--- a/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//===--- ClangSACheckerProvider.h - Clang SA Checkers Provider --*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines the entry point for creating the provider for the checkers defined
-// in libclangStaticAnalyzerCheckers.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SA_CHECKERS_CLANGSACHECKERPROVIDER_H
-#define LLVM_CLANG_SA_CHECKERS_CLANGSACHECKERPROVIDER_H
-
-namespace clang {
-
-namespace ento {
- class CheckerProvider;
-
-CheckerProvider *createClangSACheckerProvider();
-
-} // end ento namespace
-
-} // end clang namespace
-
-#endif
diff --git a/lib/StaticAnalyzer/Checkers/ClangSACheckers.h b/lib/StaticAnalyzer/Checkers/ClangSACheckers.h
index 5524b0f..289ce8d 100644
--- a/lib/StaticAnalyzer/Checkers/ClangSACheckers.h
+++ b/lib/StaticAnalyzer/Checkers/ClangSACheckers.h
@@ -19,6 +19,7 @@
namespace ento {
class CheckerManager;
+class CheckerRegistry;
#define GET_CHECKERS
#define CHECKER(FULLNAME,CLASS,CXXFILE,HELPTEXT,GROUPINDEX,HIDDEN) \
diff --git a/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt
index 7baf52d..5b31d33 100644
--- a/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -16,6 +16,7 @@
CheckerContext.cpp
CheckerHelpers.cpp
CheckerManager.cpp
+ CheckerRegistry.cpp
CoreEngine.cpp
Environment.cpp
ExplodedGraph.cpp
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 729e4cb..bcba98f 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/Analysis/ProgramPoint.h"
@@ -543,7 +542,4 @@
}
// Anchor for the vtable.
-CheckerProvider::~CheckerProvider() { }
-
-// Anchor for the vtable.
GraphExpander::~GraphExpander() { }
diff --git a/lib/StaticAnalyzer/Core/CheckerRegistry.cpp b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
new file mode 100644
index 0000000..13401ac
--- /dev/null
+++ b/lib/StaticAnalyzer/Core/CheckerRegistry.cpp
@@ -0,0 +1,149 @@
+//===--- CheckerRegistry.cpp - Maintains all available checkers -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
+#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
+
+using namespace clang;
+using namespace ento;
+
+static const char PackageSeparator = '.';
+typedef llvm::DenseSet<const CheckerRegistry::CheckerInfo *> CheckerInfoSet;
+
+
+static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
+ const CheckerRegistry::CheckerInfo &b) {
+ return a.FullName < b.FullName;
+}
+
+static bool isInPackage(const CheckerRegistry::CheckerInfo &checker,
+ StringRef packageName) {
+ // Does the checker's full name have the package as a prefix?
+ if (!checker.FullName.startswith(packageName))
+ return false;
+
+ // Is the package actually just the name of a specific checker?
+ if (checker.FullName.size() == packageName.size())
+ return true;
+
+ // Is the checker in the package (or a subpackage)?
+ if (checker.FullName[packageName.size()] == PackageSeparator)
+ return true;
+
+ return false;
+}
+
+static void collectCheckers(const CheckerRegistry::CheckerInfoList &checkers,
+ const llvm::StringMap<size_t> &packageSizes,
+ CheckerOptInfo &opt, CheckerInfoSet &collected) {
+ // Use a binary search to find the possible start of the package.
+ CheckerRegistry::CheckerInfo packageInfo(NULL, opt.getName(), "");
+ CheckerRegistry::CheckerInfoList::const_iterator e = checkers.end();
+ CheckerRegistry::CheckerInfoList::const_iterator i =
+ std::lower_bound(checkers.begin(), e, packageInfo, checkerNameLT);
+
+ // If we didn't even find a possible package, give up.
+ if (i == e)
+ return;
+
+ // If what we found doesn't actually start the package, give up.
+ if (!isInPackage(*i, opt.getName()))
+ return;
+
+ // There is at least one checker in the package; claim the option.
+ opt.claim();
+
+ // See how large the package is.
+ // If the package doesn't exist, assume the option refers to a single checker.
+ size_t size = 1;
+ llvm::StringMap<size_t>::const_iterator packageSize =
+ packageSizes.find(opt.getName());
+ if (packageSize != packageSizes.end())
+ size = packageSize->getValue();
+
+ // Step through all the checkers in the package.
+ for (e = i+size; i != e; ++i) {
+ if (opt.isEnabled())
+ collected.insert(&*i);
+ else
+ collected.erase(&*i);
+ }
+}
+
+void CheckerRegistry::addChecker(InitializationFunction fn, StringRef name,
+ StringRef desc) {
+ Checkers.push_back(CheckerInfo(fn, name, desc));
+
+ // Record the presence of the checker in its packages.
+ StringRef packageName, leafName;
+ llvm::tie(packageName, leafName) = name.rsplit(PackageSeparator);
+ while (!leafName.empty()) {
+ Packages[packageName] += 1;
+ llvm::tie(packageName, leafName) = packageName.rsplit(PackageSeparator);
+ }
+}
+
+void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
+ SmallVectorImpl<CheckerOptInfo> &opts) const {
+ // Sort checkers for efficient collection.
+ std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
+
+ // Collect checkers enabled by the options.
+ CheckerInfoSet enabledCheckers;
+ for (SmallVectorImpl<CheckerOptInfo>::iterator
+ i = opts.begin(), e = opts.end(); i != e; ++i) {
+ collectCheckers(Checkers, Packages, *i, enabledCheckers);
+ }
+
+ // Initialize the CheckerManager with all enabled checkers.
+ for (CheckerInfoSet::iterator
+ i = enabledCheckers.begin(), e = enabledCheckers.end(); i != e; ++i) {
+ (*i)->Initialize(checkerMgr);
+ }
+}
+
+void CheckerRegistry::printHelp(llvm::raw_ostream &out,
+ size_t maxNameChars) const {
+ // FIXME: Alphabetical sort puts 'experimental' in the middle.
+ // Would it be better to name it '~experimental' or something else
+ // that's ASCIIbetically last?
+ std::sort(Checkers.begin(), Checkers.end(), checkerNameLT);
+
+ // FIXME: Print available packages.
+
+ out << "CHECKERS:\n";
+
+ // Find the maximum option length.
+ size_t optionFieldWidth = 0;
+ for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
+ i != e; ++i) {
+ // Limit the amount of padding we are willing to give up for alignment.
+ // Package.Name Description [Hidden]
+ size_t nameLength = i->FullName.size();
+ if (nameLength <= maxNameChars)
+ optionFieldWidth = std::max(optionFieldWidth, nameLength);
+ }
+
+ const size_t initialPad = 2;
+ for (CheckerInfoList::const_iterator i = Checkers.begin(), e = Checkers.end();
+ i != e; ++i) {
+ out.indent(initialPad) << i->FullName;
+
+ int pad = optionFieldWidth - i->FullName.size();
+
+ // Break on long option names.
+ if (pad < 0) {
+ out << '\n';
+ pad = optionFieldWidth + initialPad;
+ }
+ out.indent(pad + 2) << i->Desc;
+
+ out << '\n';
+ }
+}
diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index 18a946c..24f19cd 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -66,6 +66,7 @@
const Preprocessor &PP;
const std::string OutDir;
AnalyzerOptions Opts;
+ ArrayRef<std::string> Plugins;
// PD is owned by AnalysisManager.
PathDiagnosticClient *PD;
@@ -78,9 +79,9 @@
AnalysisConsumer(const Preprocessor& pp,
const std::string& outdir,
- const AnalyzerOptions& opts)
- : Ctx(0), PP(pp), OutDir(outdir),
- Opts(opts), PD(0) {
+ const AnalyzerOptions& opts,
+ ArrayRef<std::string> plugins)
+ : Ctx(0), PP(pp), OutDir(outdir), Opts(opts), Plugins(plugins), PD(0) {
DigestAnalyzerOptions();
}
@@ -143,8 +144,8 @@
virtual void Initialize(ASTContext &Context) {
Ctx = &Context;
- checkerMgr.reset(registerCheckers(Opts, PP.getLangOptions(),
- PP.getDiagnostics()));
+ checkerMgr.reset(createCheckerManager(Opts, PP.getLangOptions(), Plugins,
+ PP.getDiagnostics()));
Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
PP.getLangOptions(), PD,
CreateStoreMgr, CreateConstraintMgr,
@@ -366,14 +367,13 @@
//===----------------------------------------------------------------------===//
ASTConsumer* ento::CreateAnalysisConsumer(const Preprocessor& pp,
- const std::string& OutDir,
- const AnalyzerOptions& Opts) {
- llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));
-
- // Last, disable the effects of '-Werror' when using the AnalysisConsumer.
+ const std::string& outDir,
+ const AnalyzerOptions& opts,
+ ArrayRef<std::string> plugins) {
+ // Disable the effects of '-Werror' when using the AnalysisConsumer.
pp.getDiagnostics().setWarningsAsErrors(false);
- return C.take();
+ return new AnalysisConsumer(pp, outDir, opts, plugins);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.h b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.h
index 646fe97..0265517 100644
--- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.h
+++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.h
@@ -15,6 +15,7 @@
#ifndef LLVM_CLANG_GR_ANALYSISCONSUMER_H
#define LLVM_CLANG_GR_ANALYSISCONSUMER_H
+#include "clang/Basic/LLVM.h"
#include <string>
namespace clang {
@@ -32,7 +33,8 @@
/// options.)
ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp,
const std::string &output,
- const AnalyzerOptions& Opts);
+ const AnalyzerOptions& opts,
+ ArrayRef<std::string> plugins);
} // end GR namespace
diff --git a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index 29c1cd1..8ed74a2 100644
--- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -13,9 +13,10 @@
#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
-#include "../Checkers/ClangSACheckerProvider.h"
+#include "clang/StaticAnalyzer/Checkers/ClangCheckers.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
+#include "clang/StaticAnalyzer/Core/CheckerOptInfo.h"
+#include "clang/StaticAnalyzer/Core/CheckerRegistry.h"
#include "clang/Frontend/AnalyzerOptions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Basic/Diagnostic.h"
@@ -26,9 +27,17 @@
using namespace clang;
using namespace ento;
-CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts,
- const LangOptions &langOpts,
- Diagnostic &diags) {
+static void registerCheckers(CheckerRegistry ®istry,
+ ArrayRef<std::string> plugins) {
+ registerBuiltinCheckers(registry);
+
+ // FIXME: register plugins.
+}
+
+CheckerManager *ento::createCheckerManager(const AnalyzerOptions &opts,
+ const LangOptions &langOpts,
+ ArrayRef<std::string> plugins,
+ Diagnostic &diags) {
llvm::OwningPtr<CheckerManager> checkerMgr(new CheckerManager(langOpts));
SmallVector<CheckerOptInfo, 8> checkerOpts;
@@ -37,11 +46,9 @@
checkerOpts.push_back(CheckerOptInfo(opt.first.c_str(), opt.second));
}
- llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider());
- provider->registerCheckers(*checkerMgr,
- checkerOpts.data(), checkerOpts.size());
-
- // FIXME: Load CheckerProviders from plugins.
+ CheckerRegistry allCheckers;
+ registerCheckers(allCheckers, plugins);
+ allCheckers.initializeManager(*checkerMgr, checkerOpts);
checkerMgr->finishedCheckerRegistration();
@@ -54,12 +61,11 @@
return checkerMgr.take();
}
-void ento::printCheckerHelp(raw_ostream &OS) {
- OS << "OVERVIEW: Clang Static Analyzer Checkers List\n";
- OS << '\n';
+void ento::printCheckerHelp(raw_ostream &out, ArrayRef<std::string> plugins) {
+ out << "OVERVIEW: Clang Static Analyzer Checkers List\n\n";
+ out << "USAGE: -analyzer-checker <CHECKER or PACKAGE,...>\n\n";
- llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider());
- provider->printHelp(OS);
-
- // FIXME: Load CheckerProviders from plugins.
+ CheckerRegistry allCheckers;
+ registerCheckers(allCheckers, plugins);
+ allCheckers.printHelp(out);
}
diff --git a/lib/StaticAnalyzer/Frontend/FrontendActions.cpp b/lib/StaticAnalyzer/Frontend/FrontendActions.cpp
index eeb7800..85a18ec 100644
--- a/lib/StaticAnalyzer/Frontend/FrontendActions.cpp
+++ b/lib/StaticAnalyzer/Frontend/FrontendActions.cpp
@@ -17,6 +17,7 @@
StringRef InFile) {
return CreateAnalysisConsumer(CI.getPreprocessor(),
CI.getFrontendOpts().OutputFile,
- CI.getAnalyzerOpts());
+ CI.getAnalyzerOpts(),
+ CI.getFrontendOpts().Plugins);
}