[analyzer] New flag to print all -analyzer-config options

A new -cc1 flag is avaible for the said purpose: -analyzer-config-help

Differential Revision: https://reviews.llvm.org/D53296

llvm-svn: 345989
diff --git a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
index 76e66cc..03d2ef3 100644
--- a/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/CheckerRegistration.cpp
@@ -22,6 +22,7 @@
 #include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"
 #include <memory>
@@ -157,3 +158,74 @@
   SmallVector<CheckerOptInfo, 8> checkerOpts = getCheckerOptList(opts);
   ClangCheckerRegistry(plugins).printList(out, checkerOpts);
 }
+
+void ento::printAnalyzerConfigList(raw_ostream &out) {
+  out << "OVERVIEW: Clang Static Analyzer -analyzer-config Option List\n\n";
+  out << "USAGE: clang -cc1 [CLANG_OPTIONS] -analyzer-config "
+                                        "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
+  out << "       clang -cc1 [CLANG_OPTIONS] -analyzer-config OPTION1=VALUE, "
+                                      "-analyzer-config OPTION2=VALUE, ...\n\n";
+  out << "       clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang"
+                                        "<OPTION1=VALUE,OPTION2=VALUE,...>\n\n";
+  out << "       clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang "
+                              "OPTION1=VALUE, -Xclang -analyzer-config -Xclang "
+                              "OPTION2=VALUE, ...\n\n";
+  out << "OPTIONS:\n\n";
+
+  using OptionAndDescriptionTy = std::pair<StringRef, std::string>;
+  OptionAndDescriptionTy PrintableOptions[] = {
+#define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL)                \
+    {                                                                          \
+      CMDFLAG,                                                                 \
+      llvm::Twine(llvm::Twine() + "(" +                                        \
+                  (#TYPE == "StringRef" ? "string" : #TYPE ) + ") " DESC       \
+                  " (default: " #DEFAULT_VAL ")").str()                        \
+    },
+
+#define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC,        \
+                                             SHALLOW_VAL, DEEP_VAL)            \
+    {                                                                          \
+      CMDFLAG,                                                                 \
+      llvm::Twine(llvm::Twine() + "(" +                                        \
+                  (#TYPE == "StringRef" ? "string" : #TYPE ) + ") " DESC       \
+                  " (default: " #SHALLOW_VAL " in shallow mode, " #DEEP_VAL    \
+                  " in deep mode)").str()                                      \
+    },
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
+#undef ANALYZER_OPTION
+#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
+  };
+
+  llvm::sort(PrintableOptions, [](const OptionAndDescriptionTy &LHS,
+                                  const OptionAndDescriptionTy &RHS) {
+    return LHS.first < RHS.first;
+  });
+
+  constexpr size_t MinLineWidth = 70;
+  constexpr size_t PadForOpt = 2;
+  constexpr size_t OptionWidth = 30;
+  constexpr size_t PadForDesc = PadForOpt + OptionWidth;
+  static_assert(MinLineWidth > PadForDesc, "MinLineWidth must be greater!");
+
+  llvm::formatted_raw_ostream FOut(out);
+
+  for (const auto &Pair : PrintableOptions) {
+    FOut.PadToColumn(PadForOpt) << Pair.first;
+
+    // If the buffer's length is greater then PadForDesc, print a newline.
+    if (FOut.getColumn() > PadForDesc)
+      FOut << '\n';
+
+    FOut.PadToColumn(PadForDesc);
+
+    for (char C : Pair.second) {
+      if (FOut.getColumn() > MinLineWidth && C == ' ') {
+        FOut << '\n';
+        FOut.PadToColumn(PadForDesc);
+        continue;
+      }
+      FOut << C;
+    }
+    FOut << "\n\n";
+  }
+}