1 //===- AnalyzerOptions.h - Analysis Engine Options --------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This header defines various options for the static analyzer that are set 10 // by the frontend and are consulted throughout the analyzer. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H 15 #define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H 16 17 #include "clang/Analysis/PathDiagnostic.h" 18 #include "clang/Basic/LLVM.h" 19 #include "llvm/ADT/IntrusiveRefCntPtr.h" 20 #include "llvm/ADT/StringMap.h" 21 #include "llvm/ADT/StringRef.h" 22 #include <string> 23 #include <utility> 24 #include <vector> 25 26 namespace clang { 27 28 namespace ento { 29 30 class CheckerBase; 31 32 } // namespace ento 33 34 /// AnalysisConstraints - Set of available constraint models. 35 enum AnalysisConstraints { 36 #define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, 37 #include "clang/StaticAnalyzer/Core/Analyses.def" 38 NumConstraints 39 }; 40 41 /// AnalysisDiagClients - Set of available diagnostic clients for rendering 42 /// analysis results. 43 enum AnalysisDiagClients { 44 #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME, 45 #include "clang/StaticAnalyzer/Core/Analyses.def" 46 PD_NONE, 47 NUM_ANALYSIS_DIAG_CLIENTS 48 }; 49 50 /// AnalysisPurgeModes - Set of available strategies for dead symbol removal. 51 enum AnalysisPurgeMode { 52 #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) NAME, 53 #include "clang/StaticAnalyzer/Core/Analyses.def" 54 NumPurgeModes 55 }; 56 57 /// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics. 58 enum AnalysisInliningMode { 59 #define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME, 60 #include "clang/StaticAnalyzer/Core/Analyses.def" 61 NumInliningModes 62 }; 63 64 /// Describes the different kinds of C++ member functions which can be 65 /// considered for inlining by the analyzer. 66 /// 67 /// These options are cumulative; enabling one kind of member function will 68 /// enable all kinds with lower enum values. 69 enum CXXInlineableMemberKind { 70 // Uninitialized = 0, 71 72 /// A dummy mode in which no C++ inlining is enabled. 73 CIMK_None, 74 75 /// Refers to regular member function and operator calls. 76 CIMK_MemberFunctions, 77 78 /// Refers to constructors (implicit or explicit). 79 /// 80 /// Note that a constructor will not be inlined if the corresponding 81 /// destructor is non-trivial. 82 CIMK_Constructors, 83 84 /// Refers to destructors (implicit or explicit). 85 CIMK_Destructors 86 }; 87 88 /// Describes the different modes of inter-procedural analysis. 89 enum IPAKind { 90 /// Perform only intra-procedural analysis. 91 IPAK_None = 1, 92 93 /// Inline C functions and blocks when their definitions are available. 94 IPAK_BasicInlining = 2, 95 96 /// Inline callees(C, C++, ObjC) when their definitions are available. 97 IPAK_Inlining = 3, 98 99 /// Enable inlining of dynamically dispatched methods. 100 IPAK_DynamicDispatch = 4, 101 102 /// Enable inlining of dynamically dispatched methods, bifurcate paths when 103 /// exact type info is unavailable. 104 IPAK_DynamicDispatchBifurcate = 5 105 }; 106 107 enum class ExplorationStrategyKind { 108 DFS, 109 BFS, 110 UnexploredFirst, 111 UnexploredFirstQueue, 112 UnexploredFirstLocationQueue, 113 BFSBlockDFSContents, 114 }; 115 116 /// Describes the kinds for high-level analyzer mode. 117 enum UserModeKind { 118 /// Perform shallow but fast analyzes. 119 UMK_Shallow = 1, 120 121 /// Perform deep analyzes. 122 UMK_Deep = 2 123 }; 124 125 enum class CTUPhase1InliningKind { None, Small, All }; 126 127 /// Stores options for the analyzer from the command line. 128 /// 129 /// Some options are frontend flags (e.g.: -analyzer-output), but some are 130 /// analyzer configuration options, which are preceded by -analyzer-config 131 /// (e.g.: -analyzer-config notes-as-events=true). 132 /// 133 /// If you'd like to add a new frontend flag, add it to 134 /// include/clang/Driver/CC1Options.td, add a new field to store the value of 135 /// that flag in this class, and initialize it in 136 /// lib/Frontend/CompilerInvocation.cpp. 137 /// 138 /// If you'd like to add a new non-checker configuration, register it in 139 /// include/clang/StaticAnalyzer/Core/AnalyzerOptions.def, and refer to the 140 /// top of the file for documentation. 141 /// 142 /// If you'd like to add a new checker option, call getChecker*Option() 143 /// whenever. 144 /// 145 /// Some of the options are controlled by raw frontend flags for no good reason, 146 /// and should be eventually converted into -analyzer-config flags. New analyzer 147 /// options should not be implemented as frontend flags. Frontend flags still 148 /// make sense for things that do not affect the actual analysis. 149 class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> { 150 public: 151 using ConfigTable = llvm::StringMap<std::string>; 152 153 /// Retrieves the list of checkers generated from Checkers.td. This doesn't 154 /// contain statically linked but non-generated checkers and plugin checkers! 155 static std::vector<StringRef> 156 getRegisteredCheckers(bool IncludeExperimental = false); 157 158 /// Retrieves the list of packages generated from Checkers.td. This doesn't 159 /// contain statically linked but non-generated packages and plugin packages! 160 static std::vector<StringRef> 161 getRegisteredPackages(bool IncludeExperimental = false); 162 163 /// Convenience function for printing options or checkers and their 164 /// description in a formatted manner. If \p MinLineWidth is set to 0, no line 165 /// breaks are introduced for the description. 166 /// 167 /// Format, depending whether the option name's length is less than 168 /// \p EntryWidth: 169 /// 170 /// <padding>EntryName<padding>Description 171 /// <---------padding--------->Description 172 /// <---------padding--------->Description 173 /// 174 /// <padding>VeryVeryLongEntryName 175 /// <---------padding--------->Description 176 /// <---------padding--------->Description 177 /// ^~~~~~~~~InitialPad 178 /// ^~~~~~~~~~~~~~~~~~EntryWidth 179 /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~MinLineWidth 180 static void printFormattedEntry(llvm::raw_ostream &Out, 181 std::pair<StringRef, StringRef> EntryDescPair, 182 size_t InitialPad, size_t EntryWidth, 183 size_t MinLineWidth = 0); 184 185 /// Pairs of checker/package name and enable/disable. 186 std::vector<std::pair<std::string, bool>> CheckersAndPackages; 187 188 /// Vector of checker/package names which will not emit warnings. 189 std::vector<std::string> SilencedCheckersAndPackages; 190 191 /// A key-value table of use-specified configuration values. 192 // TODO: This shouldn't be public. 193 ConfigTable Config; 194 AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel; 195 AnalysisDiagClients AnalysisDiagOpt = PD_HTML; 196 AnalysisPurgeMode AnalysisPurgeOpt = PurgeStmt; 197 198 std::string AnalyzeSpecificFunction; 199 200 /// File path to which the exploded graph should be dumped. 201 std::string DumpExplodedGraphTo; 202 203 /// Store full compiler invocation for reproducible instructions in the 204 /// generated report. 205 std::string FullCompilerInvocation; 206 207 /// The maximum number of times the analyzer visits a block. 208 unsigned maxBlockVisitOnPath; 209 210 /// Disable all analyzer checkers. 211 /// 212 /// This flag allows one to disable analyzer checkers on the code processed by 213 /// the given analysis consumer. Note, the code will get parsed and the 214 /// command-line options will get checked. 215 unsigned DisableAllCheckers : 1; 216 217 unsigned ShowCheckerHelp : 1; 218 unsigned ShowCheckerHelpAlpha : 1; 219 unsigned ShowCheckerHelpDeveloper : 1; 220 221 unsigned ShowCheckerOptionList : 1; 222 unsigned ShowCheckerOptionAlphaList : 1; 223 unsigned ShowCheckerOptionDeveloperList : 1; 224 225 unsigned ShowEnabledCheckerList : 1; 226 unsigned ShowConfigOptionsList : 1; 227 unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; 228 unsigned AnalyzeAll : 1; 229 unsigned AnalyzerDisplayProgress : 1; 230 231 unsigned eagerlyAssumeBinOpBifurcation : 1; 232 233 unsigned TrimGraph : 1; 234 unsigned visualizeExplodedGraphWithGraphViz : 1; 235 unsigned UnoptimizedCFG : 1; 236 unsigned PrintStats : 1; 237 238 /// Do not re-analyze paths leading to exhausted nodes with a different 239 /// strategy. We get better code coverage when retry is enabled. 240 unsigned NoRetryExhausted : 1; 241 242 /// Emit analyzer warnings as errors. 243 bool AnalyzerWerror : 1; 244 245 /// The inlining stack depth limit. 246 unsigned InlineMaxStackDepth; 247 248 /// The mode of function selection used during inlining. 249 AnalysisInliningMode InliningMode = NoRedundancy; 250 251 // Create a field for each -analyzer-config option. 252 #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ 253 SHALLOW_VAL, DEEP_VAL) \ 254 ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL) 255 256 #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ 257 TYPE NAME; 258 259 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" 260 #undef ANALYZER_OPTION 261 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE 262 263 bool isUnknownAnalyzerConfig(llvm::StringRef Name) { 264 static std::vector<llvm::StringLiteral> AnalyzerConfigCmdFlags = []() { 265 // Create an array of all -analyzer-config command line options. 266 std::vector<llvm::StringLiteral> AnalyzerConfigCmdFlags = { 267 #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ 268 SHALLOW_VAL, DEEP_VAL) \ 269 ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL) 270 271 #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ 272 llvm::StringLiteral(CMDFLAG), 273 274 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" 275 #undef ANALYZER_OPTION 276 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE 277 }; 278 // FIXME: Sort this at compile-time when we get constexpr sort (C++20). 279 llvm::sort(AnalyzerConfigCmdFlags); 280 return AnalyzerConfigCmdFlags; 281 }(); 282 283 return !std::binary_search(AnalyzerConfigCmdFlags.begin(), 284 AnalyzerConfigCmdFlags.end(), Name); 285 } 286 287 AnalyzerOptions() 288 : DisableAllCheckers(false), ShowCheckerHelp(false), 289 ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false), 290 ShowCheckerOptionList(false), ShowCheckerOptionAlphaList(false), 291 ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false), 292 ShowConfigOptionsList(false), 293 ShouldEmitErrorsOnInvalidConfigValue(false), AnalyzeAll(false), 294 AnalyzerDisplayProgress(false), eagerlyAssumeBinOpBifurcation(false), 295 TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), 296 UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false), 297 AnalyzerWerror(false) {} 298 299 /// Interprets an option's string value as a boolean. The "true" string is 300 /// interpreted as true and the "false" string is interpreted as false. 301 /// 302 /// If an option value is not provided, returns the given \p DefaultVal. 303 /// @param [in] CheckerName The *full name* of the checker. One may retrieve 304 /// this from the checker object's field \c Name, or through \c 305 /// CheckerManager::getCurrentCheckerName within the checker's registry 306 /// function. 307 /// Checker options are retrieved in the following format: 308 /// `-analyzer-config CheckerName:OptionName=Value. 309 /// @param [in] OptionName Name for option to retrieve. 310 /// @param [in] SearchInParents If set to true and the searched option was not 311 /// specified for the given checker the options for the parent packages will 312 /// be searched as well. The inner packages take precedence over the outer 313 /// ones. 314 bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, 315 bool SearchInParents = false) const; 316 317 bool getCheckerBooleanOption(const ento::CheckerBase *C, StringRef OptionName, 318 bool SearchInParents = false) const; 319 320 /// Interprets an option's string value as an integer value. 321 /// 322 /// If an option value is not provided, returns the given \p DefaultVal. 323 /// @param [in] CheckerName The *full name* of the checker. One may retrieve 324 /// this from the checker object's field \c Name, or through \c 325 /// CheckerManager::getCurrentCheckerName within the checker's registry 326 /// function. 327 /// Checker options are retrieved in the following format: 328 /// `-analyzer-config CheckerName:OptionName=Value. 329 /// @param [in] OptionName Name for option to retrieve. 330 /// @param [in] SearchInParents If set to true and the searched option was not 331 /// specified for the given checker the options for the parent packages will 332 /// be searched as well. The inner packages take precedence over the outer 333 /// ones. 334 int getCheckerIntegerOption(StringRef CheckerName, StringRef OptionName, 335 bool SearchInParents = false) const; 336 337 int getCheckerIntegerOption(const ento::CheckerBase *C, StringRef OptionName, 338 bool SearchInParents = false) const; 339 340 /// Query an option's string value. 341 /// 342 /// If an option value is not provided, returns the given \p DefaultVal. 343 /// @param [in] CheckerName The *full name* of the checker. One may retrieve 344 /// this from the checker object's field \c Name, or through \c 345 /// CheckerManager::getCurrentCheckerName within the checker's registry 346 /// function. 347 /// Checker options are retrieved in the following format: 348 /// `-analyzer-config CheckerName:OptionName=Value. 349 /// @param [in] OptionName Name for option to retrieve. 350 /// @param [in] SearchInParents If set to true and the searched option was not 351 /// specified for the given checker the options for the parent packages will 352 /// be searched as well. The inner packages take precedence over the outer 353 /// ones. 354 StringRef getCheckerStringOption(StringRef CheckerName, StringRef OptionName, 355 bool SearchInParents = false) const; 356 357 StringRef getCheckerStringOption(const ento::CheckerBase *C, 358 StringRef OptionName, 359 bool SearchInParents = false) const; 360 361 ExplorationStrategyKind getExplorationStrategy() const; 362 CTUPhase1InliningKind getCTUPhase1Inlining() const; 363 364 /// Returns the inter-procedural analysis mode. 365 IPAKind getIPAMode() const; 366 367 /// Returns the option controlling which C++ member functions will be 368 /// considered for inlining. 369 /// 370 /// This is controlled by the 'c++-inlining' config option. 371 /// 372 /// \sa CXXMemberInliningMode 373 bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const; 374 375 ento::PathDiagnosticConsumerOptions getDiagOpts() const { 376 return {FullCompilerInvocation, 377 ShouldDisplayMacroExpansions, 378 ShouldSerializeStats, 379 // The stable report filename option is deprecated because 380 // file names are now always stable. Now the old option acts as 381 // an alias to the new verbose filename option because this 382 // closely mimics the behavior under the old option. 383 ShouldWriteStableReportFilename || ShouldWriteVerboseReportFilename, 384 AnalyzerWerror, 385 ShouldApplyFixIts, 386 ShouldDisplayCheckerNameForText}; 387 } 388 }; 389 390 using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>; 391 392 //===----------------------------------------------------------------------===// 393 // We'll use AnalyzerOptions in the frontend, but we can't link the frontend 394 // with clangStaticAnalyzerCore, because clangStaticAnalyzerCore depends on 395 // clangFrontend. 396 // 397 // For this reason, implement some methods in this header file. 398 //===----------------------------------------------------------------------===// 399 400 inline std::vector<StringRef> 401 AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental) { 402 static constexpr llvm::StringLiteral StaticAnalyzerCheckerNames[] = { 403 #define GET_CHECKERS 404 #define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \ 405 llvm::StringLiteral(FULLNAME), 406 #include "clang/StaticAnalyzer/Checkers/Checkers.inc" 407 #undef CHECKER 408 #undef GET_CHECKERS 409 }; 410 std::vector<StringRef> Checkers; 411 for (StringRef CheckerName : StaticAnalyzerCheckerNames) { 412 if (!CheckerName.startswith("debug.") && 413 (IncludeExperimental || !CheckerName.startswith("alpha."))) 414 Checkers.push_back(CheckerName); 415 } 416 return Checkers; 417 } 418 419 inline std::vector<StringRef> 420 AnalyzerOptions::getRegisteredPackages(bool IncludeExperimental) { 421 static constexpr llvm::StringLiteral StaticAnalyzerPackageNames[] = { 422 #define GET_PACKAGES 423 #define PACKAGE(FULLNAME) llvm::StringLiteral(FULLNAME), 424 #include "clang/StaticAnalyzer/Checkers/Checkers.inc" 425 #undef PACKAGE 426 #undef GET_PACKAGES 427 }; 428 std::vector<StringRef> Packages; 429 for (StringRef PackageName : StaticAnalyzerPackageNames) { 430 if (PackageName != "debug" && 431 (IncludeExperimental || PackageName != "alpha")) 432 Packages.push_back(PackageName); 433 } 434 return Packages; 435 } 436 437 } // namespace clang 438 439 #endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H 440