#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;
LLVM_DUMP_METHOD void CmdLineOption::dump() const {
dumpToStream(llvm::errs());
}
LLVM_DUMP_METHOD void
CmdLineOption::dumpToStream(llvm::raw_ostream &Out) const {
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 {
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) {
if (!Checker.FullName.startswith(PackageName))
return false;
if (Checker.FullName.size() == PackageName.size())
return true;
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()};
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};
}
void CheckerRegistryData::printCheckerWithDescList(
const AnalyzerOptions &AnOpts, raw_ostream &Out,
size_t MaxNameChars) const {
Out << "CHECKERS:\n";
size_t OptionFieldWidth = 0;
for (const auto &Checker : Checkers) {
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) {
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";
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},
2,
50,
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();
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);
}
}