1//===--- AnalyzerOptions.h - Analysis Engine Options ------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This header defines various options for the static analyzer that are set 11// by the frontend and are consulted throughout the analyzer. 12// 13//===----------------------------------------------------------------------===// 14 15#ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H 16#define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H 17 18#include "clang/Basic/LLVM.h" 19#include "llvm/ADT/IntrusiveRefCntPtr.h" 20#include "llvm/ADT/Optional.h" 21#include "llvm/ADT/StringMap.h" 22#include <string> 23#include <vector> 24 25namespace clang { 26class ASTConsumer; 27class DiagnosticsEngine; 28class Preprocessor; 29class LangOptions; 30 31namespace ento { 32class CheckerBase; 33} 34 35/// Analysis - Set of available source code analyses. 36enum Analyses { 37#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME, 38#include "clang/StaticAnalyzer/Core/Analyses.def" 39NumAnalyses 40}; 41 42/// AnalysisStores - Set of available analysis store models. 43enum AnalysisStores { 44#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, 45#include "clang/StaticAnalyzer/Core/Analyses.def" 46NumStores 47}; 48 49/// AnalysisConstraints - Set of available constraint models. 50enum AnalysisConstraints { 51#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model, 52#include "clang/StaticAnalyzer/Core/Analyses.def" 53NumConstraints 54}; 55 56/// AnalysisDiagClients - Set of available diagnostic clients for rendering 57/// analysis results. 58enum AnalysisDiagClients { 59#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME, 60#include "clang/StaticAnalyzer/Core/Analyses.def" 61PD_NONE, 62NUM_ANALYSIS_DIAG_CLIENTS 63}; 64 65/// AnalysisPurgeModes - Set of available strategies for dead symbol removal. 66enum AnalysisPurgeMode { 67#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) NAME, 68#include "clang/StaticAnalyzer/Core/Analyses.def" 69NumPurgeModes 70}; 71 72/// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics. 73enum AnalysisInliningMode { 74#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME, 75#include "clang/StaticAnalyzer/Core/Analyses.def" 76NumInliningModes 77}; 78 79/// \brief 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. 84enum CXXInlineableMemberKind { 85 // Uninitialized = 0, 86 87 /// A dummy mode in which no C++ inlining is enabled. 88 CIMK_None = 1, 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/// \brief Describes the different modes of inter-procedural analysis. 104enum IPAKind { 105 IPAK_NotSet = 0, 106 107 /// Perform only intra-procedural analysis. 108 IPAK_None = 1, 109 110 /// Inline C functions and blocks when their definitions are available. 111 IPAK_BasicInlining = 2, 112 113 /// Inline callees(C, C++, ObjC) when their definitions are available. 114 IPAK_Inlining = 3, 115 116 /// Enable inlining of dynamically dispatched methods. 117 IPAK_DynamicDispatch = 4, 118 119 /// Enable inlining of dynamically dispatched methods, bifurcate paths when 120 /// exact type info is unavailable. 121 IPAK_DynamicDispatchBifurcate = 5 122}; 123 124class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> { 125public: 126 typedef llvm::StringMap<std::string> ConfigTable; 127 128 static std::vector<StringRef> 129 getRegisteredCheckers(bool IncludeExperimental = false); 130 131 /// \brief Pair of checker name and enable/disable. 132 std::vector<std::pair<std::string, bool> > CheckersControlList; 133 134 /// \brief A key-value table of use-specified configuration values. 135 ConfigTable Config; 136 AnalysisStores AnalysisStoreOpt; 137 AnalysisConstraints AnalysisConstraintsOpt; 138 AnalysisDiagClients AnalysisDiagOpt; 139 AnalysisPurgeMode AnalysisPurgeOpt; 140 141 std::string AnalyzeSpecificFunction; 142 143 /// \brief The maximum number of times the analyzer visits a block. 144 unsigned maxBlockVisitOnPath; 145 146 147 /// \brief Disable all analyzer checks. 148 /// 149 /// This flag allows one to disable analyzer checks on the code processed by 150 /// the given analysis consumer. Note, the code will get parsed and the 151 /// command-line options will get checked. 152 unsigned DisableAllChecks : 1; 153 154 unsigned ShowCheckerHelp : 1; 155 unsigned ShowEnabledCheckerList : 1; 156 unsigned AnalyzeAll : 1; 157 unsigned AnalyzerDisplayProgress : 1; 158 unsigned AnalyzeNestedBlocks : 1; 159 160 /// \brief The flag regulates if we should eagerly assume evaluations of 161 /// conditionals, thus, bifurcating the path. 162 /// 163 /// This flag indicates how the engine should handle expressions such as: 'x = 164 /// (y != 0)'. When this flag is true then the subexpression 'y != 0' will be 165 /// eagerly assumed to be true or false, thus evaluating it to the integers 0 166 /// or 1 respectively. The upside is that this can increase analysis 167 /// precision until we have a better way to lazily evaluate such logic. The 168 /// downside is that it eagerly bifurcates paths. 169 unsigned eagerlyAssumeBinOpBifurcation : 1; 170 171 unsigned TrimGraph : 1; 172 unsigned visualizeExplodedGraphWithGraphViz : 1; 173 unsigned visualizeExplodedGraphWithUbiGraph : 1; 174 unsigned UnoptimizedCFG : 1; 175 unsigned PrintStats : 1; 176 177 /// \brief Do not re-analyze paths leading to exhausted nodes with a different 178 /// strategy. We get better code coverage when retry is enabled. 179 unsigned NoRetryExhausted : 1; 180 181 /// \brief The inlining stack depth limit. 182 unsigned InlineMaxStackDepth; 183 184 /// \brief The mode of function selection used during inlining. 185 AnalysisInliningMode InliningMode; 186 187private: 188 /// \brief Describes the kinds for high-level analyzer mode. 189 enum UserModeKind { 190 UMK_NotSet = 0, 191 /// Perform shallow but fast analyzes. 192 UMK_Shallow = 1, 193 /// Perform deep analyzes. 194 UMK_Deep = 2 195 }; 196 197 /// Controls the high-level analyzer mode, which influences the default 198 /// settings for some of the lower-level config options (such as IPAMode). 199 /// \sa getUserMode 200 UserModeKind UserMode; 201 202 /// Controls the mode of inter-procedural analysis. 203 IPAKind IPAMode; 204 205 /// Controls which C++ member functions will be considered for inlining. 206 CXXInlineableMemberKind CXXMemberInliningMode; 207 208 /// \sa includeImplicitDtorsInCFG 209 Optional<bool> IncludeImplicitDtorsInCFG; 210 211 /// \sa includeTemporaryDtorsInCFG 212 Optional<bool> IncludeTemporaryDtorsInCFG; 213 214 /// \sa IncludeLifetimeInCFG 215 Optional<bool> IncludeLifetimeInCFG; 216 217 /// \sa IncludeLoopExitInCFG 218 Optional<bool> IncludeLoopExitInCFG; 219 220 /// \sa mayInlineCXXStandardLibrary 221 Optional<bool> InlineCXXStandardLibrary; 222 223 /// \sa mayInlineTemplateFunctions 224 Optional<bool> InlineTemplateFunctions; 225 226 /// \sa mayInlineCXXAllocator 227 Optional<bool> InlineCXXAllocator; 228 229 /// \sa mayInlineCXXContainerMethods 230 Optional<bool> InlineCXXContainerMethods; 231 232 /// \sa mayInlineCXXSharedPtrDtor 233 Optional<bool> InlineCXXSharedPtrDtor; 234 235 /// \sa mayInlineObjCMethod 236 Optional<bool> ObjCInliningMode; 237 238 // Cache of the "ipa-always-inline-size" setting. 239 // \sa getAlwaysInlineSize 240 Optional<unsigned> AlwaysInlineSize; 241 242 /// \sa shouldSuppressNullReturnPaths 243 Optional<bool> SuppressNullReturnPaths; 244 245 // \sa getMaxInlinableSize 246 Optional<unsigned> MaxInlinableSize; 247 248 /// \sa shouldAvoidSuppressingNullArgumentPaths 249 Optional<bool> AvoidSuppressingNullArgumentPaths; 250 251 /// \sa shouldSuppressInlinedDefensiveChecks 252 Optional<bool> SuppressInlinedDefensiveChecks; 253 254 /// \sa shouldSuppressFromCXXStandardLibrary 255 Optional<bool> SuppressFromCXXStandardLibrary; 256 257 /// \sa reportIssuesInMainSourceFile 258 Optional<bool> ReportIssuesInMainSourceFile; 259 260 /// \sa StableReportFilename 261 Optional<bool> StableReportFilename; 262 263 /// \sa getGraphTrimInterval 264 Optional<unsigned> GraphTrimInterval; 265 266 /// \sa getMaxTimesInlineLarge 267 Optional<unsigned> MaxTimesInlineLarge; 268 269 /// \sa getMinCFGSizeTreatFunctionsAsLarge 270 Optional<unsigned> MinCFGSizeTreatFunctionsAsLarge; 271 272 /// \sa getMaxNodesPerTopLevelFunction 273 Optional<unsigned> MaxNodesPerTopLevelFunction; 274 275 /// \sa shouldInlineLambdas 276 Optional<bool> InlineLambdas; 277 278 /// \sa shouldWidenLoops 279 Optional<bool> WidenLoops; 280 281 /// \sa shouldUnrollLoops 282 Optional<bool> UnrollLoops; 283 284 /// \sa shouldDisplayNotesAsEvents 285 Optional<bool> DisplayNotesAsEvents; 286 287 /// A helper function that retrieves option for a given full-qualified 288 /// checker name. 289 /// Options for checkers can be specified via 'analyzer-config' command-line 290 /// option. 291 /// Example: 292 /// @code-analyzer-config unix.Malloc:OptionName=CheckerOptionValue @endcode 293 /// or @code-analyzer-config unix:OptionName=GroupOptionValue @endcode 294 /// for groups of checkers. 295 /// @param [in] CheckerName Full-qualified checker name, like 296 /// alpha.unix.StreamChecker. 297 /// @param [in] OptionName Name of the option to get. 298 /// @param [in] Default Default value if no option is specified. 299 /// @param [in] SearchInParents If set to true and the searched option was not 300 /// specified for the given checker the options for the parent packages will 301 /// be searched as well. The inner packages take precedence over the outer 302 /// ones. 303 /// @retval CheckerOptionValue An option for a checker if it was specified. 304 /// @retval GroupOptionValue An option for group if it was specified and no 305 /// checker-specific options were found. The closer group to checker, 306 /// the more priority it has. For example, @c coregroup.subgroup has more 307 /// priority than @c coregroup for @c coregroup.subgroup.CheckerName checker. 308 /// @retval Default If nor checker option, nor group option was found. 309 StringRef getCheckerOption(StringRef CheckerName, StringRef OptionName, 310 StringRef Default, 311 bool SearchInParents = false); 312 313public: 314 /// Interprets an option's string value as a boolean. The "true" string is 315 /// interpreted as true and the "false" string is interpreted as false. 316 /// 317 /// If an option value is not provided, returns the given \p DefaultVal. 318 /// @param [in] Name Name for option to retrieve. 319 /// @param [in] DefaultVal Default value returned if no such option was 320 /// specified. 321 /// @param [in] C The optional checker parameter that can be used to restrict 322 /// the search to the options of this particular checker (and its parents 323 /// dependening on search mode). 324 /// @param [in] SearchInParents If set to true and the searched option was not 325 /// specified for the given checker the options for the parent packages will 326 /// be searched as well. The inner packages take precedence over the outer 327 /// ones. 328 bool getBooleanOption(StringRef Name, bool DefaultVal, 329 const ento::CheckerBase *C = nullptr, 330 bool SearchInParents = false); 331 332 /// Variant that accepts a Optional value to cache the result. 333 /// 334 /// @param [in,out] V Return value storage, returned if parameter contains 335 /// an existing valid option, else it is used to store a return value 336 /// @param [in] Name Name for option to retrieve. 337 /// @param [in] DefaultVal Default value returned if no such option was 338 /// specified. 339 /// @param [in] C The optional checker parameter that can be used to restrict 340 /// the search to the options of this particular checker (and its parents 341 /// dependening on search mode). 342 /// @param [in] SearchInParents If set to true and the searched option was not 343 /// specified for the given checker the options for the parent packages will 344 /// be searched as well. The inner packages take precedence over the outer 345 /// ones. 346 bool getBooleanOption(Optional<bool> &V, StringRef Name, bool DefaultVal, 347 const ento::CheckerBase *C = nullptr, 348 bool SearchInParents = false); 349 350 /// Interprets an option's string value as an integer value. 351 /// 352 /// If an option value is not provided, returns the given \p DefaultVal. 353 /// @param [in] Name Name for option to retrieve. 354 /// @param [in] DefaultVal Default value returned if no such option was 355 /// specified. 356 /// @param [in] C The optional checker parameter that can be used to restrict 357 /// the search to the options of this particular checker (and its parents 358 /// dependening on search mode). 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 getOptionAsInteger(StringRef Name, int DefaultVal, 364 const ento::CheckerBase *C = nullptr, 365 bool SearchInParents = false); 366 367 /// Query an option's string value. 368 /// 369 /// If an option value is not provided, returns the given \p DefaultVal. 370 /// @param [in] Name Name for option to retrieve. 371 /// @param [in] DefaultVal Default value returned if no such option was 372 /// specified. 373 /// @param [in] C The optional checker parameter that can be used to restrict 374 /// the search to the options of this particular checker (and its parents 375 /// dependening on search mode). 376 /// @param [in] SearchInParents If set to true and the searched option was not 377 /// specified for the given checker the options for the parent packages will 378 /// be searched as well. The inner packages take precedence over the outer 379 /// ones. 380 StringRef getOptionAsString(StringRef Name, StringRef DefaultVal, 381 const ento::CheckerBase *C = nullptr, 382 bool SearchInParents = false); 383 384 /// \brief Retrieves and sets the UserMode. This is a high-level option, 385 /// which is used to set other low-level options. It is not accessible 386 /// outside of AnalyzerOptions. 387 UserModeKind getUserMode(); 388 389 /// \brief Returns the inter-procedural analysis mode. 390 IPAKind getIPAMode(); 391 392 /// Returns the option controlling which C++ member functions will be 393 /// considered for inlining. 394 /// 395 /// This is controlled by the 'c++-inlining' config option. 396 /// 397 /// \sa CXXMemberInliningMode 398 bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K); 399 400 /// Returns true if ObjectiveC inlining is enabled, false otherwise. 401 bool mayInlineObjCMethod(); 402 403 /// Returns whether or not the destructors for C++ temporary objects should 404 /// be included in the CFG. 405 /// 406 /// This is controlled by the 'cfg-temporary-dtors' config option, which 407 /// accepts the values "true" and "false". 408 bool includeTemporaryDtorsInCFG(); 409 410 /// Returns whether or not implicit destructors for C++ objects should 411 /// be included in the CFG. 412 /// 413 /// This is controlled by the 'cfg-implicit-dtors' config option, which 414 /// accepts the values "true" and "false". 415 bool includeImplicitDtorsInCFG(); 416 417 /// Returns whether or not end-of-lifetime information should be included in 418 /// the CFG. 419 /// 420 /// This is controlled by the 'cfg-lifetime' config option, which accepts 421 /// the values "true" and "false". 422 bool includeLifetimeInCFG(); 423 424 /// Returns whether or not the end of the loop information should be included 425 /// in the CFG. 426 /// 427 /// This is controlled by the 'cfg-loopexit' config option, which accepts 428 /// the values "true" and "false". 429 bool includeLoopExitInCFG(); 430 431 /// Returns whether or not C++ standard library functions may be considered 432 /// for inlining. 433 /// 434 /// This is controlled by the 'c++-stdlib-inlining' config option, which 435 /// accepts the values "true" and "false". 436 bool mayInlineCXXStandardLibrary(); 437 438 /// Returns whether or not templated functions may be considered for inlining. 439 /// 440 /// This is controlled by the 'c++-template-inlining' config option, which 441 /// accepts the values "true" and "false". 442 bool mayInlineTemplateFunctions(); 443 444 /// Returns whether or not allocator call may be considered for inlining. 445 /// 446 /// This is controlled by the 'c++-allocator-inlining' config option, which 447 /// accepts the values "true" and "false". 448 bool mayInlineCXXAllocator(); 449 450 /// Returns whether or not methods of C++ container objects may be considered 451 /// for inlining. 452 /// 453 /// This is controlled by the 'c++-container-inlining' config option, which 454 /// accepts the values "true" and "false". 455 bool mayInlineCXXContainerMethods(); 456 457 /// Returns whether or not the destructor of C++ 'shared_ptr' may be 458 /// considered for inlining. 459 /// 460 /// This covers std::shared_ptr, std::tr1::shared_ptr, and boost::shared_ptr, 461 /// and indeed any destructor named "~shared_ptr". 462 /// 463 /// This is controlled by the 'c++-shared_ptr-inlining' config option, which 464 /// accepts the values "true" and "false". 465 bool mayInlineCXXSharedPtrDtor(); 466 467 /// Returns whether or not paths that go through null returns should be 468 /// suppressed. 469 /// 470 /// This is a heuristic for avoiding bug reports with paths that go through 471 /// inlined functions that are more defensive than their callers. 472 /// 473 /// This is controlled by the 'suppress-null-return-paths' config option, 474 /// which accepts the values "true" and "false". 475 bool shouldSuppressNullReturnPaths(); 476 477 /// Returns whether a bug report should \em not be suppressed if its path 478 /// includes a call with a null argument, even if that call has a null return. 479 /// 480 /// This option has no effect when #shouldSuppressNullReturnPaths() is false. 481 /// 482 /// This is a counter-heuristic to avoid false negatives. 483 /// 484 /// This is controlled by the 'avoid-suppressing-null-argument-paths' config 485 /// option, which accepts the values "true" and "false". 486 bool shouldAvoidSuppressingNullArgumentPaths(); 487 488 /// Returns whether or not diagnostics containing inlined defensive NULL 489 /// checks should be suppressed. 490 /// 491 /// This is controlled by the 'suppress-inlined-defensive-checks' config 492 /// option, which accepts the values "true" and "false". 493 bool shouldSuppressInlinedDefensiveChecks(); 494 495 /// Returns whether or not diagnostics reported within the C++ standard 496 /// library should be suppressed. 497 /// 498 /// This is controlled by the 'suppress-c++-stdlib' config option, 499 /// which accepts the values "true" and "false". 500 bool shouldSuppressFromCXXStandardLibrary(); 501 502 /// Returns whether or not the diagnostic report should be always reported 503 /// in the main source file and not the headers. 504 /// 505 /// This is controlled by the 'report-in-main-source-file' config option, 506 /// which accepts the values "true" and "false". 507 bool shouldReportIssuesInMainSourceFile(); 508 509 /// Returns whether or not the report filename should be random or not. 510 /// 511 /// This is controlled by the 'stable-report-filename' config option, 512 /// which accepts the values "true" and "false". Default = false 513 bool shouldWriteStableReportFilename(); 514 515 /// Returns whether irrelevant parts of a bug report path should be pruned 516 /// out of the final output. 517 /// 518 /// This is controlled by the 'prune-paths' config option, which accepts the 519 /// values "true" and "false". 520 bool shouldPrunePaths(); 521 522 /// Returns true if 'static' initializers should be in conditional logic 523 /// in the CFG. 524 bool shouldConditionalizeStaticInitializers(); 525 526 // Returns the size of the functions (in basic blocks), which should be 527 // considered to be small enough to always inline. 528 // 529 // This is controlled by "ipa-always-inline-size" analyzer-config option. 530 unsigned getAlwaysInlineSize(); 531 532 // Returns the bound on the number of basic blocks in an inlined function 533 // (50 by default). 534 // 535 // This is controlled by "-analyzer-config max-inlinable-size" option. 536 unsigned getMaxInlinableSize(); 537 538 /// Returns true if the analyzer engine should synthesize fake bodies 539 /// for well-known functions. 540 bool shouldSynthesizeBodies(); 541 542 /// Returns how often nodes in the ExplodedGraph should be recycled to save 543 /// memory. 544 /// 545 /// This is controlled by the 'graph-trim-interval' config option. To disable 546 /// node reclamation, set the option to "0". 547 unsigned getGraphTrimInterval(); 548 549 /// Returns the maximum times a large function could be inlined. 550 /// 551 /// This is controlled by the 'max-times-inline-large' config option. 552 unsigned getMaxTimesInlineLarge(); 553 554 /// Returns the number of basic blocks a function needs to have to be 555 /// considered large for the 'max-times-inline-large' config option. 556 /// 557 /// This is controlled by the 'min-cfg-size-treat-functions-as-large' config 558 /// option. 559 unsigned getMinCFGSizeTreatFunctionsAsLarge(); 560 561 /// Returns the maximum number of nodes the analyzer can generate while 562 /// exploring a top level function (for each exploded graph). 563 /// 150000 is default; 0 means no limit. 564 /// 565 /// This is controlled by the 'max-nodes' config option. 566 unsigned getMaxNodesPerTopLevelFunction(); 567 568 /// Returns true if lambdas should be inlined. Otherwise a sink node will be 569 /// generated each time a LambdaExpr is visited. 570 bool shouldInlineLambdas(); 571 572 /// Returns true if the analysis should try to widen loops. 573 /// This is controlled by the 'widen-loops' config option. 574 bool shouldWidenLoops(); 575 576 /// Returns true if the analysis should try to unroll loops with known bounds. 577 /// This is controlled by the 'unroll-loops' config option. 578 bool shouldUnrollLoops(); 579 580 /// Returns true if the bug reporter should transparently treat extra note 581 /// diagnostic pieces as event diagnostic pieces. Useful when the diagnostic 582 /// consumer doesn't support the extra note pieces. 583 /// 584 /// This is controlled by the 'extra-notes-as-events' option, which defaults 585 /// to false when unset. 586 bool shouldDisplayNotesAsEvents(); 587 588public: 589 AnalyzerOptions() : 590 AnalysisStoreOpt(RegionStoreModel), 591 AnalysisConstraintsOpt(RangeConstraintsModel), 592 AnalysisDiagOpt(PD_HTML), 593 AnalysisPurgeOpt(PurgeStmt), 594 DisableAllChecks(0), 595 ShowCheckerHelp(0), 596 ShowEnabledCheckerList(0), 597 AnalyzeAll(0), 598 AnalyzerDisplayProgress(0), 599 AnalyzeNestedBlocks(0), 600 eagerlyAssumeBinOpBifurcation(0), 601 TrimGraph(0), 602 visualizeExplodedGraphWithGraphViz(0), 603 visualizeExplodedGraphWithUbiGraph(0), 604 UnoptimizedCFG(0), 605 PrintStats(0), 606 NoRetryExhausted(0), 607 // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). 608 InlineMaxStackDepth(5), 609 InliningMode(NoRedundancy), 610 UserMode(UMK_NotSet), 611 IPAMode(IPAK_NotSet), 612 CXXMemberInliningMode() {} 613 614}; 615 616typedef IntrusiveRefCntPtr<AnalyzerOptions> AnalyzerOptionsRef; 617 618} 619 620#endif 621