1 //===--- ClangTidyCheck.h - clang-tidy --------------------------*- 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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H 10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H 11 12 #include "ClangTidyDiagnosticConsumer.h" 13 #include "ClangTidyOptions.h" 14 #include "clang/ASTMatchers/ASTMatchFinder.h" 15 #include "clang/Basic/Diagnostic.h" 16 #include "llvm/ADT/Optional.h" 17 #include "llvm/Support/Error.h" 18 #include <type_traits> 19 #include <utility> 20 #include <vector> 21 22 namespace clang { 23 24 class CompilerInstance; 25 class SourceManager; 26 27 namespace tidy { 28 29 /// This class should be specialized by any enum type that needs to be converted 30 /// to and from an \ref llvm::StringRef. 31 template <class T> struct OptionEnumMapping { 32 // Specializations of this struct must implement this function. 33 static ArrayRef<std::pair<T, StringRef>> getEnumMapping() = delete; 34 }; 35 36 template <typename T> class OptionError : public llvm::ErrorInfo<T> { convertToErrorCode()37 std::error_code convertToErrorCode() const override { 38 return llvm::inconvertibleErrorCode(); 39 } 40 41 public: log(raw_ostream & OS)42 void log(raw_ostream &OS) const override { OS << this->message(); } 43 }; 44 45 class MissingOptionError : public OptionError<MissingOptionError> { 46 public: MissingOptionError(std::string OptionName)47 explicit MissingOptionError(std::string OptionName) 48 : OptionName(OptionName) {} 49 50 std::string message() const override; 51 static char ID; 52 private: 53 const std::string OptionName; 54 }; 55 56 class UnparseableEnumOptionError 57 : public OptionError<UnparseableEnumOptionError> { 58 public: UnparseableEnumOptionError(std::string LookupName,std::string LookupValue)59 explicit UnparseableEnumOptionError(std::string LookupName, 60 std::string LookupValue) 61 : LookupName(LookupName), LookupValue(LookupValue) {} UnparseableEnumOptionError(std::string LookupName,std::string LookupValue,std::string SuggestedValue)62 explicit UnparseableEnumOptionError(std::string LookupName, 63 std::string LookupValue, 64 std::string SuggestedValue) 65 : LookupName(LookupName), LookupValue(LookupValue), 66 SuggestedValue(SuggestedValue) {} 67 68 std::string message() const override; 69 static char ID; 70 71 private: 72 const std::string LookupName; 73 const std::string LookupValue; 74 const llvm::Optional<std::string> SuggestedValue; 75 }; 76 77 class UnparseableIntegerOptionError 78 : public OptionError<UnparseableIntegerOptionError> { 79 public: 80 explicit UnparseableIntegerOptionError(std::string LookupName, 81 std::string LookupValue, 82 bool IsBoolean = false) LookupName(LookupName)83 : LookupName(LookupName), LookupValue(LookupValue), IsBoolean(IsBoolean) { 84 } 85 86 std::string message() const override; 87 static char ID; 88 89 private: 90 const std::string LookupName; 91 const std::string LookupValue; 92 const bool IsBoolean; 93 }; 94 95 /// Base class for all clang-tidy checks. 96 /// 97 /// To implement a ``ClangTidyCheck``, write a subclass and override some of the 98 /// base class's methods. E.g. to implement a check that validates namespace 99 /// declarations, override ``registerMatchers``: 100 /// 101 /// ~~~{.cpp} 102 /// void registerMatchers(ast_matchers::MatchFinder *Finder) override { 103 /// Finder->addMatcher(namespaceDecl().bind("namespace"), this); 104 /// } 105 /// ~~~ 106 /// 107 /// and then override ``check(const MatchResult &Result)`` to do the actual 108 /// check for each match. 109 /// 110 /// A new ``ClangTidyCheck`` instance is created per translation unit. 111 /// 112 /// FIXME: Figure out whether carrying information from one TU to another is 113 /// useful/necessary. 114 class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { 115 public: 116 /// Initializes the check with \p CheckName and \p Context. 117 /// 118 /// Derived classes must implement the constructor with this signature or 119 /// delegate it. If a check needs to read options, it can do this in the 120 /// constructor using the Options.get() methods below. 121 ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context); 122 123 /// Override this to disable registering matchers and PP callbacks if an 124 /// invalid language version is being used. 125 /// 126 /// For example if a check is examining overloaded functions then this should 127 /// be overridden to return false when the CPlusPlus flag is not set in 128 /// \p LangOpts. isLanguageVersionSupported(const LangOptions & LangOpts)129 virtual bool isLanguageVersionSupported(const LangOptions &LangOpts) const { 130 return true; 131 } 132 133 /// Override this to register ``PPCallbacks`` in the preprocessor. 134 /// 135 /// This should be used for clang-tidy checks that analyze preprocessor- 136 /// dependent properties, e.g. include directives and macro definitions. 137 /// 138 /// This will only be executed if the function isLanguageVersionSupported 139 /// returns true. 140 /// 141 /// There are two Preprocessors to choose from that differ in how they handle 142 /// modular #includes: 143 /// - PP is the real Preprocessor. It doesn't walk into modular #includes and 144 /// thus doesn't generate PPCallbacks for their contents. 145 /// - ModuleExpanderPP preprocesses the whole translation unit in the 146 /// non-modular mode, which allows it to generate PPCallbacks not only for 147 /// the main file and textual headers, but also for all transitively 148 /// included modular headers when the analysis runs with modules enabled. 149 /// When modules are not enabled ModuleExpanderPP just points to the real 150 /// preprocessor. registerPPCallbacks(const SourceManager & SM,Preprocessor * PP,Preprocessor * ModuleExpanderPP)151 virtual void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, 152 Preprocessor *ModuleExpanderPP) {} 153 154 /// Override this to register AST matchers with \p Finder. 155 /// 156 /// This should be used by clang-tidy checks that analyze code properties that 157 /// dependent on AST knowledge. 158 /// 159 /// You can register as many matchers as necessary with \p Finder. Usually, 160 /// "this" will be used as callback, but you can also specify other callback 161 /// classes. Thereby, different matchers can trigger different callbacks. 162 /// 163 /// This will only be executed if the function isLanguageVersionSupported 164 /// returns true. 165 /// 166 /// If you need to merge information between the different matchers, you can 167 /// store these as members of the derived class. However, note that all 168 /// matches occur in the order of the AST traversal. registerMatchers(ast_matchers::MatchFinder * Finder)169 virtual void registerMatchers(ast_matchers::MatchFinder *Finder) {} 170 171 /// ``ClangTidyChecks`` that register ASTMatchers should do the actual 172 /// work in here. check(const ast_matchers::MatchFinder::MatchResult & Result)173 virtual void check(const ast_matchers::MatchFinder::MatchResult &Result) {} 174 175 /// Add a diagnostic with the check's name. 176 DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, 177 DiagnosticIDs::Level Level = DiagnosticIDs::Warning); 178 179 /// Add a diagnostic with the check's name. 180 DiagnosticBuilder diag(StringRef Description, 181 DiagnosticIDs::Level Level = DiagnosticIDs::Warning); 182 183 /// Adds a diagnostic to report errors in the check's configuration. 184 DiagnosticBuilder 185 configurationDiag(StringRef Description, 186 DiagnosticIDs::Level Level = DiagnosticIDs::Warning); 187 188 /// Should store all options supported by this check with their 189 /// current values or default values for options that haven't been overridden. 190 /// 191 /// The check should use ``Options.store()`` to store each option it supports 192 /// whether it has the default value or it has been overridden. storeOptions(ClangTidyOptions::OptionMap & Options)193 virtual void storeOptions(ClangTidyOptions::OptionMap &Options) {} 194 195 /// Provides access to the ``ClangTidyCheck`` options via check-local 196 /// names. 197 /// 198 /// Methods of this class prepend ``CheckName + "."`` to translate check-local 199 /// option names to global option names. 200 class OptionsView { 201 public: 202 /// Initializes the instance using \p CheckName + "." as a prefix. 203 OptionsView(StringRef CheckName, 204 const ClangTidyOptions::OptionMap &CheckOptions, 205 ClangTidyContext *Context); 206 207 /// Read a named option from the ``Context``. 208 /// 209 /// Reads the option with the check-local name \p LocalName from the 210 /// ``CheckOptions``. If the corresponding key is not present, returns 211 /// a ``MissingOptionError``. 212 llvm::Expected<std::string> get(StringRef LocalName) const; 213 214 /// Read a named option from the ``Context``. 215 /// 216 /// Reads the option with the check-local name \p LocalName from the 217 /// ``CheckOptions``. If the corresponding key is not present, returns 218 /// \p Default. get(StringRef LocalName,StringRef Default)219 std::string get(StringRef LocalName, StringRef Default) const { 220 if (llvm::Expected<std::string> Val = get(LocalName)) 221 return *Val; 222 else 223 llvm::consumeError(Val.takeError()); 224 return Default.str(); 225 } 226 227 /// Read a named option from the ``Context``. 228 /// 229 /// Reads the option with the check-local name \p LocalName from local or 230 /// global ``CheckOptions``. Gets local option first. If local is not 231 /// present, falls back to get global option. If global option is not 232 /// present either, returns a ``MissingOptionError``. 233 llvm::Expected<std::string> getLocalOrGlobal(StringRef LocalName) const; 234 235 /// Read a named option from the ``Context``. 236 /// 237 /// Reads the option with the check-local name \p LocalName from local or 238 /// global ``CheckOptions``. Gets local option first. If local is not 239 /// present, falls back to get global option. If global option is not 240 /// present either, returns \p Default. getLocalOrGlobal(StringRef LocalName,StringRef Default)241 std::string getLocalOrGlobal(StringRef LocalName, StringRef Default) const { 242 if (llvm::Expected<std::string> Val = getLocalOrGlobal(LocalName)) 243 return *Val; 244 else 245 llvm::consumeError(Val.takeError()); 246 return Default.str(); 247 } 248 249 /// Read a named option from the ``Context`` and parse it as an 250 /// integral type ``T``. 251 /// 252 /// Reads the option with the check-local name \p LocalName from the 253 /// ``CheckOptions``. If the corresponding key is not present, returns 254 /// a ``MissingOptionError``. If the corresponding key can't be parsed as 255 /// a ``T``, return an ``UnparseableIntegerOptionError``. 256 template <typename T> 257 std::enable_if_t<std::is_integral<T>::value, llvm::Expected<T>> get(StringRef LocalName)258 get(StringRef LocalName) const { 259 if (llvm::Expected<std::string> Value = get(LocalName)) { 260 T Result{}; 261 if (!StringRef(*Value).getAsInteger(10, Result)) 262 return Result; 263 return llvm::make_error<UnparseableIntegerOptionError>( 264 (NamePrefix + LocalName).str(), *Value); 265 } else 266 return std::move(Value.takeError()); 267 } 268 269 /// Read a named option from the ``Context`` and parse it as an 270 /// integral type ``T``. 271 /// 272 /// Reads the option with the check-local name \p LocalName from the 273 /// ``CheckOptions``. If the corresponding key is not present or it can't be 274 /// parsed as a ``T``, returns \p Default. 275 template <typename T> get(StringRef LocalName,T Default)276 std::enable_if_t<std::is_integral<T>::value, T> get(StringRef LocalName, 277 T Default) const { 278 if (llvm::Expected<T> ValueOr = get<T>(LocalName)) 279 return *ValueOr; 280 else 281 reportOptionParsingError(ValueOr.takeError()); 282 return Default; 283 } 284 285 /// Read a named option from the ``Context`` and parse it as an 286 /// integral type ``T``. 287 /// 288 /// Reads the option with the check-local name \p LocalName from local or 289 /// global ``CheckOptions``. Gets local option first. If local is not 290 /// present, falls back to get global option. If global option is not 291 /// present either, returns a ``MissingOptionError``. If the corresponding 292 /// key can't be parsed as a ``T``, return an 293 /// ``UnparseableIntegerOptionError``. 294 template <typename T> 295 std::enable_if_t<std::is_integral<T>::value, llvm::Expected<T>> getLocalOrGlobal(StringRef LocalName)296 getLocalOrGlobal(StringRef LocalName) const { 297 llvm::Expected<std::string> ValueOr = get(LocalName); 298 bool IsGlobal = false; 299 if (!ValueOr) { 300 IsGlobal = true; 301 llvm::consumeError(ValueOr.takeError()); 302 ValueOr = getLocalOrGlobal(LocalName); 303 if (!ValueOr) 304 return std::move(ValueOr.takeError()); 305 } 306 T Result{}; 307 if (!StringRef(*ValueOr).getAsInteger(10, Result)) 308 return Result; 309 return llvm::make_error<UnparseableIntegerOptionError>( 310 (IsGlobal ? LocalName.str() : (NamePrefix + LocalName).str()), 311 *ValueOr); 312 } 313 314 /// Read a named option from the ``Context`` and parse it as an 315 /// integral type ``T``. 316 /// 317 /// Reads the option with the check-local name \p LocalName from local or 318 /// global ``CheckOptions``. Gets local option first. If local is not 319 /// present, falls back to get global option. If global option is not 320 /// present either or it can't be parsed as a ``T``, returns \p Default. 321 template <typename T> 322 std::enable_if_t<std::is_integral<T>::value, T> getLocalOrGlobal(StringRef LocalName,T Default)323 getLocalOrGlobal(StringRef LocalName, T Default) const { 324 if (llvm::Expected<T> ValueOr = getLocalOrGlobal<T>(LocalName)) 325 return *ValueOr; 326 else 327 reportOptionParsingError(ValueOr.takeError()); 328 return Default; 329 } 330 331 /// Read a named option from the ``Context`` and parse it as an 332 /// enum type ``T``. 333 /// 334 /// Reads the option with the check-local name \p LocalName from the 335 /// ``CheckOptions``. If the corresponding key is not present, returns a 336 /// ``MissingOptionError``. If the key can't be parsed as a ``T`` returns a 337 /// ``UnparseableEnumOptionError``. 338 /// 339 /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to 340 /// supply the mapping required to convert between ``T`` and a string. 341 template <typename T> 342 std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>> 343 get(StringRef LocalName, bool IgnoreCase = false) const { 344 if (llvm::Expected<int64_t> ValueOr = 345 getEnumInt(LocalName, typeEraseMapping<T>(), false, IgnoreCase)) 346 return static_cast<T>(*ValueOr); 347 else 348 return std::move(ValueOr.takeError()); 349 } 350 351 /// Read a named option from the ``Context`` and parse it as an 352 /// enum type ``T``. 353 /// 354 /// Reads the option with the check-local name \p LocalName from the 355 /// ``CheckOptions``. If the corresponding key is not present or it can't be 356 /// parsed as a ``T``, returns \p Default. 357 /// 358 /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to 359 /// supply the mapping required to convert between ``T`` and a string. 360 template <typename T> 361 std::enable_if_t<std::is_enum<T>::value, T> 362 get(StringRef LocalName, T Default, bool IgnoreCase = false) const { 363 if (auto ValueOr = get<T>(LocalName, IgnoreCase)) 364 return *ValueOr; 365 else 366 reportOptionParsingError(ValueOr.takeError()); 367 return Default; 368 } 369 370 /// Read a named option from the ``Context`` and parse it as an 371 /// enum type ``T``. 372 /// 373 /// Reads the option with the check-local name \p LocalName from local or 374 /// global ``CheckOptions``. Gets local option first. If local is not 375 /// present, falls back to get global option. If global option is not 376 /// present either, returns a ``MissingOptionError``. If the key can't be 377 /// parsed as a ``T`` returns a ``UnparseableEnumOptionError``. 378 /// 379 /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to 380 /// supply the mapping required to convert between ``T`` and a string. 381 template <typename T> 382 std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>> 383 getLocalOrGlobal(StringRef LocalName, bool IgnoreCase = false) const { 384 if (llvm::Expected<int64_t> ValueOr = 385 getEnumInt(LocalName, typeEraseMapping<T>(), true, IgnoreCase)) 386 return static_cast<T>(*ValueOr); 387 else 388 return std::move(ValueOr.takeError()); 389 } 390 391 /// Read a named option from the ``Context`` and parse it as an 392 /// enum type ``T``. 393 /// 394 /// Reads the option with the check-local name \p LocalName from local or 395 /// global ``CheckOptions``. Gets local option first. If local is not 396 /// present, falls back to get global option. If global option is not 397 /// present either or it can't be parsed as a ``T``, returns \p Default. 398 /// 399 /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to 400 /// supply the mapping required to convert between ``T`` and a string. 401 template <typename T> 402 std::enable_if_t<std::is_enum<T>::value, T> 403 getLocalOrGlobal(StringRef LocalName, T Default, 404 bool IgnoreCase = false) const { 405 if (auto ValueOr = getLocalOrGlobal<T>(LocalName, IgnoreCase)) 406 return *ValueOr; 407 else 408 reportOptionParsingError(ValueOr.takeError()); 409 return Default; 410 } 411 412 /// Returns the value for the option \p LocalName represented as a ``T``. 413 /// If the option is missing returns None, if the option can't be parsed 414 /// as a ``T``, log that to stderr and return None. 415 template <typename T = std::string> getOptional(StringRef LocalName)416 llvm::Optional<T> getOptional(StringRef LocalName) const { 417 if (auto ValueOr = get<T>(LocalName)) 418 return *ValueOr; 419 else 420 reportOptionParsingError(ValueOr.takeError()); 421 return llvm::None; 422 } 423 424 /// Returns the value for the local or global option \p LocalName 425 /// represented as a ``T``. 426 /// If the option is missing returns None, if the 427 /// option can't be parsed as a ``T``, log that to stderr and return None. 428 template <typename T = std::string> getOptionalLocalOrGlobal(StringRef LocalName)429 llvm::Optional<T> getOptionalLocalOrGlobal(StringRef LocalName) const { 430 if (auto ValueOr = getLocalOrGlobal<T>(LocalName)) 431 return *ValueOr; 432 else 433 reportOptionParsingError(ValueOr.takeError()); 434 return llvm::None; 435 } 436 437 /// Stores an option with the check-local name \p LocalName with 438 /// string value \p Value to \p Options. 439 void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, 440 StringRef Value) const; 441 442 /// Stores an option with the check-local name \p LocalName with 443 /// integer value \p Value to \p Options. 444 template <typename T> 445 std::enable_if_t<std::is_integral<T>::value> store(ClangTidyOptions::OptionMap & Options,StringRef LocalName,T Value)446 store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, 447 T Value) const { 448 storeInt(Options, LocalName, Value); 449 } 450 451 /// Stores an option with the check-local name \p LocalName as the string 452 /// representation of the Enum \p Value to \p Options. 453 /// 454 /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to 455 /// supply the mapping required to convert between ``T`` and a string. 456 template <typename T> 457 std::enable_if_t<std::is_enum<T>::value> store(ClangTidyOptions::OptionMap & Options,StringRef LocalName,T Value)458 store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, 459 T Value) const { 460 ArrayRef<std::pair<T, StringRef>> Mapping = 461 OptionEnumMapping<T>::getEnumMapping(); 462 auto Iter = llvm::find_if( 463 Mapping, [&](const std::pair<T, StringRef> &NameAndEnum) { 464 return NameAndEnum.first == Value; 465 }); 466 assert(Iter != Mapping.end() && "Unknown Case Value"); 467 store(Options, LocalName, Iter->second); 468 } 469 470 private: 471 using NameAndValue = std::pair<int64_t, StringRef>; 472 473 llvm::Expected<int64_t> getEnumInt(StringRef LocalName, 474 ArrayRef<NameAndValue> Mapping, 475 bool CheckGlobal, bool IgnoreCase) const; 476 477 template <typename T> 478 std::enable_if_t<std::is_enum<T>::value, std::vector<NameAndValue>> typeEraseMapping()479 typeEraseMapping() const { 480 ArrayRef<std::pair<T, StringRef>> Mapping = 481 OptionEnumMapping<T>::getEnumMapping(); 482 std::vector<NameAndValue> Result; 483 Result.reserve(Mapping.size()); 484 for (auto &MappedItem : Mapping) { 485 Result.emplace_back(static_cast<int64_t>(MappedItem.first), 486 MappedItem.second); 487 } 488 return Result; 489 } 490 491 void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName, 492 int64_t Value) const; 493 494 /// Emits a diagnostic if \p Err is not a MissingOptionError. 495 void reportOptionParsingError(llvm::Error &&Err) const; 496 497 std::string NamePrefix; 498 const ClangTidyOptions::OptionMap &CheckOptions; 499 ClangTidyContext *Context; 500 }; 501 502 private: 503 void run(const ast_matchers::MatchFinder::MatchResult &Result) override; getID()504 StringRef getID() const override { return CheckName; } 505 std::string CheckName; 506 ClangTidyContext *Context; 507 508 protected: 509 OptionsView Options; 510 /// Returns the main file name of the current translation unit. getCurrentMainFile()511 StringRef getCurrentMainFile() const { return Context->getCurrentFile(); } 512 /// Returns the language options from the context. getLangOpts()513 const LangOptions &getLangOpts() const { return Context->getLangOpts(); } 514 }; 515 516 /// Read a named option from the ``Context`` and parse it as a bool. 517 /// 518 /// Reads the option with the check-local name \p LocalName from the 519 /// ``CheckOptions``. If the corresponding key is not present, returns 520 /// a ``MissingOptionError``. If the corresponding key can't be parsed as 521 /// a bool, return an ``UnparseableIntegerOptionError``. 522 template <> 523 llvm::Expected<bool> 524 ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName) const; 525 526 /// Read a named option from the ``Context`` and parse it as a bool. 527 /// 528 /// Reads the option with the check-local name \p LocalName from the 529 /// ``CheckOptions``. If the corresponding key is not present or it can't be 530 /// parsed as a bool, returns \p Default. 531 template <> 532 bool ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName, 533 bool Default) const; 534 535 /// Read a named option from the ``Context`` and parse it as a bool. 536 /// 537 /// Reads the option with the check-local name \p LocalName from local or 538 /// global ``CheckOptions``. Gets local option first. If local is not 539 /// present, falls back to get global option. If global option is not 540 /// present either, returns a ``MissingOptionError``. If the corresponding 541 /// key can't be parsed as a bool, return an 542 /// ``UnparseableIntegerOptionError``. 543 template <> 544 llvm::Expected<bool> 545 ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName) const; 546 547 /// Read a named option from the ``Context`` and parse it as a bool. 548 /// 549 /// Reads the option with the check-local name \p LocalName from local or 550 /// global ``CheckOptions``. Gets local option first. If local is not 551 /// present, falls back to get global option. If global option is not 552 /// present either or it can't be parsed as a bool, returns \p Default. 553 template <> 554 bool ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName, 555 bool Default) const; 556 557 /// Stores an option with the check-local name \p LocalName with 558 /// bool value \p Value to \p Options. 559 template <> 560 void ClangTidyCheck::OptionsView::store<bool>( 561 ClangTidyOptions::OptionMap &Options, StringRef LocalName, 562 bool Value) const; 563 564 /// Returns the value for the option \p LocalName. 565 /// If the option is missing returns None. 566 template <> 567 Optional<std::string> ClangTidyCheck::OptionsView::getOptional<std::string>( 568 StringRef LocalName) const; 569 570 /// Returns the value for the local or global option \p LocalName. 571 /// If the option is missing returns None. 572 template <> 573 Optional<std::string> 574 ClangTidyCheck::OptionsView::getOptionalLocalOrGlobal<std::string>( 575 StringRef LocalName) const; 576 577 } // namespace tidy 578 } // namespace clang 579 580 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H 581