Index: include/clang/Driver/CC1Options.td =================================================================== --- include/clang/Driver/CC1Options.td +++ include/clang/Driver/CC1Options.td @@ -132,7 +132,7 @@ def analyzer_checker_help_hidden : Flag<["-"], "analyzer-checker-help-hidden">, HelpText<"Display the list of analyzer checkers that are available, " - "including modeling checkers">; + "including those meant for development only">; def analyzer_config_help : Flag<["-"], "analyzer-config-help">, HelpText<"Display the list of -analyzer-config options">; @@ -145,6 +145,9 @@ def analyzer_checker_option_help : Flag<["-"], "analyzer-checker-option-help">, HelpText<"Display the list of checker and package options">; +def analyzer_checker_option_help_hidden : Flag<["-"], "analyzer-checker-option-help-hidden">, + HelpText<"Display the list of checker and package options, including those " + "meant for development purposes only">; def analyzer_config_compatibility_mode : Separate<["-"], "analyzer-config-compatibility-mode">, HelpText<"Don't emit errors on invalid analyzer-config inputs">; Index: include/clang/StaticAnalyzer/Checkers/CheckerBase.td =================================================================== --- include/clang/StaticAnalyzer/Checkers/CheckerBase.td +++ include/clang/StaticAnalyzer/Checkers/CheckerBase.td @@ -25,13 +25,22 @@ bits<2> Type = val.Type; } +/// Marks the entry hidden. Hidden entries won't be displayed in +/// -analyzer-checker-option-help. +class HiddenEnum { + bit Val = val; +} +def DontHide : HiddenEnum<0>; +def Hide : HiddenEnum<1>; + /// Describes an option for a checker or a package. class CmdLineOption { + string defaultVal, HiddenEnum isHidden = DontHide> { bits<2> Type = type.Type; - string CmdFlag = cmdFlag; - string Desc = desc; - string DefaultVal = defaultVal; + string CmdFlag = cmdFlag; + string Desc = desc; + string DefaultVal = defaultVal; + bit Hidden = isHidden.Val; } /// Describes a list of package options. @@ -111,6 +120,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 the entry hidden. Hidden entries won't be displayed in +/// -analyzer-checker-help. class Hidden { bit Hidden = 1; } Index: include/clang/StaticAnalyzer/Checkers/Checkers.td =================================================================== --- include/clang/StaticAnalyzer/Checkers/Checkers.td +++ include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -519,7 +519,8 @@ "for each uninitalized field, as opposed to emitting one " "warning per constructor call, and listing the uninitialized " "fields that belongs to it in notes.", - "false">, + "false", + Hide>, CmdLineOptiongetAnalyzerOpts()->ShowCheckerOptionList) { + if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionHiddenList) { ento::printCheckerConfigList(llvm::outs(), Clang->getFrontendOpts().Plugins, *Clang->getAnalyzerOpts(), Index: lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp =================================================================== --- lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp +++ lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp @@ -180,12 +180,12 @@ addDependency(FULLNAME, DEPENDENCY); #define GET_CHECKER_OPTIONS -#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL) \ - addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC); +#define CHECKER_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, IS_HIDDEN) \ + addCheckerOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, IS_HIDDEN); #define GET_PACKAGE_OPTIONS -#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL) \ - addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC); +#define PACKAGE_OPTION(TYPE, FULLNAME, CMDFLAG, DESC, DEFAULT_VAL, IS_HIDDEN) \ + addPackageOption(TYPE, FULLNAME, CMDFLAG, DEFAULT_VAL, DESC, IS_HIDDEN); #include "clang/StaticAnalyzer/Checkers/Checkers.inc" #undef CHECKER_DEPENDENCY @@ -396,10 +396,10 @@ StringRef PackageFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description) { + StringRef Description, bool IsHidden) { PackageOptions.emplace_back( - PackageFullName, - CmdLineOption{OptionType, OptionName, DefaultValStr, Description}); + PackageFullName, CmdLineOption{OptionType, OptionName, DefaultValStr, + Description, IsHidden}); } void CheckerRegistry::addChecker(InitializationFunction Rfn, @@ -421,10 +421,10 @@ StringRef CheckerFullName, StringRef OptionName, StringRef DefaultValStr, - StringRef Description) { + StringRef Description, bool IsHidden) { CheckerOptions.emplace_back( - CheckerFullName, - CmdLineOption{OptionType, OptionName, DefaultValStr, Description}); + CheckerFullName, CmdLineOption{OptionType, OptionName, DefaultValStr, + Description, IsHidden}); } void CheckerRegistry::initializeManager(CheckerManager &CheckerMgr) const { @@ -554,6 +554,9 @@ } for (const std::pair &Entry : OptionMap) { + if (!AnOpts.ShowCheckerOptionHiddenList && Entry.second.IsHidden) + continue; + const CmdLineOption &Option = Entry.second; std::string FullOption = (Entry.first + ":" + Option.OptionName).str(); Index: test/Analysis/analyzer-checker-option-help.c =================================================================== --- test/Analysis/analyzer-checker-option-help.c +++ test/Analysis/analyzer-checker-option-help.c @@ -1,5 +1,8 @@ // RUN: %clang_cc1 -analyzer-checker-option-help 2>&1 | FileCheck %s +// RUN: %clang_cc1 -analyzer-checker-option-help-hidden \ +// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-HIDDEN + // CHECK: OVERVIEW: Clang Static Analyzer Checker and Package Option List // // CHECK: USAGE: -analyzer-config @@ -17,3 +20,6 @@ // CHECK: the first statement in the group is representative // CHECK: for all other statements in the group in // CHECK: terms of complexity. (default: 50) + +// CHECK-NOT: optin.cplusplus.UninitializedObject:NotesAsWarnings +// CHECK-HIDDEN: optin.cplusplus.UninitializedObject:NotesAsWarnings Index: utils/TableGen/ClangSACheckersEmitter.cpp =================================================================== --- utils/TableGen/ClangSACheckersEmitter.cpp +++ utils/TableGen/ClangSACheckersEmitter.cpp @@ -113,6 +113,7 @@ static bool isHidden(const Record *R) { if (R->getValueAsBit("Hidden")) return true; + // Not declared as hidden, check the parent package if it is hidden. if (DefInit *DI = dyn_cast(R->getValueInit("ParentPackage"))) return isHidden(DI->getDef()); @@ -121,21 +122,38 @@ } static void printChecker(llvm::raw_ostream &OS, const Record &R) { - OS << "CHECKER(" << "\""; - OS.write_escaped(getCheckerFullName(&R)) << "\", "; - OS << R.getName() << ", "; - OS << "\""; - OS.write_escaped(getStringValue(R, "HelpText")) << "\", "; - OS << "\""; - OS.write_escaped(getCheckerDocs(R)); - OS << "\", "; - - if (!isHidden(&R)) - OS << "false"; - else - OS << "true"; + OS << "CHECKER(" << "\""; + OS.write_escaped(getCheckerFullName(&R)) << "\", "; + OS << R.getName() << ", "; + OS << "\""; + OS.write_escaped(getStringValue(R, "HelpText")) << "\", "; + OS << "\""; + OS.write_escaped(getCheckerDocs(R)); + OS << "\", "; + + if (!isHidden(&R)) + OS << "false"; + else + OS << "true"; + + OS << ")\n"; +} + +static void printOption(llvm::raw_ostream &OS, StringRef FullName, + const Record &R) { + OS << "\""; + OS.write_escaped(getCheckerOptionType(R)) << "\", \""; + OS.write_escaped(FullName) << "\", "; + OS << '\"' << getStringValue(R, "CmdFlag") << "\", "; + OS << '\"'; + OS.write_escaped(getStringValue(R, "Desc")) << "\", "; + OS << '\"'; + OS.write_escaped(getStringValue(R, "DefaultVal")) << "\", "; - OS << ")\n"; + if (!R.getValueAsBit("Hidden")) + OS << "false"; + else + OS << "true"; } namespace clang { @@ -196,14 +214,8 @@ std::vector PackageOptions = Package ->getValueAsListOfDefs("PackageOptions"); for (Record *PackageOpt : PackageOptions) { - OS << "PACKAGE_OPTION(\""; - OS.write_escaped(getCheckerOptionType(*PackageOpt)) << "\", \""; - OS.write_escaped(getPackageFullName(Package)) << "\", "; - OS << '\"' << getStringValue(*PackageOpt, "CmdFlag") << "\", "; - OS << '\"'; - OS.write_escaped(getStringValue(*PackageOpt, "Desc")) << "\", "; - OS << '\"'; - OS.write_escaped(getStringValue(*PackageOpt, "DefaultVal")) << "\""; + OS << "PACKAGE_OPTION("; + printOption(OS, getPackageFullName(Package), *PackageOpt); OS << ")\n"; } } @@ -277,16 +289,9 @@ std::vector CheckerOptions = Checker ->getValueAsListOfDefs("CheckerOptions"); for (Record *CheckerOpt : CheckerOptions) { - OS << "CHECKER_OPTION(\""; - OS << getCheckerOptionType(*CheckerOpt) << "\", \""; - OS.write_escaped(getCheckerFullName(Checker)) << "\", "; - OS << '\"' << getStringValue(*CheckerOpt, "CmdFlag") << "\", "; - OS << '\"'; - OS.write_escaped(getStringValue(*CheckerOpt, "Desc")) << "\", "; - OS << '\"'; - OS.write_escaped(getStringValue(*CheckerOpt, "DefaultVal")) << "\""; - OS << ")"; - OS << '\n'; + OS << "CHECKER_OPTION("; + printOption(OS, getCheckerFullName(Checker), *CheckerOpt); + OS << ")\n"; } } OS << "#endif // GET_CHECKER_OPTIONS\n"