Skip to content

Commit

Permalink
[analyzer] Don't display implementation checkers under -analyzer-chec…
Browse files Browse the repository at this point in the history
…ker-help, but do under the new flag -analyzer-checker-help-hidden

During my work on analyzer dependencies, I created a great amount of new
checkers that emitted no diagnostics at all, and were purely modeling some
function or another.

However, the user shouldn't really disable/enable these by hand, hence this
patch, which hides these by default. I intentionally chose not to hide alpha
checkers, because they have a scary enough name, in my opinion, to cause no
surprise when they emit false positives or cause crashes.

The patch introduces the Hidden bit into the TableGen files (you may remember
it before I removed it in D53995), and checkers that are either marked as
hidden, or are in a package that is marked hidden won't be displayed under
-analyzer-checker-help. -analyzer-checker-help-hidden, a new flag meant for
developers only, displays the full list.

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

llvm-svn: 359720
  • Loading branch information
Kristof Umann committed May 1, 2019
1 parent 20c5676 commit 9f7fc98
Show file tree
Hide file tree
Showing 13 changed files with 103 additions and 40 deletions.
6 changes: 5 additions & 1 deletion clang/include/clang/Driver/CC1Options.td
Expand Up @@ -107,7 +107,7 @@ def analyzer_checker : Separate<["-"], "analyzer-checker">,
ValuesCode<[{
const char *Values =
#define GET_CHECKERS
#define CHECKER(FULLNAME, CLASS, HT, DOC_URI) FULLNAME ","
#define CHECKER(FULLNAME, CLASS, HT, DOC_URI, IS_HIDDEN) FULLNAME ","
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef GET_CHECKERS
#define GET_PACKAGES
Expand All @@ -130,6 +130,10 @@ def analyzer_disable_all_checks : Flag<["-"], "analyzer-disable-all-checks">,
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_config_help : Flag<["-"], "analyzer-config-help">,
HelpText<"Display the list of -analyzer-config options">;

Expand Down
Expand Up @@ -26,7 +26,7 @@ class CheckerManager;
class CheckerRegistry;

#define GET_CHECKERS
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \
void register##CLASS(CheckerManager &mgr); \
bool shouldRegister##CLASS(const LangOptions &LO);
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
Expand Up @@ -49,6 +49,7 @@ class Package<string name> {
// This field is optional.
list<CmdLineOption> PackageOptions;
Package ParentPackage;
bit Hidden = 0;
}

/// Describes a 'super' package that holds another package inside it. This is
Expand Down Expand Up @@ -91,6 +92,7 @@ class Checker<string name = ""> {
list<Checker> Dependencies;
bits<2> Documentation;
Package ParentPackage;
bit Hidden = 0;
}

/// Describes a list of checker options.
Expand All @@ -108,3 +110,7 @@ class CheckerOptions<list<CmdLineOption> opts> {
class Dependencies<list<Checker> Deps = []> {
list<Checker> 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.
class Hidden { bit Hidden = 1; }
47 changes: 30 additions & 17 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Expand Up @@ -20,7 +20,7 @@ include "CheckerBase.td"
def Alpha : Package<"alpha">;

def Core : Package<"core">;
def CoreBuiltin : Package<"builtin">, ParentPackage<Core>;
def CoreBuiltin : Package<"builtin">, ParentPackage<Core>, Hidden;
def CoreUninitialized : Package<"uninitialized">, ParentPackage<Core>;
def CoreAlpha : Package<"core">, ParentPackage<Alpha>;

Expand Down Expand Up @@ -97,10 +97,10 @@ def LLVMAlpha : Package<"llvm">, ParentPackage<Alpha>;
// The APIModeling package is for checkers that model APIs and don't perform
// any diagnostics. These checkers are always turned on; this package is
// intended for API modeling that is not controlled by the target triple.
def APIModeling : Package<"apiModeling">;
def GoogleAPIModeling : Package<"google">, ParentPackage<APIModeling>;
def APIModeling : Package<"apiModeling">, Hidden;
def GoogleAPIModeling : Package<"google">, ParentPackage<APIModeling>, Hidden;

def Debug : Package<"debug">;
def Debug : Package<"debug">, Hidden;

def CloneDetectionAlpha : Package<"clone">, ParentPackage<Alpha>;

Expand Down Expand Up @@ -141,7 +141,8 @@ def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">,

def StackAddrEscapeBase : Checker<"StackAddrEscapeBase">,
HelpText<"Generate information about stack address escapes.">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def StackAddrEscapeChecker : Checker<"StackAddressEscape">,
HelpText<"Check that addresses to stack memory do not escape the function">,
Expand All @@ -154,7 +155,8 @@ def DynamicTypePropagation : Checker<"DynamicTypePropagation">,

def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">,
HelpText<"Assume that const string-like globals are non-null">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

} // end "core"

Expand Down Expand Up @@ -231,7 +233,8 @@ let ParentPackage = Nullability in {

def NullabilityBase : Checker<"NullabilityBase">,
HelpText<"Stores information during the analysis about nullability.">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def NullPassedToNonnullChecker : Checker<"NullPassedToNonnull">,
HelpText<"Warns when a null pointer is passed to a pointer which has a "
Expand Down Expand Up @@ -336,7 +339,8 @@ def CStringModeling : Checker<"CStringModeling">,
HelpText<"The base of several CString related checkers. On it's own it emits "
"no reports, but adds valuable information to the analysis when "
"enabled.">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def CStringNullArg : Checker<"NullArg">,
HelpText<"Check for null pointers being passed as arguments to C string "
Expand Down Expand Up @@ -390,7 +394,8 @@ def DynamicMemoryModeling: Checker<"DynamicMemoryModeling">,
"false">
]>,
Dependencies<[CStringModeling]>,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def MallocChecker: Checker<"Malloc">,
HelpText<"Check for memory leaks, double free, and use-after-free problems. "
Expand Down Expand Up @@ -462,11 +467,13 @@ def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">,

def CXXSelfAssignmentChecker : Checker<"SelfAssignment">,
HelpText<"Checks C++ copy and move assignment operators for self assignment">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def SmartPtrModeling: Checker<"SmartPtr">,
HelpText<"Model behavior of C++ smart pointers">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def MoveChecker: Checker<"Move">,
HelpText<"Find use-after-move bugs in C++">,
Expand Down Expand Up @@ -559,7 +566,8 @@ def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">,

def IteratorModeling : Checker<"IteratorModeling">,
HelpText<"Models iterators of C++ containers">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
HelpText<"Check for use of invalidated iterators">,
Expand Down Expand Up @@ -588,7 +596,8 @@ let ParentPackage = Valist in {

def ValistBase : Checker<"ValistBase">,
HelpText<"Gathers information about va_lists.">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def UninitializedChecker : Checker<"Uninitialized">,
HelpText<"Check for usages of uninitialized (or already released) va_lists.">,
Expand Down Expand Up @@ -655,7 +664,8 @@ let ParentPackage = InsecureAPI in {

def SecuritySyntaxChecker : Checker<"SecuritySyntaxChecker">,
HelpText<"Base of various security function related checkers">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def bcmp : Checker<"bcmp">,
HelpText<"Warn on uses of the 'bcmp' function">,
Expand Down Expand Up @@ -787,15 +797,17 @@ let ParentPackage = Cocoa in {

def RetainCountBase : Checker<"RetainCountBase">,
HelpText<"Common base of various retain count related checkers">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

} // end "osx.cocoa"

let ParentPackage = OSX in {

def NSOrCFErrorDerefChecker : Checker<"NSOrCFErrorDerefChecker">,
HelpText<"Implementation checker for NSErrorChecker and CFErrorChecker">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def NumberObjectConversionChecker : Checker<"NumberObjectConversion">,
HelpText<"Check for erroneous conversions of objects representing numbers "
Expand Down Expand Up @@ -962,7 +974,8 @@ def IvarInvalidationModeling : Checker<"IvarInvalidationModeling">,
HelpText<"Gathers information for annotation driven invalidation checking "
"for classes that contains a method annotated with "
"'objc_instance_variable_invalidator'">,
Documentation<NotDocumented>;
Documentation<NotDocumented>,
Hidden;

def InstanceVariableInvalidation : Checker<"InstanceVariableInvalidation">,
HelpText<"Check that the invalidatable instance variables are invalidated in "
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
Expand Up @@ -197,6 +197,7 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
unsigned DisableAllChecks : 1;

unsigned ShowCheckerHelp : 1;
unsigned ShowCheckerHelpHidden : 1;
unsigned ShowEnabledCheckerList : 1;
unsigned ShowConfigOptionsList : 1;
unsigned ShouldEmitErrorsOnInvalidConfigValue : 1;
Expand Down
15 changes: 10 additions & 5 deletions clang/include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
Expand Up @@ -137,6 +137,7 @@ class CheckerRegistry {
StringRef Desc;
StringRef DocumentationUri;
CmdLineOptionList CmdLineOptions;
bool IsHidden = false;
StateFromCmdLine State = StateFromCmdLine::State_Unspecified;

ConstCheckerInfoList Dependencies;
Expand All @@ -150,9 +151,10 @@ class CheckerRegistry {
}

CheckerInfo(InitializationFunction Fn, ShouldRegisterFunction sfn,
StringRef Name, StringRef Desc, StringRef DocsUri)
StringRef Name, StringRef Desc, StringRef DocsUri,
bool IsHidden)
: Initialize(Fn), ShouldRegister(sfn), FullName(Name), Desc(Desc),
DocumentationUri(DocsUri) {}
DocumentationUri(DocsUri), IsHidden(IsHidden) {}

// Used for lower_bound.
explicit CheckerInfo(StringRef FullName) : FullName(FullName) {}
Expand Down Expand Up @@ -190,16 +192,19 @@ class CheckerRegistry {
/// Adds a checker to the registry. Use this non-templated overload when your
/// checker requires custom initialization.
void addChecker(InitializationFunction Fn, ShouldRegisterFunction sfn,
StringRef FullName, StringRef Desc, StringRef DocsUri);
StringRef FullName, StringRef Desc, StringRef DocsUri,
bool IsHidden);

/// Adds a checker to the registry. Use this templated overload when your
/// checker does not require any custom initialization.
template <class T>
void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri) {
void addChecker(StringRef FullName, StringRef Desc, StringRef DocsUri,
bool IsHidden = false) {
// Avoid MSVC's Compiler Error C2276:
// http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
addChecker(&CheckerRegistry::initializeManager<T>,
&CheckerRegistry::returnTrue<T>, FullName, Desc, DocsUri);
&CheckerRegistry::returnTrue<T>, FullName, Desc, DocsUri,
IsHidden);
}

/// Makes the checker with the full name \p fullName depends on the checker
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -285,6 +285,7 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
}

Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help);
Opts.ShowCheckerHelpHidden = Args.hasArg(OPT_analyzer_checker_help_hidden);
Opts.ShowConfigOptionsList = Args.hasArg(OPT_analyzer_config_help);
Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers);
Opts.ShouldEmitErrorsOnInvalidConfigValue =
Expand Down
16 changes: 9 additions & 7 deletions clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
Expand Up @@ -234,28 +234,30 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
}

#if CLANG_ENABLE_STATIC_ANALYZER
// Honor -analyzer-checker-help.
// This should happen AFTER plugins have been loaded!
if (Clang->getAnalyzerOpts()->ShowCheckerHelp) {
// These should happen AFTER plugins have been loaded!

AnalyzerOptions &AnOpts = *Clang->getAnalyzerOpts();
// Honor -analyzer-checker-help and -analyzer-checker-help-hidden.
if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpHidden) {
ento::printCheckerHelp(llvm::outs(),
Clang->getFrontendOpts().Plugins,
*Clang->getAnalyzerOpts(),
AnOpts,
Clang->getDiagnostics(),
Clang->getLangOpts());
return true;
}

// Honor -analyzer-list-enabled-checkers.
if (Clang->getAnalyzerOpts()->ShowEnabledCheckerList) {
if (AnOpts.ShowEnabledCheckerList) {
ento::printEnabledCheckerList(llvm::outs(),
Clang->getFrontendOpts().Plugins,
*Clang->getAnalyzerOpts(),
AnOpts,
Clang->getDiagnostics(),
Clang->getLangOpts());
}

// Honor -analyzer-config-help.
if (Clang->getAnalyzerOpts()->ShowConfigOptionsList) {
if (AnOpts.ShowConfigOptionsList) {
ento::printAnalyzerConfigList(llvm::outs());
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
Expand Up @@ -33,7 +33,7 @@ std::vector<StringRef>
AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental /* = false */) {
static const StringRef StaticAnalyzerChecks[] = {
#define GET_CHECKERS
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \
FULLNAME,
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef CHECKER
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp
Expand Up @@ -256,7 +256,7 @@ static json::Object createResult(const PathDiagnostic &Diag, json::Array &Files,
static StringRef getRuleDescription(StringRef CheckName) {
return llvm::StringSwitch<StringRef>(CheckName)
#define GET_CHECKERS
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \
.Case(FULLNAME, HELPTEXT)
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef CHECKER
Expand All @@ -267,7 +267,7 @@ static StringRef getRuleDescription(StringRef CheckName) {
static StringRef getRuleHelpURIStr(StringRef CheckName) {
return llvm::StringSwitch<StringRef>(CheckName)
#define GET_CHECKERS
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \
.Case(FULLNAME, DOC_URI)
#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
#undef CHECKER
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
Expand Up @@ -115,9 +115,9 @@ CheckerRegistry::CheckerRegistry(

// Register builtin checkers.
#define GET_CHECKERS
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI) \
#define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \
addChecker(register##CLASS, shouldRegister##CLASS, FULLNAME, HELPTEXT, \
DOC_URI);
DOC_URI, IS_HIDDEN);

#define GET_PACKAGES
#define PACKAGE(FULLNAME) addPackage(FULLNAME);
Expand Down Expand Up @@ -350,8 +350,9 @@ void CheckerRegistry::addPackageOption(StringRef OptionType,

void CheckerRegistry::addChecker(InitializationFunction Rfn,
ShouldRegisterFunction Sfn, StringRef Name,
StringRef Desc, StringRef DocsUri) {
Checkers.emplace_back(Rfn, Sfn, Name, Desc, DocsUri);
StringRef Desc, StringRef DocsUri,
bool IsHidden) {
Checkers.emplace_back(Rfn, Sfn, Name, Desc, DocsUri, IsHidden);

// Record the presence of the checker in its packages.
StringRef PackageName, LeafName;
Expand Down Expand Up @@ -421,6 +422,9 @@ void CheckerRegistry::printCheckerWithDescList(raw_ostream &Out,

const size_t InitialPad = 2;
for (const auto &Checker : Checkers) {
if (!AnOpts.ShowCheckerHelpHidden && Checker.IsHidden)
continue;

Out.indent(InitialPad) << Checker.FullName;

int Pad = OptionFieldWidth - Checker.FullName.size();
Expand Down
11 changes: 11 additions & 0 deletions clang/test/Analysis/show-checker-list.c
@@ -0,0 +1,11 @@
// RUN: %clang_cc1 -analyzer-checker-help \
// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK

// RUN: %clang_cc1 -analyzer-checker-help-hidden \
// RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-HIDDEN

// CHECK: core.DivideZero
// CHECK-HIDDEN: core.DivideZero

// CHECK-NOT: unix.DynamicMemoryModeling
// CHECK-HIDDEN: unix.DynamicMemoryModeling

0 comments on commit 9f7fc98

Please sign in to comment.