]> granicus.if.org Git - clang/commitdiff
Intoduce '-analyzer-checker-help' flag which outputs a list of all available static...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 25 Feb 2011 00:09:51 +0000 (00:09 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 25 Feb 2011 00:09:51 +0000 (00:09 +0000)
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
include/clang/Frontend/AnalyzerOptions.h
include/clang/StaticAnalyzer/Core/CheckerProvider.h
include/clang/StaticAnalyzer/Frontend/FrontendActions.h
lib/Frontend/CompilerInvocation.cpp
lib/FrontendTool/ExecuteCompilerInvocation.cpp
lib/StaticAnalyzer/Checkers/ClangSACheckerProvider.cpp
lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp

index 6cb85a3d4e99eb3d5c051aa4274bc52cd337f154..748e6cf3269188dd2eec26364304766fb9c8be81 100644 (file)
@@ -105,6 +105,9 @@ def analyzer_disable_checker : Separate<"-analyzer-disable-checker">,
 def analyzer_disable_checker_EQ : Joined<"-analyzer-disable-checker=">,
   Alias<analyzer_disable_checker>;
 
+def analyzer_checker_help : Flag<"-analyzer-checker-help">,
+  HelpText<"Display the list of analyzer checkers that are available">;
+
 //===----------------------------------------------------------------------===//
 // CodeGen Options
 //===----------------------------------------------------------------------===//
index 4b31e1e065ae072e2048a585ec5402e7096165aa..64263c1b54e8a7cf133a8bf87f36e5e385ec47e6 100644 (file)
@@ -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;
index 414ad92b2a5a334458334a74570c307f18706f4d..40b838e758869a2435310100eaa114fe4b868a65 100644 (file)
 #include "llvm/ADT/StringRef.h"
 #include <vector>
 
+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
index e3867a2a24780034c948905d41ad316f314b0917..f01418175281c6e3c3bf0a95ff2d82020e88d6bc 100644 (file)
@@ -26,6 +26,8 @@ protected:
                                          llvm::StringRef InFile);
 };
 
+void printCheckerHelp(llvm::raw_ostream &OS);
+
 } // end GR namespace
 
 } // end namespace clang
index 5111511c0b16c1ca6e9309aa1fa11fcadb8ee82b..0a1b2572d540e80b8e58d37908193a29d6e21b26 100644 (file)
@@ -78,6 +78,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
                                std::vector<std::string> &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);
index 4bb85e7e6340bd6fedc876d429f352f94b00dfcf..65fad6da51fa0d558e0b3f20800fa41b424e6592 100644 (file)
@@ -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?
index aefaf5480204eaff330723a043f6ab5972e1800c..5c0c9504db03843a05763dd30fcd7621369a3171 100644 (file)
@@ -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<std::string, const StaticCheckerInfoRec *> 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);
+}
index 608e349b278208e09f7fc33be52d1941a5d9cce8..677e20cd9c0e83a5b5e1f4364d764ed55a610ddc 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #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 <check1,check2,...>\n";
+  OS << '\n';
+  OS << "CHECKERS:\n";
+
+  llvm::OwningPtr<CheckerProvider> provider(createClangSACheckerProvider());
+  provider->printHelp(OS);
+
+  // FIXME: Load CheckerProviders from plugins.
+}