diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/FrontendTool/ExecuteCompilerInvocation.cpp | 13 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ClangCheckers.cpp | 32 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp | 289 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.h | 29 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ClangSACheckers.h | 1 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CheckerManager.cpp | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CheckerRegistry.cpp | 149 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 22 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Frontend/AnalysisConsumer.h | 4 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp | 40 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Frontend/FrontendActions.cpp | 3 |
13 files changed, 230 insertions, 359 deletions
diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 1d10b241ab..ed081923f3 100644 --- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -125,12 +125,6 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) { return 0; } - // Honor -analyzer-checker-help. - if (Clang->getAnalyzerOpts().ShowCheckerHelp) { - ento::printCheckerHelp(llvm::outs()); - return 0; - } - // Honor -version. // // FIXME: Use a better -version message? @@ -162,6 +156,13 @@ bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) { << Path << Error; } + // Honor -analyzer-checker-help. + // This should happen AFTER plugins have been loaded! + if (Clang->getAnalyzerOpts().ShowCheckerHelp) { + ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins); + return 0; + } + // If there were errors in processing arguments, don't do anything else. bool Success = false; if (!Clang->getDiagnostics().hasErrorOccurred()) { diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt index 33d2c31fa0..d8e982bd69 100644 --- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt @@ -22,7 +22,7 @@ add_clang_library(clangStaticAnalyzerCheckers 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 0000000000..77a5a72264 --- /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 a6286cbd7b..0000000000 --- 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 f6c80119fd..0000000000 --- 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 5524b0f532..289ce8d8c3 100644 --- a/lib/StaticAnalyzer/Checkers/ClangSACheckers.h +++ b/lib/StaticAnalyzer/Checkers/ClangSACheckers.h @@ -19,6 +19,7 @@ namespace clang { 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 7baf52da8c..5b31d33976 100644 --- a/lib/StaticAnalyzer/Core/CMakeLists.txt +++ b/lib/StaticAnalyzer/Core/CMakeLists.txt @@ -16,6 +16,7 @@ add_clang_library(clangStaticAnalyzerCore 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 729e4cb17c..bcba98fb3a 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 @@ CheckerManager::~CheckerManager() { } // 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 0000000000..13401acf3d --- /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 18a946c195..24f19cd0ab 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -66,6 +66,7 @@ public: const Preprocessor &PP; const std::string OutDir; AnalyzerOptions Opts; + ArrayRef<std::string> Plugins; // PD is owned by AnalysisManager. PathDiagnosticClient *PD; @@ -78,9 +79,9 @@ public: 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 @@ public: 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 @@ static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr, //===----------------------------------------------------------------------===// 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 646fe97564..0265517aff 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 @@ class CheckerManager; /// 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 29c1cd1eda..8ed74a2267 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 @@ CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts, 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 @@ CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts, return checkerMgr.take(); } -void ento::printCheckerHelp(raw_ostream &OS) { - OS << "OVERVIEW: Clang Static Analyzer Checkers List\n"; - OS << '\n'; - - llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider()); - provider->printHelp(OS); +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"; - // 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 eeb7800e48..85a18ec98e 100644 --- a/lib/StaticAnalyzer/Frontend/FrontendActions.cpp +++ b/lib/StaticAnalyzer/Frontend/FrontendActions.cpp @@ -17,6 +17,7 @@ ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { return CreateAnalysisConsumer(CI.getPreprocessor(), CI.getFrontendOpts().OutputFile, - CI.getAnalyzerOpts()); + CI.getAnalyzerOpts(), + CI.getFrontendOpts().Plugins); } |