r346113 - [analyzer] Restrict AnalyzerOptions' interface so that non-checker objects have to be registered
Kristof Umann via cfe-commits
cfe-commits at lists.llvm.org
Sun Nov 4 19:50:38 PST 2018
Author: szelethus
Date: Sun Nov 4 19:50:37 2018
New Revision: 346113
URL: http://llvm.org/viewvc/llvm-project?rev=346113&view=rev
Log:
[analyzer] Restrict AnalyzerOptions' interface so that non-checker objects have to be registered
One of the reasons why AnalyzerOptions is so chaotic is that options can be
retrieved from the command line whenever and wherever. This allowed for some
options to be forgotten for a looooooong time. Have you ever heard of
"region-store-small-struct-limit"? In order to prevent this in the future, I'm
proposing to restrict AnalyzerOptions' interface so that only checker options
can be retrieved without special getters. I would like to make every option be
accessible only through a getter, but checkers from plugins are a thing, so I'll
have to figure something out for that.
This also forces developers who'd like to add a new option to register it
properly in the .def file.
This is done by
* making the third checker pointer parameter non-optional, and checked by an
assert to be non-null.
* I added new, but private non-checkers option initializers, meant only for
internal use,
* Renamed these methods accordingly (mind the consistent name for once with
getBooleanOption!):
- getOptionAsString -> getCheckerStringOption,
- getOptionAsInteger -> getCheckerIntegerOption
* The 3 functions meant for initializing data members (with the not very
descriptive getBooleanOption, getOptionAsString and getOptionAsUInt names)
were renamed to be overloads of the getAndInitOption function name.
* All options were in some way retrieved via getCheckerOption. I removed it, and
moved the logic to getStringOption and getCheckerStringOption. This did cause
some code duplication, but that's the only way I could do it, now that checker
and non-checker options are separated. Note that the non-checker version
inserts the new option to the ConfigTable with the default value, but the
checker version only attempts to find already existing entries. This is how
it always worked, but this is clunky and I might end reworking that too, so we
can eventually get a ConfigTable that contains the entire configuration of the
analyzer.
Differential Revision: https://reviews.llvm.org/D53483
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
cfe/trunk/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Sun Nov 4 19:50:37 2018
@@ -137,6 +137,28 @@ enum UserModeKind {
UMK_Deep = 2
};
+/// Stores options for the analyzer from the command line.
+///
+/// Some options are frontend flags (e.g.: -analyzer-output), but some are
+/// analyzer configuration options, which are preceded by -analyzer-config
+/// (e.g.: -analyzer-config notes-as-events=true).
+///
+/// If you'd like to add a new frontend flag, add it to
+/// include/clang/Driver/CC1Options.td, add a new field to store the value of
+/// that flag in this class, and initialize it in
+/// lib/Frontend/CompilerInvocation.cpp.
+///
+/// If you'd like to add a new non-checker configuration, register it in
+/// include/clang/StaticAnalyzer/Core/AnalyzerOptions.def, and refer to the
+/// top of the file for documentation.
+///
+/// If you'd like to add a new checker option, call getChecker*Option()
+/// whenever.
+///
+/// Some of the options are controlled by raw frontend flags for no good reason,
+/// and should be eventually converted into -analyzer-config flags. New analyzer
+/// options should not be implemented as frontend flags. Frontend flags still
+/// make sense for things that do not affect the actual analysis.
class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
public:
using ConfigTable = llvm::StringMap<std::string>;
@@ -209,32 +231,21 @@ private:
#undef ANALYZER_OPTION
#undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE
- /// A helper function that retrieves option for a given full-qualified
- /// checker name.
- /// Options for checkers can be specified via 'analyzer-config' command-line
- /// option.
- /// Example:
- /// @code-analyzer-config unix.Malloc:OptionName=CheckerOptionValue @endcode
- /// or @code-analyzer-config unix:OptionName=GroupOptionValue @endcode
- /// for groups of checkers.
- /// @param [in] CheckerName Full-qualified checker name, like
- /// alpha.unix.StreamChecker.
- /// @param [in] OptionName Name of the option to get.
- /// @param [in] Default Default value if no option is specified.
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- /// @retval CheckerOptionValue An option for a checker if it was specified.
- /// @retval GroupOptionValue An option for group if it was specified and no
- /// checker-specific options were found. The closer group to checker,
- /// the more priority it has. For example, @c coregroup.subgroup has more
- /// priority than @c coregroup for @c coregroup.subgroup.CheckerName checker.
- /// @retval Default If nor checker option, nor group option was found.
- StringRef getCheckerOption(StringRef CheckerName, StringRef OptionName,
- StringRef Default,
- bool SearchInParents = false);
+ /// Query an option's string value.
+ ///
+ /// If an option value is not provided, returns the given \p DefaultVal.
+ /// @param [in] Name Name for option to retrieve.
+ /// @param [in] DefaultVal Default value returned if no such option was
+ /// specified.
+ StringRef getStringOption(StringRef OptionName, StringRef DefaultVal);
+ void initOption(Optional<StringRef> &V, StringRef Name,
+ StringRef DefaultVal);
+
+ void initOption(Optional<bool> &V, StringRef Name, bool DefaultVal);
+
+ void initOption(Optional<unsigned> &V, StringRef Name,
+ unsigned DefaultVal);
public:
AnalyzerOptions()
: DisableAllChecks(false), ShowCheckerHelp(false),
@@ -252,34 +263,17 @@ public:
/// @param [in] Name Name for option to retrieve.
/// @param [in] DefaultVal Default value returned if no such option was
/// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
+ /// @param [in] C The checker object the option belongs to. Checker options
+ /// are retrieved in the following format:
+ /// `-analyzer-config <package and checker name>:OptionName=Value.
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
/// ones.
- bool getBooleanOption(StringRef Name, bool DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
+ bool getCheckerBooleanOption(StringRef Name, bool DefaultVal,
+ const ento::CheckerBase *C,
+ bool SearchInParents = false) const;
- /// Variant that accepts a Optional value to cache the result.
- ///
- /// @param [in,out] V Return value storage, returned if parameter contains
- /// an existing valid option, else it is used to store a return value
- /// @param [in] Name Name for option to retrieve.
- /// @param [in] DefaultVal Default value returned if no such option was
- /// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- bool getBooleanOption(Optional<bool> &V, StringRef Name, bool DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
/// Interprets an option's string value as an integer value.
///
@@ -287,21 +281,16 @@ public:
/// @param [in] Name Name for option to retrieve.
/// @param [in] DefaultVal Default value returned if no such option was
/// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
+ /// @param [in] C The checker object the option belongs to. Checker options
+ /// are retrieved in the following format:
+ /// `-analyzer-config <package and checker name>:OptionName=Value.
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
/// ones.
- int getOptionAsInteger(StringRef Name, int DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
-
- unsigned getOptionAsUInt(Optional<unsigned> &V, StringRef Name,
- unsigned DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
+ int getCheckerIntegerOption(StringRef Name, int DefaultVal,
+ const ento::CheckerBase *C,
+ bool SearchInParents = false) const;
/// Query an option's string value.
///
@@ -309,29 +298,38 @@ public:
/// @param [in] Name Name for option to retrieve.
/// @param [in] DefaultVal Default value returned if no such option was
/// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// depending on search mode).
+ /// @param [in] C The checker object the option belongs to. Checker options
+ /// are retrieved in the following format:
+ /// `-analyzer-config <package and checker name>:OptionName=Value.
/// @param [in] SearchInParents If set to true and the searched option was not
/// specified for the given checker the options for the parent packages will
/// be searched as well. The inner packages take precedence over the outer
/// ones.
- StringRef getOptionAsString(StringRef Name, StringRef DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
-
- StringRef getOptionAsString(Optional<StringRef> &V, StringRef Name,
- StringRef DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
+ StringRef getCheckerStringOption(StringRef Name, StringRef DefaultVal,
+ const ento::CheckerBase *C,
+ bool SearchInParents = false) const;
#define ANALYZER_OPTION_GEN_FN(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL, \
- CREATE_FN) \
- TYPE CREATE_FN();
+ CREATE_FN) \
+ TYPE CREATE_FN() { \
+ initOption(NAME, CMDFLAG, DEFAULT_VAL); \
+ return NAME.getValue(); \
+ }
#define ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE( \
TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, DEEP_VAL, CREATE_FN) \
- TYPE CREATE_FN();
+ TYPE CREATE_FN() { \
+ switch (getUserMode()) { \
+ case UMK_Shallow: \
+ initOption(NAME, CMDFLAG, SHALLOW_VAL); \
+ break; \
+ case UMK_Deep: \
+ initOption(NAME, CMDFLAG, DEEP_VAL); \
+ break; \
+ } \
+ \
+ return NAME.getValue(); \
+ }
#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp Sun Nov 4 19:50:37 2018
@@ -45,8 +45,8 @@ class AnalysisOrderChecker
check::LiveSymbols> {
bool isCallbackEnabled(AnalyzerOptions &Opts, StringRef CallbackName) const {
- return Opts.getBooleanOption("*", false, this) ||
- Opts.getBooleanOption(CallbackName, false, this);
+ return Opts.getCheckerBooleanOption("*", false, this) ||
+ Opts.getCheckerBooleanOption(CallbackName, false, this);
}
bool isCallbackEnabled(CheckerContext &C, StringRef CallbackName) const {
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CloneChecker.cpp Sun Nov 4 19:50:37 2018
@@ -63,18 +63,18 @@ void CloneChecker::checkEndOfTranslation
// At this point, every statement in the translation unit has been analyzed by
// the CloneDetector. The only thing left to do is to report the found clones.
- int MinComplexity = Mgr.getAnalyzerOptions().getOptionAsInteger(
+ int MinComplexity = Mgr.getAnalyzerOptions().getCheckerIntegerOption(
"MinimumCloneComplexity", 50, this);
assert(MinComplexity >= 0);
- bool ReportSuspiciousClones = Mgr.getAnalyzerOptions().getBooleanOption(
- "ReportSuspiciousClones", true, this);
+ bool ReportSuspiciousClones = Mgr.getAnalyzerOptions()
+ .getCheckerBooleanOption("ReportSuspiciousClones", true, this);
- bool ReportNormalClones = Mgr.getAnalyzerOptions().getBooleanOption(
+ bool ReportNormalClones = Mgr.getAnalyzerOptions().getCheckerBooleanOption(
"ReportNormalClones", true, this);
- StringRef IgnoredFilesPattern = Mgr.getAnalyzerOptions().getOptionAsString(
- "IgnoredFilesPattern", "", this);
+ StringRef IgnoredFilesPattern = Mgr.getAnalyzerOptions()
+ .getCheckerStringOption("IgnoredFilesPattern", "", this);
// Let the CloneDetector create a list of clones from all the analyzed
// statements. We don't filter for matching variable patterns at this point
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/LocalizationChecker.cpp Sun Nov 4 19:50:37 2018
@@ -1398,8 +1398,8 @@ void ento::registerNonLocalizedStringChe
NonLocalizedStringChecker *checker =
mgr.registerChecker<NonLocalizedStringChecker>();
checker->IsAggressive =
- mgr.getAnalyzerOptions().getBooleanOption("AggressiveReport", false,
- checker);
+ mgr.getAnalyzerOptions().getCheckerBooleanOption("AggressiveReport",
+ false, checker);
}
void ento::registerEmptyLocalizationContextChecker(CheckerManager &mgr) {
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Sun Nov 4 19:50:37 2018
@@ -3084,7 +3084,7 @@ markReleased(ProgramStateRef State, Symb
void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
registerCStringCheckerBasic(mgr);
MallocChecker *checker = mgr.registerChecker<MallocChecker>();
- checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption(
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption(
"Optimistic", false, checker);
checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] = true;
checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
@@ -3105,7 +3105,7 @@ void ento::registerNewDeleteLeaksChecker
void ento::registerInnerPointerCheckerAux(CheckerManager &mgr) {
registerCStringCheckerBasic(mgr);
MallocChecker *checker = mgr.registerChecker<MallocChecker>();
- checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption(
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption(
"Optimistic", false, checker);
checker->ChecksEnabled[MallocChecker::CK_InnerPointerChecker] = true;
checker->CheckNames[MallocChecker::CK_InnerPointerChecker] =
@@ -3116,7 +3116,7 @@ void ento::registerInnerPointerCheckerAu
void ento::register##name(CheckerManager &mgr) { \
registerCStringCheckerBasic(mgr); \
MallocChecker *checker = mgr.registerChecker<MallocChecker>(); \
- checker->IsOptimistic = mgr.getAnalyzerOptions().getBooleanOption( \
+ checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption( \
"Optimistic", false, checker); \
checker->ChecksEnabled[MallocChecker::CK_##name] = true; \
checker->CheckNames[MallocChecker::CK_##name] = mgr.getCurrentCheckName(); \
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MmapWriteExecChecker.cpp Sun Nov 4 19:50:37 2018
@@ -82,7 +82,9 @@ void ento::registerMmapWriteExecChecker(
MmapWriteExecChecker *Mwec =
mgr.registerChecker<MmapWriteExecChecker>();
Mwec->ProtExecOv =
- mgr.getAnalyzerOptions().getOptionAsInteger("MmapProtExec", 0x04, Mwec);
+ mgr.getAnalyzerOptions()
+ .getCheckerIntegerOption("MmapProtExec", 0x04, Mwec);
Mwec->ProtReadOv =
- mgr.getAnalyzerOptions().getOptionAsInteger("MmapProtRead", 0x01, Mwec);
+ mgr.getAnalyzerOptions()
+ .getCheckerIntegerOption("MmapProtRead", 0x01, Mwec);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp Sun Nov 4 19:50:37 2018
@@ -1193,7 +1193,7 @@ void NullabilityChecker::printState(raw_
checker->NeedTracking = checker->NeedTracking || trackingRequired; \
checker->NoDiagnoseCallsToSystemHeaders = \
checker->NoDiagnoseCallsToSystemHeaders || \
- mgr.getAnalyzerOptions().getBooleanOption( \
+ mgr.getAnalyzerOptions().getCheckerBooleanOption( \
"NoDiagnoseCallsToSystemHeaders", false, checker, true); \
}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/NumberObjectConversionChecker.cpp Sun Nov 4 19:50:37 2018
@@ -346,5 +346,5 @@ void ento::registerNumberObjectConversio
NumberObjectConversionChecker *Chk =
Mgr.registerChecker<NumberObjectConversionChecker>();
Chk->Pedantic =
- Mgr.getAnalyzerOptions().getBooleanOption("Pedantic", false, Chk);
+ Mgr.getAnalyzerOptions().getCheckerBooleanOption("Pedantic", false, Chk);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/PaddingChecker.cpp Sun Nov 4 19:50:37 2018
@@ -41,7 +41,8 @@ public:
BugReporter &BRArg) const {
BR = &BRArg;
AllowedPad =
- MGR.getAnalyzerOptions().getOptionAsInteger("AllowedPad", 24, this);
+ MGR.getAnalyzerOptions()
+ .getCheckerIntegerOption("AllowedPad", 24, this);
assert(AllowedPad >= 0 && "AllowedPad option should be non-negative");
// The calls to checkAST* from AnalysisConsumer don't
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp Sun Nov 4 19:50:37 2018
@@ -1397,8 +1397,8 @@ void ento::registerRetainCountChecker(Ch
AnalyzerOptions &Options = Mgr.getAnalyzerOptions();
- Chk->IncludeAllocationLine = Options.getBooleanOption(
+ Chk->IncludeAllocationLine = Options.getCheckerBooleanOption(
"leak-diagnostics-reference-allocation", false, Chk);
- Chk->ShouldCheckOSObjectRetainCount = Options.getBooleanOption(
- "CheckOSObject", true, Chk);
+ Chk->ShouldCheckOSObjectRetainCount = Options.getCheckerBooleanOption(
+ "CheckOSObject", true, Chk);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp Sun Nov 4 19:50:37 2018
@@ -488,12 +488,12 @@ void ento::registerUninitializedObjectCh
UninitObjCheckerOptions &ChOpts = Chk->Opts;
ChOpts.IsPedantic =
- AnOpts.getBooleanOption("Pedantic", /*DefaultVal*/ false, Chk);
+ AnOpts.getCheckerBooleanOption("Pedantic", /*DefaultVal*/ false, Chk);
ChOpts.ShouldConvertNotesToWarnings =
- AnOpts.getBooleanOption("NotesAsWarnings", /*DefaultVal*/ false, Chk);
- ChOpts.CheckPointeeInitialization = AnOpts.getBooleanOption(
+ AnOpts.getCheckerBooleanOption("NotesAsWarnings", /*DefaultVal*/ false, Chk);
+ ChOpts.CheckPointeeInitialization = AnOpts.getCheckerBooleanOption(
"CheckPointeeInitialization", /*DefaultVal*/ false, Chk);
ChOpts.IgnoredRecordsWithFieldPattern =
- AnOpts.getOptionAsString("IgnoreRecordsWithField",
+ AnOpts.getCheckerStringOption("IgnoreRecordsWithField",
/*DefaultVal*/ "", Chk);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp Sun Nov 4 19:50:37 2018
@@ -280,5 +280,6 @@ void ento::registerVirtualCallChecker(Ch
VirtualCallChecker *checker = mgr.registerChecker<VirtualCallChecker>();
checker->IsPureOnly =
- mgr.getAnalyzerOptions().getBooleanOption("PureOnly", false, checker);
+ mgr.getAnalyzerOptions().getCheckerBooleanOption("PureOnly", false,
+ checker);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp Sun Nov 4 19:50:37 2018
@@ -51,7 +51,7 @@ AnalyzerOptions::getRegisteredCheckers(b
UserModeKind AnalyzerOptions::getUserMode() {
if (!UserMode.hasValue()) {
- UserMode = getOptionAsString("mode", "deep");
+ UserMode = getStringOption("mode", "deep");
}
auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(*UserMode)
@@ -65,7 +65,7 @@ UserModeKind AnalyzerOptions::getUserMod
ExplorationStrategyKind
AnalyzerOptions::getExplorationStrategy() {
if (!ExplorationStrategy.hasValue()) {
- ExplorationStrategy = getOptionAsString("exploration_strategy",
+ ExplorationStrategy = getStringOption("exploration_strategy",
"unexplored_first_queue");
}
auto K =
@@ -90,10 +90,10 @@ IPAKind AnalyzerOptions::getIPAMode() {
if (!IPAMode.hasValue()) {
switch (getUserMode()) {
case UMK_Shallow:
- IPAMode = getOptionAsString("ipa", "inlining");
+ IPAMode = getStringOption("ipa", "inlining");
break;
case UMK_Deep:
- IPAMode = getOptionAsString("ipa", "dynamic-bifurcate");
+ IPAMode = getStringOption("ipa", "dynamic-bifurcate");
break;
}
}
@@ -112,7 +112,7 @@ IPAKind AnalyzerOptions::getIPAMode() {
bool
AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind Param) {
if (!CXXMemberInliningMode.hasValue()) {
- CXXMemberInliningMode = getOptionAsString("c++-inlining", "destructors");
+ CXXMemberInliningMode = getStringOption("c++-inlining", "destructors");
}
if (getIPAMode() < IPAK_Inlining)
@@ -132,14 +132,62 @@ AnalyzerOptions::mayInlineCXXMemberFunct
return *K >= Param;
}
-static StringRef toString(bool b) { return b ? "true" : "false"; }
+StringRef AnalyzerOptions::getStringOption(StringRef OptionName,
+ StringRef DefaultVal) {
+ return Config.insert({OptionName, DefaultVal}).first->second;
+}
+
+static StringRef toString(bool B) { return (B ? "true" : "false"); }
+
+template <typename T>
+static StringRef toString(T) = delete;
+
+void AnalyzerOptions::initOption(Optional<StringRef> &V, StringRef Name,
+ StringRef DefaultVal) {
+ if (V.hasValue())
+ return;
+
+ V = getStringOption(Name, DefaultVal);
+}
+
+void AnalyzerOptions::initOption(Optional<bool> &V, StringRef Name,
+ bool DefaultVal) {
+ if (V.hasValue())
+ return;
+
+ // FIXME: We should emit a warning here if the value is something other than
+ // "true", "false", or the empty string (meaning the default value),
+ // but the AnalyzerOptions doesn't have access to a diagnostic engine.
+ V = llvm::StringSwitch<bool>(getStringOption(Name, toString(DefaultVal)))
+ .Case("true", true)
+ .Case("false", false)
+ .Default(DefaultVal);
+}
-StringRef AnalyzerOptions::getCheckerOption(StringRef CheckerName,
- StringRef OptionName,
- StringRef Default,
- bool SearchInParents) {
+void AnalyzerOptions::initOption(Optional<unsigned> &V, StringRef Name,
+ unsigned DefaultVal) {
+ if (V.hasValue())
+ return;
+
+ V = DefaultVal;
+ bool HasFailed = getStringOption(Name, std::to_string(DefaultVal))
+ .getAsInteger(10, *V);
+ assert(!HasFailed && "analyzer-config option should be numeric");
+ (void)HasFailed;
+}
+
+StringRef AnalyzerOptions::getCheckerStringOption(StringRef OptionName,
+ StringRef DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) const {
+ assert(C);
// Search for a package option if the option for the checker is not specified
// and search in parents is enabled.
+ StringRef CheckerName = C->getTagDescription();
+
+ assert(!CheckerName.empty() &&
+ "Empty checker name! Make sure the checker object (including it's "
+ "bases!) if fully initialized before calling this function!");
ConfigTable::const_iterator E = Config.end();
do {
ConfigTable::const_iterator I =
@@ -148,127 +196,41 @@ StringRef AnalyzerOptions::getCheckerOpt
return StringRef(I->getValue());
size_t Pos = CheckerName.rfind('.');
if (Pos == StringRef::npos)
- return Default;
+ return DefaultVal;
CheckerName = CheckerName.substr(0, Pos);
} while (!CheckerName.empty() && SearchInParents);
- return Default;
+ return DefaultVal;
}
-bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal,
- const CheckerBase *C,
- bool SearchInParents) {
+bool AnalyzerOptions::getCheckerBooleanOption(StringRef Name, bool DefaultVal,
+ const CheckerBase *C,
+ bool SearchInParents) const {
// FIXME: We should emit a warning here if the value is something other than
// "true", "false", or the empty string (meaning the default value),
// but the AnalyzerOptions doesn't have access to a diagnostic engine.
- StringRef Default = toString(DefaultVal);
- StringRef V =
- C ? getCheckerOption(C->getTagDescription(), Name, Default,
- SearchInParents)
- : getOptionAsString(Name, Default);
- return llvm::StringSwitch<bool>(V)
+ assert(C);
+ return llvm::StringSwitch<bool>(
+ getCheckerStringOption(Name, toString(DefaultVal), C, SearchInParents))
.Case("true", true)
.Case("false", false)
.Default(DefaultVal);
}
-bool AnalyzerOptions::getBooleanOption(Optional<bool> &V, StringRef Name,
- bool DefaultVal, const CheckerBase *C,
- bool SearchInParents) {
- if (!V.hasValue())
- V = getBooleanOption(Name, DefaultVal, C, SearchInParents);
- return V.getValue();
-}
-
-int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal,
+int AnalyzerOptions::getCheckerIntegerOption(StringRef Name, int DefaultVal,
const CheckerBase *C,
- bool SearchInParents) {
- SmallString<10> StrBuf;
- llvm::raw_svector_ostream OS(StrBuf);
- OS << DefaultVal;
-
- StringRef V = C ? getCheckerOption(C->getTagDescription(), Name, OS.str(),
- SearchInParents)
- : getOptionAsString(Name, OS.str());
-
- int Res = DefaultVal;
- bool b = V.getAsInteger(10, Res);
- assert(!b && "analyzer-config option should be numeric");
- (void)b;
- return Res;
-}
-
-unsigned AnalyzerOptions::getOptionAsUInt(Optional<unsigned> &V, StringRef Name,
- unsigned DefaultVal,
- const CheckerBase *C,
- bool SearchInParents) {
- if (!V.hasValue())
- V = getOptionAsInteger(Name, DefaultVal, C, SearchInParents);
- return V.getValue();
-}
-
-StringRef AnalyzerOptions::getOptionAsString(StringRef Name,
- StringRef DefaultVal,
- const CheckerBase *C,
- bool SearchInParents) {
- return C ? getCheckerOption(C->getTagDescription(), Name, DefaultVal,
- SearchInParents)
- : StringRef(
- Config.insert(std::make_pair(Name, DefaultVal)).first->second);
-}
-
-StringRef AnalyzerOptions::getOptionAsString(Optional<StringRef> &V,
- StringRef Name,
- StringRef DefaultVal,
- const ento::CheckerBase *C,
- bool SearchInParents) {
- if (!V.hasValue())
- V = getOptionAsString(Name, DefaultVal, C, SearchInParents);
- return V.getValue();
-}
-
-static bool getOption(AnalyzerOptions &A, Optional<bool> &V, StringRef Name,
- bool DefaultVal) {
- return A.getBooleanOption(V, Name, DefaultVal);
-}
-
-static unsigned getOption(AnalyzerOptions &A, Optional<unsigned> &V,
- StringRef Name, unsigned DefaultVal) {
- return A.getOptionAsUInt(V, Name, DefaultVal);
-}
-
-static StringRef getOption(AnalyzerOptions &A, Optional<StringRef> &V,
- StringRef Name, StringRef DefaultVal) {
- return A.getOptionAsString(V, Name, DefaultVal);
-}
-
-#define ANALYZER_OPTION_GEN_FN(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL, \
- CREATE_FN) \
-TYPE AnalyzerOptions::CREATE_FN() { \
- return getOption(*this, NAME, CMDFLAG, DEFAULT_VAL); \
-}
-
-#define ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE( \
- TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL, DEEP_VAL, CREATE_FN) \
-TYPE AnalyzerOptions::CREATE_FN() { \
- switch (getUserMode()) { \
- case UMK_Shallow: \
- return getOption(*this, NAME, CMDFLAG, SHALLOW_VAL); \
- case UMK_Deep: \
- return getOption(*this, NAME, CMDFLAG, DEEP_VAL); \
- } \
- \
- llvm_unreachable("Unknown usermode!"); \
- return {}; \
+ bool SearchInParents) const {
+ int Ret = DefaultVal;
+ bool HasFailed = getCheckerStringOption(Name, std::to_string(DefaultVal), C,
+ SearchInParents)
+ .getAsInteger(10, Ret);
+ assert(!HasFailed && "analyzer-config option should be numeric");
+ (void)HasFailed;
+ return Ret;
}
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.def"
-
-#undef ANALYZER_OPTION_GEN_FN_DEPENDS_ON_USER_MODE
-#undef ANALYZER_OPTION_WITH_FN
-
StringRef AnalyzerOptions::getCTUDir() {
if (!CTUDir.hasValue()) {
- CTUDir = getOptionAsString("ctu-dir", "");
+ CTUDir = getStringOption("ctu-dir", "");
if (!llvm::sys::fs::is_directory(*CTUDir))
CTUDir = "";
}
Modified: cfe/trunk/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp?rev=346113&r1=346112&r2=346113&view=diff
==============================================================================
--- cfe/trunk/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp (original)
+++ cfe/trunk/unittests/StaticAnalyzer/AnalyzerOptionsTest.cpp Sun Nov 4 19:50:37 2018
@@ -52,23 +52,25 @@ TEST(StaticAnalyzerOptions, SearchInPare
// Checker one has Option specified as true. It should read true regardless of
// search mode.
CheckerOneMock CheckerOne;
- EXPECT_TRUE(Opts.getBooleanOption("Option", false, &CheckerOne));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option", false, &CheckerOne));
// The package option is overridden with a checker option.
- EXPECT_TRUE(Opts.getBooleanOption("Option", false, &CheckerOne, true));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option", false, &CheckerOne,
+ true));
// The Outer package option is overridden by the Inner package option. No
// package option is specified.
- EXPECT_TRUE(Opts.getBooleanOption("Option2", false, &CheckerOne, true));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option2", false, &CheckerOne,
+ true));
// No package option is specified and search in packages is turned off. The
// default value should be returned.
- EXPECT_FALSE(Opts.getBooleanOption("Option2", false, &CheckerOne));
- EXPECT_TRUE(Opts.getBooleanOption("Option2", true, &CheckerOne));
+ EXPECT_FALSE(Opts.getCheckerBooleanOption("Option2", false, &CheckerOne));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option2", true, &CheckerOne));
// Checker true has no option specified. It should get the default value when
// search in parents turned off and false when search in parents turned on.
CheckerTwoMock CheckerTwo;
- EXPECT_FALSE(Opts.getBooleanOption("Option", false, &CheckerTwo));
- EXPECT_TRUE(Opts.getBooleanOption("Option", true, &CheckerTwo));
- EXPECT_FALSE(Opts.getBooleanOption("Option", true, &CheckerTwo, true));
+ EXPECT_FALSE(Opts.getCheckerBooleanOption("Option", false, &CheckerTwo));
+ EXPECT_TRUE(Opts.getCheckerBooleanOption("Option", true, &CheckerTwo));
+ EXPECT_FALSE(Opts.getCheckerBooleanOption("Option", true, &CheckerTwo, true));
}
TEST(StaticAnalyzerOptions, StringOptions) {
@@ -83,9 +85,9 @@ TEST(StaticAnalyzerOptions, StringOption
CheckerOneMock CheckerOne;
EXPECT_TRUE("StringValue" ==
- Opts.getOptionAsString("Option", "DefaultValue", &CheckerOne));
+ Opts.getCheckerStringOption("Option", "DefaultValue", &CheckerOne));
EXPECT_TRUE("DefaultValue" ==
- Opts.getOptionAsString("Option2", "DefaultValue", &CheckerOne));
+ Opts.getCheckerStringOption("Option2", "DefaultValue", &CheckerOne));
}
} // end namespace ento
} // end namespace clang
More information about the cfe-commits
mailing list