def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">,
HelpText<"Display the list of analyzer checkers that are available">;
+def analyzer_config_help : Flag<["-"], "analyzer-config-help">,
+ HelpText<"Display the list of -analyzer-config options">;
+
def analyzer_list_enabled_checkers : Flag<["-"], "analyzer-list-enabled-checkers">,
HelpText<"Display the list of enabled analyzer checkers">;
unsigned ShowCheckerHelp : 1;
unsigned ShowEnabledCheckerList : 1;
+ unsigned ShowConfigOptionsList : 1;
unsigned AnalyzeAll : 1;
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzeNestedBlocks : 1;
void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins);
void printEnabledCheckerList(raw_ostream &OS, ArrayRef<std::string> plugins,
const AnalyzerOptions &opts);
+void printAnalyzerConfigList(raw_ostream &OS);
} // end GR namespace
}
Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
+ Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help);
Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers);
Opts.DisableAllChecks = Args.hasArg(OPT_analyzer_disable_all_checks);
ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins);
return true;
}
+
+ // Honor -analyzer-list-enabled-checkers.
if (Clang->getAnalyzerOpts()->ShowEnabledCheckerList) {
ento::printEnabledCheckerList(llvm::outs(),
Clang->getFrontendOpts().Plugins,
*Clang->getAnalyzerOpts());
}
+
+ // Honor -analyzer-config-help.
+ if (Clang->getAnalyzerOpts()->ShowConfigOptionsList) {
+ ento::printAnalyzerConfigList(llvm::outs());
+ return true;
+ }
#endif
// If there were errors in processing arguments, don't do anything else.
#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>
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";
+ }
+}
--- /dev/null
+// RUN: %clang_cc1 -analyzer-config-help 2>&1 | FileCheck %s
+// CHECK: OVERVIEW: Clang Static Analyzer -analyzer-config Option List
+//
+// CHECK: USAGE: clang -cc1 [CLANG_OPTIONS] -analyzer-config <OPTION1=VALUE,OPTION2=VALUE,...>
+//
+// CHCEK: clang -cc1 [CLANG_OPTIONS] -analyzer-config OPTION1=VALUE, -analyzer-config OPTION2=VALUE, ...
+//
+// CHECK: clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang<OPTION1=VALUE,OPTION2=VALUE,...>
+//
+// CHECK: clang [CLANG_OPTIONS] -Xclang -analyzer-config -Xclang OPTION1=VALUE, -Xclang -analyzer-config -Xclang OPTION2=VALUE, ...
+//
+//
+// CHECK: OPTIONS:
+//
+// CHECK: aggressive-binary-operation-simplification
+// CHECK: (bool) Whether SValBuilder should rearrange
+// CHECK: comparisons and additive operations of symbolic
+// CHECK: expressions which consist of a sum of a
+// CHECK: symbol and a concrete integer into the format
+// CHECK: where symbols are on the left-hand side
+// CHECK: and the integer is on the right. This is
+// CHECK: only done if both symbols and both concrete
+// CHECK: integers are signed, greater than or equal
+// CHECK: to the quarter of the minimum value of the
+// CHECK: type and less than or equal to the quarter
+// CHECK: of the maximum value of that type. A + n
+// CHECK: <OP> B + m becomes A - B <OP> m - n, where
+// CHECK: A and B symbolic, n and m are integers.
+// CHECK: <OP> is any of '==', '!=', '<', '<=', '>',
+// CHECK: '>=', '+' or '-'. The rearrangement also
+// CHECK: happens with '-' instead of '+' on either
+// CHECK: or both side and also if any or both integers
+// CHECK: are missing. (default: false)