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