From 116f3640daee424dfcdbe55e80be5a67476be4b0 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Fri, 25 Feb 2011 00:09:51 +0000 Subject: [PATCH] Intoduce '-analyzer-checker-help' flag which outputs a list of all available static analyzer checkers. This is pretty basic for now, eventually checkers should be grouped according to package, hidden checkers should be indicated etc. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126454 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/CC1Options.td | 3 ++ include/clang/Frontend/AnalyzerOptions.h | 2 + .../StaticAnalyzer/Core/CheckerProvider.h | 5 ++ .../StaticAnalyzer/Frontend/FrontendActions.h | 2 + lib/Frontend/CompilerInvocation.cpp | 3 ++ .../ExecuteCompilerInvocation.cpp | 6 +++ .../Checkers/ClangSACheckerProvider.cpp | 49 ++++++++++++++++++- .../Frontend/CheckerRegistration.cpp | 15 ++++++ 8 files changed, 83 insertions(+), 2 deletions(-) diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 6cb85a3d4e..748e6cf326 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -105,6 +105,9 @@ def analyzer_disable_checker : Separate<"-analyzer-disable-checker">, def analyzer_disable_checker_EQ : Joined<"-analyzer-disable-checker=">, Alias; +def analyzer_checker_help : Flag<"-analyzer-checker-help">, + HelpText<"Display the list of analyzer checkers that are available">; + //===----------------------------------------------------------------------===// // CodeGen Options //===----------------------------------------------------------------------===// diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h index 4b31e1e065..64263c1b54 100644 --- a/include/clang/Frontend/AnalyzerOptions.h +++ b/include/clang/Frontend/AnalyzerOptions.h @@ -64,6 +64,7 @@ public: std::string AnalyzeSpecificFunction; unsigned MaxNodes; unsigned MaxLoop; + unsigned ShowCheckerHelp : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; @@ -86,6 +87,7 @@ public: AnalysisStoreOpt = BasicStoreModel; AnalysisConstraintsOpt = RangeConstraintsModel; AnalysisDiagOpt = PD_HTML; + ShowCheckerHelp = 0; AnalyzeAll = 0; AnalyzerDisplayProgress = 0; AnalyzeNestedBlocks = 0; diff --git a/include/clang/StaticAnalyzer/Core/CheckerProvider.h b/include/clang/StaticAnalyzer/Core/CheckerProvider.h index 414ad92b2a..40b838e758 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerProvider.h +++ b/include/clang/StaticAnalyzer/Core/CheckerProvider.h @@ -17,6 +17,10 @@ #include "llvm/ADT/StringRef.h" #include +namespace llvm { + class raw_ostream; +} + namespace clang { namespace ento { @@ -45,6 +49,7 @@ public: virtual ~CheckerProvider(); virtual void registerCheckers(CheckerManager &checkerMgr, CheckerOptInfo *checkOpts, unsigned numCheckOpts) = 0; + virtual void printHelp(llvm::raw_ostream &OS) = 0; }; } // end ento namespace diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index e3867a2a24..f014181752 100644 --- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h @@ -26,6 +26,8 @@ protected: llvm::StringRef InFile); }; +void printCheckerHelp(llvm::raw_ostream &OS); + } // end GR namespace } // end namespace clang diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 5111511c0b..0a1b2572d5 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -78,6 +78,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, std::vector &Res) { for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i) Res.push_back(getAnalysisName(Opts.AnalysisList[i])); + if (Opts.ShowCheckerHelp) + Res.push_back("-analyzer-checker-help"); if (Opts.AnalysisStoreOpt != BasicStoreModel) { Res.push_back("-analyzer-store"); Res.push_back(getAnalysisStoreName(Opts.AnalysisStoreOpt)); @@ -859,6 +861,7 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.AnalysisDiagOpt = Value; } + Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz); Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph); Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers); diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 4bb85e7e63..65fad6da51 100644 --- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -108,6 +108,12 @@ 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? diff --git a/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp b/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp index aefaf54802..5c0c9504db 100644 --- a/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp +++ b/lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp @@ -16,7 +16,9 @@ #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; @@ -28,6 +30,7 @@ class ClangSACheckerProvider : public CheckerProvider { public: virtual void registerCheckers(CheckerManager &checkerMgr, CheckerOptInfo *checkOpts, unsigned numCheckOpts); + virtual void printHelp(llvm::raw_ostream &OS); }; } @@ -41,6 +44,7 @@ namespace { struct StaticCheckerInfoRec { const char *FullName; void (*RegFunc)(CheckerManager &mgr); + const char *HelpText; bool Hidden; }; @@ -49,13 +53,16 @@ struct StaticCheckerInfoRec { static const StaticCheckerInfoRec StaticCheckerInfo[] = { #define GET_CHECKERS #define CHECKER(FULLNAME,CLASS,DESCFILE,HELPTEXT,HIDDEN) \ - { FULLNAME, register##CLASS, HIDDEN }, + { FULLNAME, register##CLASS, HELPTEXT, HIDDEN }, #include "Checkers.inc" - { 0, 0, 0} + { 0, 0, 0, 0} #undef CHECKER #undef GET_CHECKERS }; +static const unsigned NumCheckers = sizeof(StaticCheckerInfo) + / sizeof(StaticCheckerInfoRec) - 1; + namespace { struct CheckNameOption { @@ -136,3 +143,41 @@ void ClangSACheckerProvider::registerCheckers(CheckerManager &checkerMgr, (*I)->RegFunc(checkerMgr); } } + +typedef std::map SortedCheckers; + +static void printCheckerOption(llvm::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; + 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) << I->second->HelpText << '\n'; + } +} + +void ClangSACheckerProvider::printHelp(llvm::raw_ostream &OS) { + // 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/Frontend/CheckerRegistration.cpp b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp index 608e349b27..677e20cd9c 100644 --- a/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp +++ b/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp @@ -12,12 +12,14 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h" +#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" #include "../Checkers/ClangSACheckerProvider.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/CheckerProvider.h" #include "clang/Frontend/AnalyzerOptions.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Basic/Diagnostic.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" @@ -49,3 +51,16 @@ CheckerManager *ento::registerCheckers(const AnalyzerOptions &opts, return checkerMgr.take(); } + +void ento::printCheckerHelp(llvm::raw_ostream &OS) { + OS << "OVERVIEW: Clang Static Analyzer Checkers List\n"; + OS << '\n'; + OS << "USAGE: -analyzer-checker \n"; + OS << '\n'; + OS << "CHECKERS:\n"; + + llvm::OwningPtr provider(createClangSACheckerProvider()); + provider->printHelp(OS); + + // FIXME: Load CheckerProviders from plugins. +} -- 2.40.0