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