brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · b9c6278 Raw
242 lines · cpp
1//===- CheckerRegistry.h - Maintains all available checkers -----*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/StaticAnalyzer/Core/CheckerRegistryData.h"10#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"11#include "llvm/ADT/Twine.h"12#include <map>13 14using namespace clang;15using namespace ento;16 17//===----------------------------------------------------------------------===//18// Methods of CmdLineOption, PackageInfo and CheckerInfo.19//===----------------------------------------------------------------------===//20 21LLVM_DUMP_METHOD void CmdLineOption::dump() const {22  dumpToStream(llvm::errs());23}24 25LLVM_DUMP_METHOD void26CmdLineOption::dumpToStream(llvm::raw_ostream &Out) const {27  // The description can be just checked in Checkers.inc, the point here is to28  // debug whether we succeeded in parsing it.29  Out << OptionName << " (" << OptionType << ", "30      << (IsHidden ? "hidden, " : "") << DevelopmentStatus << ") default: \""31      << DefaultValStr;32}33 34static StringRef toString(StateFromCmdLine Kind) {35  switch (Kind) {36  case StateFromCmdLine::State_Disabled:37    return "Disabled";38  case StateFromCmdLine::State_Enabled:39    return "Enabled";40  case StateFromCmdLine::State_Unspecified:41    return "Unspecified";42  }43  llvm_unreachable("Unhandled StateFromCmdLine enum");44}45 46LLVM_DUMP_METHOD void CheckerInfo::dump() const { dumpToStream(llvm::errs()); }47 48LLVM_DUMP_METHOD void CheckerInfo::dumpToStream(llvm::raw_ostream &Out) const {49  // The description can be just checked in Checkers.inc, the point here is to50  // debug whether we succeeded in parsing it. Same with documentation uri.51  Out << FullName << " (" << toString(State) << (IsHidden ? ", hidden" : "")52      << ")\n";53  Out << "  Options:\n";54  for (const CmdLineOption &Option : CmdLineOptions) {55    Out << "    ";56    Option.dumpToStream(Out);57    Out << '\n';58  }59  Out << "  Dependencies:\n";60  for (const CheckerInfo *Dependency : Dependencies) {61    Out << "  " << Dependency->FullName << '\n';62  }63  Out << "  Weak dependencies:\n";64  for (const CheckerInfo *Dependency : WeakDependencies) {65    Out << "    " << Dependency->FullName << '\n';66  }67}68 69LLVM_DUMP_METHOD void PackageInfo::dump() const { dumpToStream(llvm::errs()); }70 71LLVM_DUMP_METHOD void PackageInfo::dumpToStream(llvm::raw_ostream &Out) const {72  Out << FullName << "\n";73  Out << "  Options:\n";74  for (const CmdLineOption &Option : CmdLineOptions) {75    Out << "    ";76    Option.dumpToStream(Out);77    Out << '\n';78  }79}80 81static constexpr char PackageSeparator = '.';82 83static bool isInPackage(const CheckerInfo &Checker, StringRef PackageName) {84  // Does the checker's full name have the package as a prefix?85  if (!Checker.FullName.starts_with(PackageName))86    return false;87 88  // Is the package actually just the name of a specific checker?89  if (Checker.FullName.size() == PackageName.size())90    return true;91 92  // Is the checker in the package (or a subpackage)?93  if (Checker.FullName[PackageName.size()] == PackageSeparator)94    return true;95 96  return false;97}98 99CheckerInfoListRange100CheckerRegistryData::getMutableCheckersForCmdLineArg(StringRef CmdLineArg) {101  auto It = checker_registry::binaryFind(Checkers, CmdLineArg);102 103  if (!isInPackage(*It, CmdLineArg))104    return {Checkers.end(), Checkers.end()};105 106  // See how large the package is.107  // If the package doesn't exist, assume the option refers to a single108  // checker.109  size_t Size = 1;110  llvm::StringMap<size_t>::const_iterator PackageSize =111      PackageSizes.find(CmdLineArg);112 113  if (PackageSize != PackageSizes.end())114    Size = PackageSize->getValue();115 116  return {It, It + Size};117}118//===----------------------------------------------------------------------===//119// Printing functions.120//===----------------------------------------------------------------------===//121 122void CheckerRegistryData::printCheckerWithDescList(123    const AnalyzerOptions &AnOpts, raw_ostream &Out,124    size_t MaxNameChars) const {125  // FIXME: Print available packages.126 127  Out << "CHECKERS:\n";128 129  // Find the maximum option length.130  size_t OptionFieldWidth = 0;131  for (const auto &Checker : Checkers) {132    // Limit the amount of padding we are willing to give up for alignment.133    //   Package.Name     Description  [Hidden]134    size_t NameLength = Checker.FullName.size();135    if (NameLength <= MaxNameChars)136      OptionFieldWidth = std::max(OptionFieldWidth, NameLength);137  }138 139  const size_t InitialPad = 2;140 141  auto Print = [=](llvm::raw_ostream &Out, const CheckerInfo &Checker,142                   StringRef Description) {143    AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Description},144                                         InitialPad, OptionFieldWidth);145    Out << '\n';146  };147 148  for (const auto &Checker : Checkers) {149    // The order of this if branches is significant, we wouldn't like to display150    // developer checkers even in the alpha output. For example,151    // alpha.cplusplus.IteratorModeling is a modeling checker, hence it's hidden152    // by default, and users (even when the user is a developer of an alpha153    // checker) shouldn't normally tinker with whether they should be enabled.154 155    if (Checker.IsHidden) {156      if (AnOpts.ShowCheckerHelpDeveloper)157        Print(Out, Checker, Checker.Desc);158      continue;159    }160 161    if (Checker.FullName.starts_with("alpha")) {162      if (AnOpts.ShowCheckerHelpAlpha)163        Print(Out, Checker,164              ("(Enable only for development!) " + Checker.Desc).str());165      continue;166    }167 168    if (AnOpts.ShowCheckerHelp)169      Print(Out, Checker, Checker.Desc);170  }171}172 173void CheckerRegistryData::printEnabledCheckerList(raw_ostream &Out) const {174  for (const auto *i : EnabledCheckers)175    Out << i->FullName << '\n';176}177 178void CheckerRegistryData::printCheckerOptionList(const AnalyzerOptions &AnOpts,179                                                 raw_ostream &Out) const {180  Out << "OVERVIEW: Clang Static Analyzer Checker and Package Option List\n\n";181  Out << "USAGE: -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>\n\n";182  Out << "       -analyzer-config OPTION1=VALUE, -analyzer-config "183         "OPTION2=VALUE, ...\n\n";184  Out << "OPTIONS:\n\n";185 186  // It's usually ill-advised to use multimap, but clang will terminate after187  // this function.188  std::multimap<StringRef, const CmdLineOption &> OptionMap;189 190  for (const CheckerInfo &Checker : Checkers) {191    for (const CmdLineOption &Option : Checker.CmdLineOptions) {192      OptionMap.insert({Checker.FullName, Option});193    }194  }195 196  for (const PackageInfo &Package : Packages) {197    for (const CmdLineOption &Option : Package.CmdLineOptions) {198      OptionMap.insert({Package.FullName, Option});199    }200  }201 202  auto Print = [](llvm::raw_ostream &Out, StringRef FullOption,203                  StringRef Desc) {204    AnalyzerOptions::printFormattedEntry(Out, {FullOption, Desc},205                                         /*InitialPad*/ 2,206                                         /*EntryWidth*/ 50,207                                         /*MinLineWidth*/ 90);208    Out << "\n\n";209  };210  for (const std::pair<const StringRef, const CmdLineOption &> &Entry :211       OptionMap) {212    const CmdLineOption &Option = Entry.second;213    std::string FullOption = (Entry.first + ":" + Option.OptionName).str();214 215    std::string Desc =216        ("(" + Option.OptionType + ") " + Option.Description + " (default: " +217         (Option.DefaultValStr.empty() ? "\"\"" : Option.DefaultValStr) + ")")218            .str();219 220    // The list of these if branches is significant, we wouldn't like to221    // display hidden alpha checker options for222    // -analyzer-checker-option-help-alpha.223 224    if (Option.IsHidden) {225      if (AnOpts.ShowCheckerOptionDeveloperList)226        Print(Out, FullOption, Desc);227      continue;228    }229 230    if (Option.DevelopmentStatus == "alpha" ||231        Entry.first.starts_with("alpha")) {232      if (AnOpts.ShowCheckerOptionAlphaList)233        Print(Out, FullOption,234              llvm::Twine("(Enable only for development!) " + Desc).str());235      continue;236    }237 238    if (AnOpts.ShowCheckerOptionList)239      Print(Out, FullOption, Desc);240  }241}242