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 class PositiveAnalyzerOption { 128 public: 129 constexpr PositiveAnalyzerOption() = default; 130 constexpr PositiveAnalyzerOption(unsigned Value) : Value(Value) { 131 assert(Value > 0 && "only positive values are accepted"); 132 } 133 constexpr PositiveAnalyzerOption(const PositiveAnalyzerOption &) = default; 134 constexpr PositiveAnalyzerOption & 135 operator=(const PositiveAnalyzerOption &Other) { 136 Value = Other.Value; 137 return *this; 138 } 139 140 static constexpr std::optional<PositiveAnalyzerOption> create(unsigned Val) { 141 if (Val == 0) 142 return std::nullopt; 143 return PositiveAnalyzerOption{Val}; 144 } 145 static std::optional<PositiveAnalyzerOption> create(StringRef Str) { 146 unsigned Parsed = 0; 147 if (Str.getAsInteger(0, Parsed)) 148 return std::nullopt; 149 return PositiveAnalyzerOption::create(Parsed); 150 } 151 constexpr operator unsigned() const { return Value; } 152 153 private: 154 unsigned Value = 1; 155 }; 156 157 /// Stores options for the analyzer from the command line. 158 /// 159 /// Some options are frontend flags (e.g.: -analyzer-output), but some are 160 /// analyzer configuration options, which are preceded by -analyzer-config 161 /// (e.g.: -analyzer-config notes-as-events=true). 162 /// 163 /// If you'd like to add a new frontend flag, add it to 164 /// include/clang/Driver/CC1Options.td, add a new field to store the value of 165 /// that flag in this class, and initialize it in 166 /// lib/Frontend/CompilerInvocation.cpp. 167 /// 168 /// If you'd like to add a new non-checker configuration, register it in 169 /// include/clang/StaticAnalyzer/Core/AnalyzerOptions.def, and refer to the 170 /// top of the file for documentation. 171 /// 172 /// If you'd like to add a new checker option, call getChecker*Option() 173 /// whenever. 174 /// 175 /// Some of the options are controlled by raw frontend flags for no good reason, 176 /// and should be eventually converted into -analyzer-config flags. New analyzer 177 /// options should not be implemented as frontend flags. Frontend flags still 178 /// make sense for things that do not affect the actual analysis. 179 class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> { 180 public: 181 using ConfigTable = llvm::StringMap<std::string>; 182 183 /// Retrieves the list of checkers generated from Checkers.td. This doesn't 184 /// contain statically linked but non-generated checkers and plugin checkers! 185 static std::vector<StringRef> 186 getRegisteredCheckers(bool IncludeExperimental = false); 187 188 /// Retrieves the list of packages generated from Checkers.td. This doesn't 189 /// contain statically linked but non-generated packages and plugin packages! 190 static std::vector<StringRef> 191 getRegisteredPackages(bool IncludeExperimental = false); 192 193 /// Convenience function for printing options or checkers and their 194 /// description in a formatted manner. If \p MinLineWidth is set to 0, no line 195 /// breaks are introduced for the description. 196 /// 197 /// Format, depending whether the option name's length is less than 198 /// \p EntryWidth: 199 /// 200 /// <padding>EntryName<padding>Description 201 /// <---------padding--------->Description 202 /// <---------padding--------->Description 203 /// 204 /// <padding>VeryVeryLongEntryName 205 /// <---------padding--------->Description 206 /// <---------padding--------->Description 207 /// ^~~~~~~~~InitialPad 208 /// ^~~~~~~~~~~~~~~~~~EntryWidth 209 /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~MinLineWidth 210 static void printFormattedEntry(llvm::raw_ostream &Out, 211 std::pair<StringRef, StringRef> EntryDescPair, 212 size_t InitialPad, size_t EntryWidth, 213 size_t MinLineWidth = 0); 214 215 /// Pairs of checker/package name and enable/disable. 216 std::vector<std::pair<std::string, bool>> CheckersAndPackages; 217 218 /// Vector of checker/package names which will not emit warnings. 219 std::vector<std::string> SilencedCheckersAndPackages; 220 221 /// A key-value table of use-specified configuration values. 222 // TODO: This shouldn't be public. 223 ConfigTable Config; 224 AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel; 225 AnalysisDiagClients AnalysisDiagOpt = PD_HTML; 226 AnalysisPurgeMode AnalysisPurgeOpt = PurgeStmt; 227 228 std::string AnalyzeSpecificFunction; 229 230 /// File path to which the exploded graph should be dumped. 231 std::string DumpExplodedGraphTo; 232 233 /// Store full compiler invocation for reproducible instructions in the 234 /// generated report. 235 std::string FullCompilerInvocation; 236 237 /// The maximum number of times the analyzer visits a block. 238 unsigned maxBlockVisitOnPath; 239 240 /// Disable all analyzer checkers. 241 /// 242 /// This flag allows one to disable analyzer checkers on the code processed by 243 /// the given analysis consumer. Note, the code will get parsed and the 244 /// command-line options will get checked. 245 unsigned DisableAllCheckers : 1; 246 247 unsigned ShowCheckerHelp : 1; 248 unsigned ShowCheckerHelpAlpha : 1; 249 unsigned ShowCheckerHelpDeveloper : 1; 250 251 unsigned ShowCheckerOptionList : 1; 252 unsigned ShowCheckerOptionAlphaList : 1; 253 unsigned ShowCheckerOptionDeveloperList : 1; 254 255 unsigned ShowEnabledCheckerList : 1; 256 unsigned ShowConfigOptionsList : 1; 257 unsigned ShouldEmitErrorsOnInvalidConfigValue : 1; 258 unsigned AnalyzeAll : 1; 259 unsigned AnalyzerDisplayProgress : 1; 260 unsigned AnalyzerNoteAnalysisEntryPoints : 1; 261 262 unsigned TrimGraph : 1; 263 unsigned visualizeExplodedGraphWithGraphViz : 1; 264 unsigned UnoptimizedCFG : 1; 265 unsigned PrintStats : 1; 266 267 /// Do not re-analyze paths leading to exhausted nodes with a different 268 /// strategy. We get better code coverage when retry is enabled. 269 unsigned NoRetryExhausted : 1; 270 271 /// Emit analyzer warnings as errors. 272 bool AnalyzerWerror : 1; 273 274 /// The inlining stack depth limit. 275 unsigned InlineMaxStackDepth; 276 277 /// The mode of function selection used during inlining. 278 AnalysisInliningMode InliningMode = NoRedundancy; 279 280 // Create a field for each -analyzer-config option. 281 #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ 282 SHALLOW_VAL, DEEP_VAL) \ 283 ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL) 284 285 #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ 286 TYPE NAME; 287 288 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" 289 #undef ANALYZER_OPTION 290 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE 291 292 bool isUnknownAnalyzerConfig(llvm::StringRef Name) { 293 static std::vector<llvm::StringLiteral> AnalyzerConfigCmdFlags = []() { 294 // Create an array of all -analyzer-config command line options. 295 std::vector<llvm::StringLiteral> AnalyzerConfigCmdFlags = { 296 #define ANALYZER_OPTION_DEPENDS_ON_USER_MODE(TYPE, NAME, CMDFLAG, DESC, \ 297 SHALLOW_VAL, DEEP_VAL) \ 298 ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, SHALLOW_VAL) 299 300 #define ANALYZER_OPTION(TYPE, NAME, CMDFLAG, DESC, DEFAULT_VAL) \ 301 llvm::StringLiteral(CMDFLAG), 302 303 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.def" 304 #undef ANALYZER_OPTION 305 #undef ANALYZER_OPTION_DEPENDS_ON_USER_MODE 306 }; 307 // FIXME: Sort this at compile-time when we get constexpr sort (C++20). 308 llvm::sort(AnalyzerConfigCmdFlags); 309 return AnalyzerConfigCmdFlags; 310 }(); 311 312 return !std::binary_search(AnalyzerConfigCmdFlags.begin(), 313 AnalyzerConfigCmdFlags.end(), Name); 314 } 315 316 AnalyzerOptions() 317 : DisableAllCheckers(false), ShowCheckerHelp(false), 318 ShowCheckerHelpAlpha(false), ShowCheckerHelpDeveloper(false), 319 ShowCheckerOptionList(false), ShowCheckerOptionAlphaList(false), 320 ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false), 321 ShowConfigOptionsList(false), 322 ShouldEmitErrorsOnInvalidConfigValue(false), AnalyzeAll(false), 323 AnalyzerDisplayProgress(false), AnalyzerNoteAnalysisEntryPoints(false), 324 TrimGraph(false), visualizeExplodedGraphWithGraphViz(false), 325 UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false), 326 AnalyzerWerror(false) {} 327 328 /// Interprets an option's string value as a boolean. The "true" string is 329 /// interpreted as true and the "false" string is interpreted as false. 330 /// 331 /// If an option value is not provided, returns the given \p DefaultVal. 332 /// @param [in] CheckerName The *full name* of the checker. One may retrieve 333 /// this from the checker object's field \c Name, or through \c 334 /// CheckerManager::getCurrentCheckerName within the checker's registry 335 /// function. 336 /// Checker options are retrieved in the following format: 337 /// `-analyzer-config CheckerName:OptionName=Value. 338 /// @param [in] OptionName Name for option to retrieve. 339 /// @param [in] SearchInParents If set to true and the searched option was not 340 /// specified for the given checker the options for the parent packages will 341 /// be searched as well. The inner packages take precedence over the outer 342 /// ones. 343 bool getCheckerBooleanOption(StringRef CheckerName, StringRef OptionName, 344 bool SearchInParents = false) const; 345 346 bool getCheckerBooleanOption(const ento::CheckerBase *C, StringRef OptionName, 347 bool SearchInParents = false) const; 348 349 /// Interprets an option's string value as an integer value. 350 /// 351 /// If an option value is not provided, returns the given \p DefaultVal. 352 /// @param [in] CheckerName The *full name* of the checker. One may retrieve 353 /// this from the checker object's field \c Name, or through \c 354 /// CheckerManager::getCurrentCheckerName within the checker's registry 355 /// function. 356 /// Checker options are retrieved in the following format: 357 /// `-analyzer-config CheckerName:OptionName=Value. 358 /// @param [in] OptionName Name for option to retrieve. 359 /// @param [in] SearchInParents If set to true and the searched option was not 360 /// specified for the given checker the options for the parent packages will 361 /// be searched as well. The inner packages take precedence over the outer 362 /// ones. 363 int getCheckerIntegerOption(StringRef CheckerName, StringRef OptionName, 364 bool SearchInParents = false) const; 365 366 int getCheckerIntegerOption(const ento::CheckerBase *C, StringRef OptionName, 367 bool SearchInParents = false) const; 368 369 /// Query an option's string value. 370 /// 371 /// If an option value is not provided, returns the given \p DefaultVal. 372 /// @param [in] CheckerName The *full name* of the checker. One may retrieve 373 /// this from the checker object's field \c Name, or through \c 374 /// CheckerManager::getCurrentCheckerName within the checker's registry 375 /// function. 376 /// Checker options are retrieved in the following format: 377 /// `-analyzer-config CheckerName:OptionName=Value. 378 /// @param [in] OptionName Name for option to retrieve. 379 /// @param [in] SearchInParents If set to true and the searched option was not 380 /// specified for the given checker the options for the parent packages will 381 /// be searched as well. The inner packages take precedence over the outer 382 /// ones. 383 StringRef getCheckerStringOption(StringRef CheckerName, StringRef OptionName, 384 bool SearchInParents = false) const; 385 386 StringRef getCheckerStringOption(const ento::CheckerBase *C, 387 StringRef OptionName, 388 bool SearchInParents = false) const; 389 390 ExplorationStrategyKind getExplorationStrategy() const; 391 CTUPhase1InliningKind getCTUPhase1Inlining() const; 392 393 /// Returns the inter-procedural analysis mode. 394 IPAKind getIPAMode() const; 395 396 /// Returns the option controlling which C++ member functions will be 397 /// considered for inlining. 398 /// 399 /// This is controlled by the 'c++-inlining' config option. 400 /// 401 /// \sa CXXMemberInliningMode 402 bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const; 403 404 ento::PathDiagnosticConsumerOptions getDiagOpts() const { 405 return {FullCompilerInvocation, 406 ShouldDisplayMacroExpansions, 407 ShouldSerializeStats, 408 // The stable report filename option is deprecated because 409 // file names are now always stable. Now the old option acts as 410 // an alias to the new verbose filename option because this 411 // closely mimics the behavior under the old option. 412 ShouldWriteStableReportFilename || ShouldWriteVerboseReportFilename, 413 AnalyzerWerror, 414 ShouldApplyFixIts, 415 ShouldDisplayCheckerNameForText}; 416 } 417 }; 418 419 using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>; 420 421 //===----------------------------------------------------------------------===// 422 // We'll use AnalyzerOptions in the frontend, but we can't link the frontend 423 // with clangStaticAnalyzerCore, because clangStaticAnalyzerCore depends on 424 // clangFrontend. 425 // 426 // For this reason, implement some methods in this header file. 427 //===----------------------------------------------------------------------===// 428 429 inline std::vector<StringRef> 430 AnalyzerOptions::getRegisteredCheckers(bool IncludeExperimental) { 431 static constexpr llvm::StringLiteral StaticAnalyzerCheckerNames[] = { 432 #define GET_CHECKERS 433 #define CHECKER(FULLNAME, CLASS, HELPTEXT, DOC_URI, IS_HIDDEN) \ 434 llvm::StringLiteral(FULLNAME), 435 #include "clang/StaticAnalyzer/Checkers/Checkers.inc" 436 #undef CHECKER 437 #undef GET_CHECKERS 438 }; 439 std::vector<StringRef> Checkers; 440 for (StringRef CheckerName : StaticAnalyzerCheckerNames) { 441 if (!CheckerName.starts_with("debug.") && 442 (IncludeExperimental || !CheckerName.starts_with("alpha."))) 443 Checkers.push_back(CheckerName); 444 } 445 return Checkers; 446 } 447 448 inline std::vector<StringRef> 449 AnalyzerOptions::getRegisteredPackages(bool IncludeExperimental) { 450 static constexpr llvm::StringLiteral StaticAnalyzerPackageNames[] = { 451 #define GET_PACKAGES 452 #define PACKAGE(FULLNAME) llvm::StringLiteral(FULLNAME), 453 #include "clang/StaticAnalyzer/Checkers/Checkers.inc" 454 #undef PACKAGE 455 #undef GET_PACKAGES 456 }; 457 std::vector<StringRef> Packages; 458 for (StringRef PackageName : StaticAnalyzerPackageNames) { 459 if (PackageName != "debug" && 460 (IncludeExperimental || PackageName != "alpha")) 461 Packages.push_back(PackageName); 462 } 463 return Packages; 464 } 465 466 } // namespace clang 467 468 #endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H 469