123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- //===- CheckerRegistry.h - Maintains all available checkers -----*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "clang/StaticAnalyzer/Core/CheckerRegistryData.h"
- #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
- #include "llvm/ADT/Twine.h"
- #include <map>
- using namespace clang;
- using namespace ento;
- //===----------------------------------------------------------------------===//
- // Methods of CmdLineOption, PackageInfo and CheckerInfo.
- //===----------------------------------------------------------------------===//
- LLVM_DUMP_METHOD void CmdLineOption::dump() const {
- dumpToStream(llvm::errs());
- }
- LLVM_DUMP_METHOD void
- CmdLineOption::dumpToStream(llvm::raw_ostream &Out) const {
- // The description can be just checked in Checkers.inc, the point here is to
- // debug whether we succeeded in parsing it.
- Out << OptionName << " (" << OptionType << ", "
- << (IsHidden ? "hidden, " : "") << DevelopmentStatus << ") default: \""
- << DefaultValStr;
- }
- static StringRef toString(StateFromCmdLine Kind) {
- switch (Kind) {
- case StateFromCmdLine::State_Disabled:
- return "Disabled";
- case StateFromCmdLine::State_Enabled:
- return "Enabled";
- case StateFromCmdLine::State_Unspecified:
- return "Unspecified";
- }
- llvm_unreachable("Unhandled StateFromCmdLine enum");
- }
- LLVM_DUMP_METHOD void CheckerInfo::dump() const { dumpToStream(llvm::errs()); }
- LLVM_DUMP_METHOD void CheckerInfo::dumpToStream(llvm::raw_ostream &Out) const {
- // The description can be just checked in Checkers.inc, the point here is to
- // debug whether we succeeded in parsing it. Same with documentation uri.
- Out << FullName << " (" << toString(State) << (IsHidden ? ", hidden" : "")
- << ")\n";
- Out << " Options:\n";
- for (const CmdLineOption &Option : CmdLineOptions) {
- Out << " ";
- Option.dumpToStream(Out);
- Out << '\n';
- }
- Out << " Dependencies:\n";
- for (const CheckerInfo *Dependency : Dependencies) {
- Out << " " << Dependency->FullName << '\n';
- }
- Out << " Weak dependencies:\n";
- for (const CheckerInfo *Dependency : WeakDependencies) {
- Out << " " << Dependency->FullName << '\n';
- }
- }
- LLVM_DUMP_METHOD void PackageInfo::dump() const { dumpToStream(llvm::errs()); }
- LLVM_DUMP_METHOD void PackageInfo::dumpToStream(llvm::raw_ostream &Out) const {
- Out << FullName << "\n";
- Out << " Options:\n";
- for (const CmdLineOption &Option : CmdLineOptions) {
- Out << " ";
- Option.dumpToStream(Out);
- Out << '\n';
- }
- }
- static constexpr char PackageSeparator = '.';
- static bool isInPackage(const 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;
- }
- CheckerInfoListRange
- CheckerRegistryData::getMutableCheckersForCmdLineArg(StringRef CmdLineArg) {
- auto It = checker_registry::binaryFind(Checkers, CmdLineArg);
- if (!isInPackage(*It, CmdLineArg))
- return {Checkers.end(), Checkers.end()};
- // 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(CmdLineArg);
- if (PackageSize != PackageSizes.end())
- Size = PackageSize->getValue();
- return {It, It + Size};
- }
- //===----------------------------------------------------------------------===//
- // Printing functions.
- //===----------------------------------------------------------------------===//
- void CheckerRegistryData::printCheckerWithDescList(
- const AnalyzerOptions &AnOpts, raw_ostream &Out,
- size_t MaxNameChars) const {
- // FIXME: Print available packages.
- Out << "CHECKERS:\n";
- // Find the maximum option length.
- size_t OptionFieldWidth = 0;
- for (const auto &Checker : Checkers) {
- // Limit the amount of padding we are willing to give up for alignment.
- // Package.Name Description [Hidden]
- size_t NameLength = Checker.FullName.size();
- if (NameLength <= MaxNameChars)
- OptionFieldWidth = std::max(OptionFieldWidth, NameLength);
- }
- const size_t InitialPad = 2;
- auto Print = [=](llvm::raw_ostream &Out, const CheckerInfo &Checker,
- StringRef Description) {
- AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Description},
- InitialPad, OptionFieldWidth);
- Out << '\n';
- };
- for (const auto &Checker : Checkers) {
- // The order of this if branches is significant, we wouldn't like to display
- // developer checkers even in the alpha output. For example,
- // alpha.cplusplus.IteratorModeling is a modeling checker, hence it's hidden
- // by default, and users (even when the user is a developer of an alpha
- // checker) shouldn't normally tinker with whether they should be enabled.
- if (Checker.IsHidden) {
- if (AnOpts.ShowCheckerHelpDeveloper)
- Print(Out, Checker, Checker.Desc);
- continue;
- }
- if (Checker.FullName.startswith("alpha")) {
- if (AnOpts.ShowCheckerHelpAlpha)
- Print(Out, Checker,
- ("(Enable only for development!) " + Checker.Desc).str());
- continue;
- }
- if (AnOpts.ShowCheckerHelp)
- Print(Out, Checker, Checker.Desc);
- }
- }
- void CheckerRegistryData::printEnabledCheckerList(raw_ostream &Out) const {
- for (const auto *i : EnabledCheckers)
- Out << i->FullName << '\n';
- }
- void CheckerRegistryData::printCheckerOptionList(const AnalyzerOptions &AnOpts,
- raw_ostream &Out) const {
- Out << "OVERVIEW: Clang Static Analyzer Checker and Package Option List\n\n";
- Out << "USAGE: -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
- Out << " -analyzer-config OPTION1=VALUE, -analyzer-config "
- "OPTION2=VALUE, ...\n\n";
- Out << "OPTIONS:\n\n";
- // It's usually ill-advised to use multimap, but clang will terminate after
- // this function.
- std::multimap<StringRef, const CmdLineOption &> OptionMap;
- for (const CheckerInfo &Checker : Checkers) {
- for (const CmdLineOption &Option : Checker.CmdLineOptions) {
- OptionMap.insert({Checker.FullName, Option});
- }
- }
- for (const PackageInfo &Package : Packages) {
- for (const CmdLineOption &Option : Package.CmdLineOptions) {
- OptionMap.insert({Package.FullName, Option});
- }
- }
- auto Print = [](llvm::raw_ostream &Out, StringRef FullOption,
- StringRef Desc) {
- AnalyzerOptions::printFormattedEntry(Out, {FullOption, Desc},
- /*InitialPad*/ 2,
- /*EntryWidth*/ 50,
- /*MinLineWidth*/ 90);
- Out << "\n\n";
- };
- for (const std::pair<const StringRef, const CmdLineOption &> &Entry :
- OptionMap) {
- const CmdLineOption &Option = Entry.second;
- std::string FullOption = (Entry.first + ":" + Option.OptionName).str();
- std::string Desc =
- ("(" + Option.OptionType + ") " + Option.Description + " (default: " +
- (Option.DefaultValStr.empty() ? "\"\"" : Option.DefaultValStr) + ")")
- .str();
- // The list of these if branches is significant, we wouldn't like to
- // display hidden alpha checker options for
- // -analyzer-checker-option-help-alpha.
- if (Option.IsHidden) {
- if (AnOpts.ShowCheckerOptionDeveloperList)
- Print(Out, FullOption, Desc);
- continue;
- }
- if (Option.DevelopmentStatus == "alpha" ||
- Entry.first.startswith("alpha")) {
- if (AnOpts.ShowCheckerOptionAlphaList)
- Print(Out, FullOption,
- llvm::Twine("(Enable only for development!) " + Desc).str());
- continue;
- }
- if (AnOpts.ShowCheckerOptionList)
- Print(Out, FullOption, Desc);
- }
- }
|