Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -130,9 +130,14 @@ def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; -def analyzer_checker_help_hidden : Flag<["-"], "analyzer-checker-help-hidden">, - HelpText<"Display the list of analyzer checkers that are available, " - "including modeling checkers">; +def analyzer_checker_help_alpha : Flag<["-"], "analyzer-checker-help-alpha">, + HelpText<"Display the list of in development analyzer checkers. These " + "are NOT considered safe, they are unstable and will emit incorrect " + "reports. Enable ONLY FOR DEVELOPMENT purposes">; + +def analyzer_checker_help_developer : Flag<["-"], "analyzer-checker-help-developer">, + HelpText<"Display the list of developer-only checkers such as modeling " + "and debug checkers">; def analyzer_config_help : Flag<["-"], "analyzer-config-help">, HelpText<"Display the list of -analyzer-config options">; Index: include/clang/StaticAnalyzer/Checkers/CheckerBase.td =================================================================== --- include/clang/StaticAnalyzer/Checkers/CheckerBase.td +++ include/clang/StaticAnalyzer/Checkers/CheckerBase.td @@ -111,6 +111,6 @@ list Dependencies = Deps; } -/// Marks a checker or a package hidden. Hidden entries won't be displayed in -/// -analyzer-checker-help, which is desirable for alpha or modeling checkers. +/// Marks a checker or a package hidden. Hidden entries are meant for developers +/// only, and aren't exposed to end users. class Hidden { bit Hidden = 1; } Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.h =================================================================== --- include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -220,7 +220,8 @@ unsigned DisableAllChecks : 1; unsigned ShowCheckerHelp : 1; - unsigned ShowCheckerHelpHidden : 1; + unsigned ShowCheckerHelpAlpha : 1; + unsigned ShowCheckerHelpDeveloper : 1; unsigned ShowEnabledCheckerList : 1; unsigned ShowCheckerOptionList : 1; unsigned ShowConfigOptionsList : 1; @@ -285,12 +286,13 @@ AnalyzerOptions() : DisableAllChecks(false), ShowCheckerHelp(false), - ShowCheckerHelpHidden(false), ShowEnabledCheckerList(false), - ShowCheckerOptionList(false), ShowConfigOptionsList(false), - AnalyzeAll(false), AnalyzerDisplayProgress(false), - AnalyzeNestedBlocks(false), eagerlyAssumeBinOpBifurcation(false), - TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), - UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false) { + ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false), + ShowEnabledCheckerList(false), ShowCheckerOptionList(false), + ShowConfigOptionsList(false), AnalyzeAll(false), + AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), + eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), + visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), + PrintStats(false), NoRetryExhausted(false) { llvm::sort(AnalyzerConfigCmdFlags); } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -285,7 +285,9 @@ } Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); - Opts.ShowCheckerHelpHidden = Args.hasArg(OPT_analyzer_checker_help_hidden); + Opts.ShowCheckerHelpAlpha = Args.hasArg(OPT_analyzer_checker_help_alpha); + Opts.ShowCheckerHelpDeveloper = + Args.hasArg(OPT_analyzer_checker_help_developer); Opts.ShowCheckerOptionList = Args.hasArg(OPT_analyzer_checker_option_help); Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help); Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); Index: lib/FrontendTool/ExecuteCompilerInvocation.cpp =================================================================== --- lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -238,7 +238,8 @@ AnalyzerOptions &AnOpts = *Clang->getAnalyzerOpts(); // Honor -analyzer-checker-help and -analyzer-checker-help-hidden. - if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpHidden) { + if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpAlpha || + AnOpts.ShowCheckerHelpDeveloper) { ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins, AnOpts, Index: lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp =================================================================== --- lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp +++ lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp @@ -514,13 +514,40 @@ } const size_t InitialPad = 2; - for (const auto &Checker : Checkers) { - if (!AnOpts.ShowCheckerHelpHidden && Checker.IsHidden) - continue; - AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Checker.Desc}, + auto Print = [=](llvm::raw_ostream &Out, const CheckerInfo &Checker, + StringRef Description) { + AnalyzerOptions::printFormattedEntry(Out, {Checker.FullName, Description}, InitialPad, OptionFieldWidth); Out << '\n'; + }; + + for (const auto &Checker : Checkers) { + // The order of this if branches is significant, we wouldn't like to display + // developer checkers even in the alpha output. For example, + // alpha.cplusplus.IteratorModeling is a modeling checker, hence it's hidden + // by default, and users (even when the user is a developer of an alpha + // checker) shouldn't normally tinker with whether they should be enabled. + + if (Checker.IsHidden) { + if (AnOpts.ShowCheckerHelpDeveloper) + Print(Out, Checker, Checker.Desc); + continue; + } + + if (Checker.FullName.startswith("alpha")) { + if (AnOpts.ShowCheckerHelpAlpha) + Print(Out, Checker, + ("(Enable only for development!) " + Checker.Desc).str()); + continue; + } + + if (AnOpts.ShowCheckerHelp) { + if (Checker.FullName.startswith("beta")) + Print(Out, Checker, ("(Experimental) " + Checker.Desc).str()); + else + Print(Out, Checker, Checker.Desc); + } } } Index: test/Analysis/show-checker-list.c =================================================================== --- test/Analysis/show-checker-list.c +++ test/Analysis/show-checker-list.c @@ -1,11 +1,60 @@ // RUN: %clang_cc1 -analyzer-checker-help \ -// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE -// RUN: %clang_cc1 -analyzer-checker-help-hidden \ -// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-HIDDEN +// RUN: %clang_cc1 -analyzer-checker-help-alpha \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-ALPHA -// CHECK: core.DivideZero -// CHECK-HIDDEN: core.DivideZero +// RUN: %clang_cc1 -analyzer-checker-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-DEVELOPER -// CHECK-NOT: unix.DynamicMemoryModeling -// CHECK-HIDDEN: unix.DynamicMemoryModeling +// RUN: %clang_cc1 -analyzer-checker-help-developer \ +// RUN: -analyzer-checker-help-alpha \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-DEVELOPER-ALPHA + +// RUN: %clang_cc1 -analyzer-checker-help \ +// RUN: -analyzer-checker-help-alpha \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE-ALPHA + +// RUN: %clang_cc1 -analyzer-checker-help \ +// RUN: -analyzer-checker-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE-DEVELOPER + +// RUN: %clang_cc1 -analyzer-checker-help \ +// RUN: -analyzer-checker-help-alpha \ +// RUN: -analyzer-checker-help-developer \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-STABLE-ALPHA-DEVELOPER + +// CHECK-STABLE-NOT: alpha.unix.Chroot +// CHECK-DEVELOPER-NOT: alpha.unix.Chroot +// CHECK-ALPHA: alpha.unix.Chroot + +// Note that alpha.cplusplus.IteratorModeling is not only an alpha, but also a +// hidden checker. In this case, we'd only like to see it in the developer list. +// CHECK-ALPHA-NOT: alpha.cplusplus.IteratorModeling +// CHECK-DEVELOPER: alpha.cplusplus.IteratorModeling + +// CHECK-STABLE: core.DivideZero +// CHECK-DEVELOPER-NOT: core.DivideZero +// CHECK-ALPHA-NOT: core.DivideZero + +// CHECK-STABLE-NOT: debug.ConfigDumper +// CHECK-DEVELOPER: debug.ConfigDumper +// CHECK-ALPHA-NOT: debug.ConfigDumper + + +// CHECK-STABLE-ALPHA: alpha.unix.Chroot +// CHECK-DEVELOPER-ALPHA: alpha.unix.Chroot +// CHECK-STABLE-DEVELOPER-NOT: alpha.unix.Chroot + +// CHECK-STABLE-ALPHA: core.DivideZero +// CHECK-DEVELOPER-ALPHA-NOT: core.DivideZero +// CHECK-STABLE-DEVELOPER: core.DivideZero + +// CHECK-STABLE-ALPHA-NOT: debug.ConfigDumper +// CHECK-DEVELOPER-ALPHA: debug.ConfigDumper +// CHECK-STABLE-DEVELOPER: debug.ConfigDumper + + +// CHECK-STABLE-ALPHA-DEVELOPER: alpha.unix.Chroot +// CHECK-STABLE-ALPHA-DEVELOPER: core.DivideZero +// CHECK-STABLE-ALPHA-DEVELOPER: debug.ConfigDumper