diff options
Diffstat (limited to 'lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp | 118 |
1 files changed, 112 insertions, 6 deletions
diff --git a/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp b/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp index 5c0c950..291f8e0 100644 --- a/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp +++ b/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp @@ -45,17 +45,54 @@ 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,HIDDEN) \ - { FULLNAME, register##CLASS, HELPTEXT, HIDDEN }, +#define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,GROUPINDEX,HIDDEN) \ + { FULLNAME, register##CLASS, HELPTEXT, GROUPINDEX, HIDDEN }, #include "Checkers.inc" - { 0, 0, 0, 0} + { 0, 0, 0, -1, 0} #undef CHECKER #undef GET_CHECKERS }; @@ -101,8 +138,9 @@ static void collectCheckers(const CheckNameOption *checkName, if (const short *member = checkName->Members) { if (enable) { - if (collectHidden || !StaticCheckerInfo[*member].Hidden) - checkers.insert(&StaticCheckerInfo[*member]); + for (; *member != -1; ++member) + if (collectHidden || !StaticCheckerInfo[*member].Hidden) + checkers.insert(&StaticCheckerInfo[*member]); } else { for (; *member != -1; ++member) checkers.erase(&StaticCheckerInfo[*member]); @@ -144,6 +182,48 @@ void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr, } } +//===----------------------------------------------------------------------===// +// Printing Help. +//===----------------------------------------------------------------------===// + +static void printPackageOption(llvm::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(llvm::raw_ostream &OS,SortedCheckers &checkers) { @@ -161,6 +241,7 @@ static void printCheckerOption(llvm::raw_ostream &OS,SortedCheckers &checkers) { 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; @@ -169,11 +250,36 @@ static void printCheckerOption(llvm::raw_ostream &OS,SortedCheckers &checkers) { OS << "\n"; Pad = OptionFieldWidth + InitialPad; } - OS.indent(Pad + 1) << I->second->HelpText << '\n'; + 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(llvm::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) |