| //===- AnalyzerOptions.h - Analysis Engine Options --------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This header defines various options for the static analyzer that are set |
| // by the frontend and are consulted throughout the analyzer. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H |
| #define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H |
| |
| #include "clang/Analysis/PathDiagnostic.h" |
| #include "clang/Basic/LLVM.h" |
| #include "llvm/ADT/IntrusiveRefCntPtr.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/StringSwitch.h" |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| namespace clang { |
| |
| namespace ento { |
| |
| class CheckerBase; |
| |
| } // namespace ento |
| |
| /// Analysis - Set of available source code analyses. |
| enum Analyses { |
| #define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME, |
| #include "clang/StaticAnalyzer/Core/Analyses.def" |
| NumAnalyses |
| }; |
| |
| /// AnalysisStores - Set of available analysis store models. |
| enum AnalysisStores { |
| #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, |
| #include "clang/StaticAnalyzer/Core/Analyses.def" |
| NumStores |
| }; |
| |
| /// AnalysisConstraints - Set of available constraint models. |
| enum AnalysisConstraints { |
| #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, |
| #include "clang/StaticAnalyzer/Core/Analyses.def" |
| NumConstraints |
| }; |
| |
| /// AnalysisDiagClients - Set of available diagnostic clients for rendering |
| /// analysis results. |
| enum AnalysisDiagClients { |
| #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME, |
| #include "clang/StaticAnalyzer/Core/Analyses.def" |
| PD_NONE, |
| NUM_ANALYSIS_DIAG_CLIENTS |
| }; |
| |
| /// AnalysisPurgeModes - Set of available strategies for dead symbol removal. |
| enum AnalysisPurgeMode { |
| #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) NAME, |
| #include "clang/StaticAnalyzer/Core/Analyses.def" |
| NumPurgeModes |
| }; |
| |
| /// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics. |
| enum AnalysisInliningMode { |
| #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME, |
| #include "clang/StaticAnalyzer/Core/Analyses.def" |
| NumInliningModes |
| }; |
| |
| /// Describes the different kinds of C++ member functions which can be |
| /// considered for inlining by the analyzer. |
| /// |
| /// These options are cumulative; enabling one kind of member function will |
| /// enable all kinds with lower enum values. |
| enum CXXInlineableMemberKind { |
| // Uninitialized = 0, |
| |
| /// A dummy mode in which no C++ inlining is enabled. |
| CIMK_None, |
| |
| /// Refers to regular member function and operator calls. |
| CIMK_MemberFunctions, |
| |
| /// Refers to constructors (implicit or explicit). |
| /// |
| /// Note that a constructor will not be inlined if the corresponding |
| /// destructor is non-trivial. |
| CIMK_Constructors, |
| |
| /// Refers to destructors (implicit or explicit). |
| CIMK_Destructors |
| }; |
| |
| /// Describes the different modes of inter-procedural analysis. |
| enum IPAKind { |
| /// Perform only intra-procedural analysis. |
| IPAK_None = 1, |
| |
| /// Inline C functions and blocks when their definitions are available. |
| IPAK_BasicInlining = 2, |
| |
| /// Inline callees(C, C++, ObjC) when their definitions are available. |
| IPAK_Inlining = 3, |
| |
| /// Enable inlining of dynamically dispatched methods. |
| IPAK_DynamicDispatch = 4, |
| |
| /// Enable inlining of dynamically dispatched methods, bifurcate paths when |
| /// exact type info is unavailable. |
| IPAK_DynamicDispatchBifurcate = 5 |
| }; |
| |
| enum class ExplorationStrategyKind { |
| DFS, |
| BFS, |
| UnexploredFirst, |
| UnexploredFirstQueue, |
| UnexploredFirstLocationQueue, |
| BFSBlockDFSContents, |
| }; |
| |
| /// Describes the kinds for high-level analyzer mode. |
| enum UserModeKind { |
| /// Perform shallow but fast analyzes. |
| UMK_Shallow = 1, |
| |
| /// Perform deep analyzes. |
| 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>; |
| |
| /// Retrieves the list of checkers generated from Checkers.td. This doesn't |
| /// contain statically linked but non-generated checkers and plugin checkers! |
| static std::vector<StringRef> |
| getRegisteredCheckers(bool IncludeExperimental = false); |
| |
| /// Retrieves the list of packages generated from Checkers.td. This doesn't |
| /// contain statically linked but non-generated packages and plugin packages! |
| static std::vector<StringRef> |
| getRegisteredPackages(bool IncludeExperimental = false); |
| |
| /// Convenience function for printing options or checkers and their |
| /// description in a formatted manner. If \p MinLineWidth is set to 0, no line |
| /// breaks are introduced for the description. |
| /// |
| /// Format, depending whether the option name's length is less than |
| /// \p EntryWidth: |
| /// |
| /// <padding>EntryName<padding>Description |
| /// <---------padding--------->Description |
| /// <---------padding--------->Description |
| /// |
| /// <padding>VeryVeryLongEntryName |
| /// <---------padding--------->Description |
| /// <---------padding--------->Description |
| /// ^~~~~~~~~InitialPad |
| /// ^~~~~~~~~~~~~~~~~~EntryWidth |
| /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~MinLineWidth |
| static void printFormattedEntry(llvm::raw_ostream &Out, |
| std::pair<StringRef, StringRef> EntryDescPair, |
| size_t InitialPad, size_t EntryWidth, |
| size_t MinLineWidth = 0); |
| |
| /// Pairs of checker/package name and enable/disable. |
| std::vector<std::pair<std::string, bool>> CheckersAndPackages; |
| |
| /// Vector of checker/package names which will not emit warnings. |
| std::vector<std::string> SilencedCheckersAndPackages; |
| |
| /// A key-value table of use-specified configuration values. |
| // TODO: This shouldn't be public. |
| ConfigTable Config; |
| AnalysisStores AnalysisStoreOpt = RegionStoreModel; |
| AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel; |
| AnalysisDiagClients AnalysisDiagOpt = PD_HTML; |
| AnalysisPurgeMode AnalysisPurgeOpt = PurgeStmt; |
| |
| std::string AnalyzeSpecificFunction; |
| |
| /// File path to which the exploded graph should be dumped. |
| std::string DumpExplodedGraphTo; |
| |
| /// Store full compiler invocation for reproducible instructions in the |
| /// generated report. |
| std::string FullCompilerInvocation; |
| |
| /// The maximum number of times the analyzer visits a block. |
| unsigned maxBlockVisitOnPath; |
| |
| /// Disable all analyzer checkers. |
| /// |
| /// This flag allows one to disable analyzer checkers on the code processed by |
| /// the given analysis consumer. Note, the code will get parsed and the |
| /// command-line options will get checked. |
| unsigned DisableAllCheckers : 1; |
| |
| unsigned ShowCheckerHelp : 1; |
| unsigned ShowCheckerHelpAlpha : 1; |
| unsigned ShowCheckerHelpDeveloper : 1; |
| |
| unsigned ShowCheckerOptionList : 1; |
| unsigned ShowCheckerOptionAlphaList : 1; |
| unsigned ShowCheckerOptionDeveloperList : 1; |
| |
| unsigned ShowEnabledCheckerList : 1; |
| unsigned ShowConfigOptionsList : 1; |
| unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; |
| unsigned AnalyzeAll : 1; |
| unsigned AnalyzerDisplayProgress : 1; |
| unsigned AnalyzeNestedBlocks : 1; |
| |
| unsigned eagerlyAssumeBinOpBifurcation : 1; |
| |
| unsigned TrimGraph : 1; |
| unsigned visualizeExplodedGraphWithGraphViz : 1; |
| unsigned UnoptimizedCFG : 1; |
| unsigned PrintStats : 1; |
| |
| /// Do not re-analyze paths leading to exhausted nodes with a different |
| /// strategy. We get better code coverage when retry is enabled. |
| unsigned NoRetryExhausted : 1; |
| |
| /// Emit analyzer warnings as errors. |
| bool AnalyzerWerror : 1; |
| |
| /// The inlining stack depth limit. |
| unsigned InlineMaxStackDepth; |
| |
| /// The mode of function selection used during inlining. |
| AnalysisInliningMode InliningMode = NoRedundancy; |
| |
| // Create a field for each -analyzer-config option. |
| #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ |
| SHALLOW_VAL, DEEP_VAL) \ |
| ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL) |
| |
| #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ |
| TYPE NAME; |
| |
| #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" |
| #undef ANALYZER_OPTION |
| #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE |
| |
| // Create an array of all -analyzer-config command line options. Sort it in |
| // the constructor. |
| std::vector<llvm::StringLiteral> AnalyzerConfigCmdFlags = { |
| #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ |
| SHALLOW_VAL, DEEP_VAL) \ |
| ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL) |
| |
| #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ |
| llvm::StringLiteral(CMDFLAG), |
| |
| #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" |
| #undef ANALYZER_OPTION |
| #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE |
| }; |
| |
| bool isUnknownAnalyzerConfig(StringRef Name) const { |
| assert(llvm::is_sorted(AnalyzerConfigCmdFlags)); |
| |
| return !std::binary_search(AnalyzerConfigCmdFlags.begin(), |
| AnalyzerConfigCmdFlags.end(), Name); |
| } |
| |
| AnalyzerOptions() |
| : DisableAllCheckers(false), ShowCheckerHelp(false), |
| ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false), |
| ShowCheckerOptionList(false), ShowCheckerOptionAlphaList(false), |
| ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false), |
| ShowConfigOptionsList(false), AnalyzeAll(false), |
| AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), |
| eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), |
| visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false), |
| PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) { |
| llvm::sort(AnalyzerConfigCmdFlags); |
| } |
| |
| /// Interprets an option's string value as a boolean. The "true" string is |
| /// interpreted as true and the "false" string is interpreted as false. |
| /// |
| /// If an option value is not provided, returns the given \p DefaultVal. |
| /// @param [in] CheckerName The *full name* of the checker. One may retrieve |
| /// this from the checker object's field \c Name, or through \c |
| /// CheckerManager::getCurrentCheckerName within the checker's registry |
| /// function. |
| /// Checker options are retrieved in the following format: |
| /// `-analyzer-config CheckerName:OptionName=Value. |
| /// @param [in] OptionName Name for option to retrieve. |
| /// @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 getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, |
| bool SearchInParents = false) const; |
| |
| bool getCheckerBooleanOption(const ento::CheckerBase *C, StringRef OptionName, |
| bool SearchInParents = false) const; |
| |
| /// Interprets an option's string value as an integer value. |
| /// |
| /// If an option value is not provided, returns the given \p DefaultVal. |
| /// @param [in] CheckerName The *full name* of the checker. One may retrieve |
| /// this from the checker object's field \c Name, or through \c |
| /// CheckerManager::getCurrentCheckerName within the checker's registry |
| /// function. |
| /// Checker options are retrieved in the following format: |
| /// `-analyzer-config CheckerName:OptionName=Value. |
| /// @param [in] OptionName Name for option to retrieve. |
| /// @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 getCheckerIntegerOption(StringRef CheckerName, StringRef OptionName, |
| bool SearchInParents = false) const; |
| |
| int getCheckerIntegerOption(const ento::CheckerBase *C, StringRef OptionName, |
| bool SearchInParents = false) const; |
| |
| /// Query an option's string value. |
| /// |
| /// If an option value is not provided, returns the given \p DefaultVal. |
| /// @param [in] CheckerName The *full name* of the checker. One may retrieve |
| /// this from the checker object's field \c Name, or through \c |
| /// CheckerManager::getCurrentCheckerName within the checker's registry |
| /// function. |
| /// Checker options are retrieved in the following format: |
| /// `-analyzer-config CheckerName:OptionName=Value. |
| /// @param [in] OptionName Name for option to retrieve. |
| /// @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 getCheckerStringOption(StringRef CheckerName, StringRef OptionName, |
| bool SearchInParents = false) const; |
| |
| StringRef getCheckerStringOption(const ento::CheckerBase *C, |
| StringRef OptionName, |
| bool SearchInParents = false) const; |
| |
| /// Retrieves and sets the UserMode. This is a high-level option, |
| /// which is used to set other low-level options. It is not accessible |
| /// outside of AnalyzerOptions. |
| UserModeKind getUserMode() const; |
| |
| ExplorationStrategyKind getExplorationStrategy() const; |
| |
| /// Returns the inter-procedural analysis mode. |
| IPAKind getIPAMode() const; |
| |
| /// Returns the option controlling which C++ member functions will be |
| /// considered for inlining. |
| /// |
| /// This is controlled by the 'c++-inlining' config option. |
| /// |
| /// \sa CXXMemberInliningMode |
| bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const; |
| |
| ento::PathDiagnosticConsumerOptions getDiagOpts() const { |
| return {FullCompilerInvocation, |
| ShouldDisplayMacroExpansions, |
| ShouldSerializeStats, |
| // The stable report filename option is deprecated because |
| // file names are now always stable. Now the old option acts as |
| // an alias to the new verbose filename option because this |
| // closely mimics the behavior under the old option. |
| ShouldWriteStableReportFilename || ShouldWriteVerboseReportFilename, |
| AnalyzerWerror, |
| ShouldApplyFixIts, |
| ShouldDisplayCheckerNameForText}; |
| } |
| }; |
| |
| using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>; |
| |
| //===----------------------------------------------------------------------===// |
| // We'll use AnalyzerOptions in the frontend, but we can't link the frontend |
| // with clangStaticAnalyzerCore, because clangStaticAnalyzerCore depends on |
| // clangFrontend. |
| // |
| // For this reason, implement some methods in this header file. |
| //===----------------------------------------------------------------------===// |
| |
| inline UserModeKind AnalyzerOptions::getUserMode() const { |
| auto K = llvm::StringSwitch<llvm::Optional<UserModeKind>>(UserMode) |
| .Case("shallow", UMK_Shallow) |
| .Case("deep", UMK_Deep) |
| .Default(None); |
| assert(K.hasValue() && "User mode is invalid."); |
| return K.getValue(); |
| } |
| |
| inline std::vector<StringRef> |
| AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental) { |
| static constexpr llvm::StringLiteral StaticAnalyzerCheckerNames[] = { |
| #define GET_CHECKERS |
| #define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \ |
| llvm::StringLiteral(FULLNAME), |
| #include "clang/StaticAnalyzer/Checkers/Checkers.inc" |
| #undef CHECKER |
| #undef GET_CHECKERS |
| }; |
| std::vector<StringRef> Checkers; |
| for (StringRef CheckerName : StaticAnalyzerCheckerNames) { |
| if (!CheckerName.startswith("debug.") && |
| (IncludeExperimental || !CheckerName.startswith("alpha."))) |
| Checkers.push_back(CheckerName); |
| } |
| return Checkers; |
| } |
| |
| inline std::vector<StringRef> |
| AnalyzerOptions::getRegisteredPackages(bool IncludeExperimental) { |
| static constexpr llvm::StringLiteral StaticAnalyzerPackageNames[] = { |
| #define GET_PACKAGES |
| #define PACKAGE(FULLNAME) llvm::StringLiteral(FULLNAME), |
| #include "clang/StaticAnalyzer/Checkers/Checkers.inc" |
| #undef PACKAGE |
| #undef GET_PACKAGES |
| }; |
| std::vector<StringRef> Packages; |
| for (StringRef PackageName : StaticAnalyzerPackageNames) { |
| if (PackageName != "debug" && |
| (IncludeExperimental || PackageName != "alpha")) |
| Packages.push_back(PackageName); |
| } |
| return Packages; |
| } |
| |
| } // namespace clang |
| |
| #endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H |