diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.h b/clang-tools-extra/clang-tidy/ClangTidyCheck.h --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.h +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.h @@ -268,7 +268,7 @@ if (llvm::Expected ValueOr = get(LocalName)) return *ValueOr; else - logErrToStdErr(ValueOr.takeError()); + logIfOptionParsingError(ValueOr.takeError()); return Default; } @@ -314,7 +314,7 @@ if (llvm::Expected ValueOr = getLocalOrGlobal(LocalName)) return *ValueOr; else - logErrToStdErr(ValueOr.takeError()); + logIfOptionParsingError(ValueOr.takeError()); return Default; } @@ -353,7 +353,7 @@ if (auto ValueOr = get(LocalName, IgnoreCase)) return *ValueOr; else - logErrToStdErr(ValueOr.takeError()); + logIfOptionParsingError(ValueOr.takeError()); return Default; } @@ -395,10 +395,35 @@ if (auto ValueOr = getLocalOrGlobal(LocalName, IgnoreCase)) return *ValueOr; else - logErrToStdErr(ValueOr.takeError()); + logIfOptionParsingError(ValueOr.takeError()); return Default; } + /// Returns the value for the option \p LocalName represented as a ``T``. + /// If the option is missing returns None, if the option can't be parsed + /// as a ``T``, log that to stderr and return None. + template + llvm::Optional getOptional(StringRef LocalName) const { + if (auto ValueOr = get(LocalName)) + return *ValueOr; + else + logIfOptionParsingError(ValueOr.takeError()); + return llvm::None; + } + + /// Returns the value for the local or global option \p LocalName + /// represented as a ``T``. + /// If the option is missing returns None, if the + /// option can't be parsed as a ``T``, log that to stderr and return None. + template + llvm::Optional getOptionalLocalOrGlobal(StringRef LocalName) const { + if (auto ValueOr = getLocalOrGlobal(LocalName)) + return *ValueOr; + else + logIfOptionParsingError(ValueOr.takeError()); + return llvm::None; + } + /// Stores an option with the check-local name \p LocalName with /// string value \p Value to \p Options. void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, @@ -456,7 +481,8 @@ void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName, int64_t Value) const; - static void logErrToStdErr(llvm::Error &&Err); + /// Logs an Error to stderr if a \p Err is not a MissingOptionError. + static void logIfOptionParsingError(llvm::Error &&Err); std::string NamePrefix; const ClangTidyOptions::OptionMap &CheckOptions; @@ -524,6 +550,19 @@ ClangTidyOptions::OptionMap &Options, StringRef LocalName, bool Value) const; +/// Returns the value for the option \p LocalName. +/// If the option is missing returns None. +template <> +Optional ClangTidyCheck::OptionsView::getOptional( + StringRef LocalName) const; + +/// Returns the value for the local or global option \p LocalName. +/// If the option is missing returns None. +template <> +Optional +ClangTidyCheck::OptionsView::getOptionalLocalOrGlobal( + StringRef LocalName) const; + } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" +#include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" namespace clang { @@ -126,7 +127,7 @@ llvm::Expected ValueOr = get(LocalName); if (ValueOr) return *ValueOr; - logErrToStdErr(ValueOr.takeError()); + logIfOptionParsingError(ValueOr.takeError()); return Default; } @@ -145,7 +146,7 @@ llvm::Expected ValueOr = getLocalOrGlobal(LocalName); if (ValueOr) return *ValueOr; - logErrToStdErr(ValueOr.takeError()); + logIfOptionParsingError(ValueOr.takeError()); return Default; } @@ -204,13 +205,33 @@ Iter->getValue().Value); } -void ClangTidyCheck::OptionsView::logErrToStdErr(llvm::Error &&Err) { - llvm::logAllUnhandledErrors( - llvm::handleErrors(std::move(Err), - [](const MissingOptionError &) -> llvm::Error { - return llvm::Error::success(); - }), - llvm::errs(), "warning: "); +void ClangTidyCheck::OptionsView::logIfOptionParsingError(llvm::Error &&Err) { + if (auto RemainingErrors = + llvm::handleErrors(std::move(Err), [](const MissingOptionError &) {})) + llvm::logAllUnhandledErrors(std::move(RemainingErrors), + llvm::WithColor::warning()); } + +template <> +Optional ClangTidyCheck::OptionsView::getOptional( + StringRef LocalName) const { + if (auto ValueOr = get(LocalName)) + return *ValueOr; + else + consumeError(ValueOr.takeError()); + return llvm::None; +} + +template <> +Optional +ClangTidyCheck::OptionsView::getOptionalLocalOrGlobal( + StringRef LocalName) const { + if (auto ValueOr = getLocalOrGlobal(LocalName)) + return *ValueOr; + else + consumeError(ValueOr.takeError()); + return llvm::None; +} + } // namespace tidy } // namespace clang