diff --git a/clang-tools-extra/clang-tidy/ClangTidy.h b/clang-tools-extra/clang-tidy/ClangTidy.h --- a/clang-tools-extra/clang-tidy/ClangTidy.h +++ b/clang-tools-extra/clang-tidy/ClangTidy.h @@ -60,11 +60,12 @@ struct NamesAndOptions { llvm::StringSet<> Names; - llvm::StringSet<> Options; + OptionsCollection Options; }; NamesAndOptions -getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers = true); +getAllChecksAndOptions(StringRef EnabledChecks = "*", + bool AllowEnablingAnalyzerAlphaCheckers = true); /// Returns the effective check-specific options. /// diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -624,10 +624,11 @@ } NamesAndOptions -getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers) { +getAllChecksAndOptions(StringRef EnabledChecks, + bool AllowEnablingAnalyzerAlphaCheckers) { NamesAndOptions Result; ClangTidyOptions Opts; - Opts.Checks = "*"; + Opts.Checks.emplace(EnabledChecks); clang::tidy::ClangTidyContext Context( std::make_unique(ClangTidyGlobalOptions(), Opts), AllowEnablingAnalyzerAlphaCheckers); @@ -653,7 +654,8 @@ Context.setOptionsCollector(&Result.Options); for (const auto &Factory : Factories) { - Factory.getValue()(Factory.getKey(), &Context); + if (Context.isCheckEnabled(Factory.getKey())) + Factory.getValue()(Factory.getKey(), &Context); } return Result; 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 @@ -164,6 +164,9 @@ /// \p Default. StringRef get(StringRef LocalName, StringRef Default) const; + StringRef getList(StringRef LocalName, StringRef Default) const; + llvm::Optional getList(StringRef LocalName) const; + /// Read a named option from the ``Context``. /// /// Reads the option with the check-local name \p LocalName from local or @@ -172,6 +175,8 @@ /// present either, return ``None``. llvm::Optional getLocalOrGlobal(StringRef LocalName) const; + llvm::Optional getLocalOrGlobalList(StringRef LocalName) const; + /// Read a named option from the ``Context``. /// /// Reads the option with the check-local name \p LocalName from local or @@ -179,6 +184,8 @@ /// present, falls back to get global option. If global option is not /// present either, returns \p Default. StringRef getLocalOrGlobal(StringRef LocalName, StringRef Default) const; + StringRef getLocalOrGlobalList(StringRef LocalName, + StringRef Default) const; /// Read a named option from the ``Context`` and parse it as an /// integral type ``T``. @@ -192,7 +199,9 @@ template std::enable_if_t::value, llvm::Optional> get(StringRef LocalName) const { - if (llvm::Optional Value = get(LocalName)) { + if (llvm::Optional Value = getInternal( + LocalName, std::is_signed_v ? OptionType::Signed + : OptionType::Unsigned)) { T Result{}; if (!StringRef(*Value).getAsInteger(10, Result)) return Result; @@ -229,11 +238,13 @@ template std::enable_if_t::value, llvm::Optional> getLocalOrGlobal(StringRef LocalName) const { - llvm::Optional ValueOr = get(LocalName); + static constexpr OptionType::Type Type = + std::is_signed_v ? OptionType::Signed : OptionType::Unsigned; + llvm::Optional ValueOr = getInternal(LocalName, Type); bool IsGlobal = false; if (!ValueOr) { IsGlobal = true; - ValueOr = getLocalOrGlobal(LocalName); + ValueOr = getInternal(LocalName, Type); if (!ValueOr) return None; } @@ -399,7 +410,10 @@ void storeInt(ClangTidyOptions::OptionMap &Options, StringRef LocalName, int64_t Value) const; - + Optional getInternal(StringRef Name, + OptionType::Type Type) const; + Optional getInternalGlobal(StringRef Name, + OptionType::Type Type) const; std::string NamePrefix; const ClangTidyOptions::OptionMap &CheckOptions; ClangTidyContext *Context; 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 @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "ClangTidyCheck.h" +#include "ClangTidyDiagnosticConsumer.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -52,22 +54,29 @@ Context(Context) {} llvm::Optional -ClangTidyCheck::OptionsView::get(StringRef LocalName) const { +ClangTidyCheck::OptionsView::getInternal(StringRef LocalName, + OptionType::Type Type) const { if (Context->getOptionsCollector()) - Context->getOptionsCollector()->insert((NamePrefix + LocalName).str()); + Context->getOptionsCollector()->try_emplace((NamePrefix + LocalName).str(), + Type); const auto &Iter = CheckOptions.find((NamePrefix + LocalName).str()); if (Iter != CheckOptions.end()) return StringRef(Iter->getValue().Value); return None; } +llvm::Optional +ClangTidyCheck::OptionsView::get(StringRef LocalName) const { + return getInternal(LocalName, OptionType::String); +} + static ClangTidyOptions::OptionMap::const_iterator findPriorityOption(const ClangTidyOptions::OptionMap &Options, StringRef NamePrefix, StringRef LocalName, - llvm::StringSet<> *Collector) { + OptionsCollection *Collector, OptionType::Type Type) { if (Collector) { - Collector->insert((NamePrefix + LocalName).str()); - Collector->insert(LocalName); + Collector->try_emplace((NamePrefix + LocalName).str(), Type); + Collector->try_emplace(LocalName, Type); } auto IterLocal = Options.find((NamePrefix + LocalName).str()); auto IterGlobal = Options.find(LocalName); @@ -81,16 +90,27 @@ } llvm::Optional -ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName) const { +ClangTidyCheck::OptionsView::getInternalGlobal(StringRef LocalName, + OptionType::Type Type) const { + auto Iter = findPriorityOption(CheckOptions, NamePrefix, LocalName, - Context->getOptionsCollector()); + Context->getOptionsCollector(), Type); if (Iter != CheckOptions.end()) return StringRef(Iter->getValue().Value); return None; } -static Optional getAsBool(StringRef Value, - const llvm::Twine &LookupName) { +llvm::Optional +ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName) const { + return getInternalGlobal(LocalName, OptionType::String); +} + +llvm::Optional +ClangTidyCheck::OptionsView::getLocalOrGlobalList(StringRef LocalName) const { + return getInternalGlobal(LocalName, OptionType::List); +} + +static Optional getAsBool(StringRef Value) { if (llvm::Optional Parsed = llvm::yaml::parseBool(Value)) return *Parsed; @@ -105,8 +125,9 @@ template <> llvm::Optional ClangTidyCheck::OptionsView::get(StringRef LocalName) const { - if (llvm::Optional ValueOr = get(LocalName)) { - if (auto Result = getAsBool(*ValueOr, NamePrefix + LocalName)) + if (llvm::Optional ValueOr = + getInternal(LocalName, OptionType::Boolean)) { + if (auto Result = getAsBool(*ValueOr)) return Result; diagnoseBadBooleanOption(NamePrefix + LocalName, *ValueOr); } @@ -116,10 +137,11 @@ template <> llvm::Optional ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName) const { - auto Iter = findPriorityOption(CheckOptions, NamePrefix, LocalName, - Context->getOptionsCollector()); + auto Iter = + findPriorityOption(CheckOptions, NamePrefix, LocalName, + Context->getOptionsCollector(), OptionType::Boolean); if (Iter != CheckOptions.end()) { - if (auto Result = getAsBool(Iter->getValue().Value, Iter->getKey())) + if (auto Result = getAsBool(Iter->getValue().Value)) return Result; diagnoseBadBooleanOption(Iter->getKey(), Iter->getValue().Value); } @@ -148,11 +170,19 @@ llvm::Optional ClangTidyCheck::OptionsView::getEnumInt( StringRef LocalName, ArrayRef Mapping, bool CheckGlobal, bool IgnoreCase) const { - if (!CheckGlobal && Context->getOptionsCollector()) - Context->getOptionsCollector()->insert((NamePrefix + LocalName).str()); + if (Context->getOptionsCollector()) { + auto ItemRange = llvm::make_second_range(Mapping); + auto Items = std::make_unique>(ItemRange.begin(), + ItemRange.end()); + if (CheckGlobal) + Context->getOptionsCollector()->try_emplace( + LocalName, std::make_unique>(*Items.get())); + Context->getOptionsCollector()->try_emplace((NamePrefix + LocalName).str(), + std::move(Items)); + } auto Iter = CheckGlobal ? findPriorityOption(CheckOptions, NamePrefix, LocalName, - Context->getOptionsCollector()) + nullptr, OptionType::Custom) : CheckOptions.find((NamePrefix + LocalName).str()); if (Iter == CheckOptions.end()) return None; @@ -224,5 +254,21 @@ StringRef Default) const { return getLocalOrGlobal(LocalName).value_or(Default); } + +StringRef +ClangTidyCheck::OptionsView::getLocalOrGlobalList(StringRef LocalName, + StringRef Default) const { + return getLocalOrGlobalList(LocalName).value_or(Default); +} + +StringRef ClangTidyCheck::OptionsView::getList(StringRef LocalName, + StringRef Default) const { + return getList(LocalName).value_or(Default); +} + +llvm::Optional +ClangTidyCheck::OptionsView::getList(StringRef LocalName) const { + return getInternal(LocalName, OptionType::List); +} } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h @@ -15,8 +15,9 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Tooling/Core/Diagnostic.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringSet.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Regex.h" +#include namespace clang { @@ -55,6 +56,40 @@ } }; +class OptionType { +public: + enum Type { String, Boolean, Unsigned, Signed, List, Custom }; + OptionType(const OptionType &) = delete; + OptionType(OptionType &&) = delete; + OptionType &operator=(const OptionType &) = delete; + OptionType &operator=(OptionType &&) = delete; + + explicit OptionType(Type T) : Data(nullptr, T){}; + explicit OptionType(std::unique_ptr> EnumValues) + : Data(EnumValues.release(), Custom) {} + + Type getType() const { return Data.getInt(); } + bool hasEnum() const { + return getType() == Custom && Data.getPointer() != nullptr; + } + + ArrayRef getEnumValue() const { + assert(hasEnum()); + return *Data.getPointer(); + } + + ~OptionType() { + if (hasEnum()) { + delete Data.getPointer(); + } + } + +private: + llvm::PointerIntPair *, 3, Type> Data; +}; + +using OptionsCollection = llvm::StringMap; + /// Every \c ClangTidyCheck reports errors through a \c DiagnosticsEngine /// provided by this context. /// @@ -202,10 +237,10 @@ DiagEngine->getDiagnosticIDs()->getDescription(DiagnosticID))); } - void setOptionsCollector(llvm::StringSet<> *Collector) { + void setOptionsCollector(OptionsCollection *Collector) { OptionsCollector = Collector; } - llvm::StringSet<> *getOptionsCollector() const { return OptionsCollector; } + OptionsCollection *getOptionsCollector() const { return OptionsCollector; } private: // Writes to Stats. @@ -236,7 +271,7 @@ bool SelfContainedDiags; NoLintDirectiveHandler NoLintHandler; - llvm::StringSet<> *OptionsCollector = nullptr; + OptionsCollection *OptionsCollector = nullptr; }; /// Gets the Fix attached to \p Diagnostic. diff --git a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp --- a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp @@ -25,7 +25,7 @@ ClangTidyContext *Context) : ClangTidyCheck(Name, Context), StringLikeClasses(utils::options::parseStringList( - Options.get("StringLikeClasses", "::std::basic_string"))), + Options.getList("StringLikeClasses", "::std::basic_string"))), IncludeInserter(Options.getLocalOrGlobal("IncludeStyle", utils::IncludeSorter::IS_LLVM), areDiagsSelfContained()), diff --git a/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp --- a/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StringFindStrContainsCheck.cpp @@ -86,7 +86,7 @@ StringRef Name, ClangTidyContext *Context) : TransformerClangTidyCheck(Name, Context), StringLikeClassesOption(utils::options::parseStringList( - Options.get("StringLikeClasses", DefaultStringLikeClasses))), + Options.getList("StringLikeClasses", DefaultStringLikeClasses))), AbseilStringsMatchHeaderOption(Options.get( "AbseilStringsMatchHeader", DefaultAbseilStringsMatchHeader)) { setRule( diff --git a/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp b/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp --- a/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp +++ b/clang-tools-extra/clang-tidy/android/ComparisonInTempFailureRetryCheck.cpp @@ -21,7 +21,7 @@ ComparisonInTempFailureRetryCheck::ComparisonInTempFailureRetryCheck( StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - RawRetryList(Options.get("RetryMacros", "TEMP_FAILURE_RETRY")) { + RawRetryList(Options.getList("RetryMacros", "TEMP_FAILURE_RETRY")) { StringRef(RawRetryList).split(RetryMacros, ",", -1, false); } diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp @@ -79,7 +79,7 @@ CheckFunctionCalls(Options.get("CheckFunctionCalls", false)), RawAssertList(Options.get("AssertMacros", "assert,NSAssert,NSCAssert")), IgnoredFunctions(utils::options::parseListPair( - "__builtin_expect;", Options.get("IgnoredFunctions", ""))) { + "__builtin_expect;", Options.getList("IgnoredFunctions", ""))) { StringRef(RawAssertList).split(AssertMacros, ",", -1, false); } diff --git a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp @@ -91,7 +91,7 @@ DanglingHandleCheck::DanglingHandleCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - HandleClasses(utils::options::parseStringList(Options.get( + HandleClasses(utils::options::parseStringList(Options.getList( "HandleClasses", "std::basic_string_view;std::experimental::basic_string_view"))), IsAHandle(cxxRecordDecl(hasAnyName(HandleClasses)).bind("handle")) {} diff --git a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp @@ -26,11 +26,11 @@ return false; } -DynamicStaticInitializersCheck::DynamicStaticInitializersCheck(StringRef Name, - ClangTidyContext *Context) +DynamicStaticInitializersCheck::DynamicStaticInitializersCheck( + StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - RawStringHeaderFileExtensions(Options.getLocalOrGlobal( - "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) { + RawStringHeaderFileExtensions(Options.getLocalOrGlobalList( + "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) { if (!utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions, utils::defaultFileExtensionDelimiters())) { diff --git a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp @@ -2086,11 +2086,11 @@ : ClangTidyCheck(Name, Context), MinimumLength(clampMinimumLength( Options.get("MinimumLength", DefaultMinimumLength))), - IgnoredParameterNames(optutils::parseStringList( - Options.get("IgnoredParameterNames", DefaultIgnoredParameterNames))), + IgnoredParameterNames(optutils::parseStringList(Options.getList( + "IgnoredParameterNames", DefaultIgnoredParameterNames))), IgnoredParameterTypeSuffixes(optutils::parseStringList( - Options.get("IgnoredParameterTypeSuffixes", - DefaultIgnoredParameterTypeSuffixes))), + Options.getList("IgnoredParameterTypeSuffixes", + DefaultIgnoredParameterTypeSuffixes))), QualifiersMix(Options.get("QualifiersMix", DefaultQualifiersMix)), ModelImplicitConversions(Options.get("ModelImplicitConversions", DefaultModelImplicitConversions)), diff --git a/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.cpp @@ -45,7 +45,7 @@ : RenamerClangTidyCheck(Name, Context), Invert(Options.get("Invert", false)), AllowedIdentifiers(utils::options::parseStringList( - Options.get("AllowedIdentifiers", ""))) {} + Options.getList("AllowedIdentifiers", ""))) {} void ReservedIdentifierCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { RenamerClangTidyCheck::storeOptions(Opts); diff --git a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp @@ -23,7 +23,7 @@ SignedCharMisuseCheck::SignedCharMisuseCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - CharTypdefsToIgnoreList(Options.get("CharTypdefsToIgnore", "")), + CharTypdefsToIgnoreList(Options.getList("CharTypdefsToIgnore", "")), DiagnoseSignedUnsignedCharComparisons( Options.get("DiagnoseSignedUnsignedCharComparisons", true)) {} diff --git a/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp @@ -48,7 +48,7 @@ WarnOnLargeLength(Options.get("WarnOnLargeLength", true)), LargeLengthThreshold(Options.get("LargeLengthThreshold", 0x800000)), StringNames(utils::options::parseStringList( - Options.get("StringNames", DefaultStringNames))) {} + Options.getList("StringNames", DefaultStringNames))) {} void StringConstructorCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "WarnOnLargeLength", WarnOnLargeLength); diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp @@ -38,7 +38,7 @@ SuspiciousIncludeCheck::SuspiciousIncludeCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - RawStringHeaderFileExtensions(Options.getLocalOrGlobal( + RawStringHeaderFileExtensions(Options.getLocalOrGlobalList( "HeaderFileExtensions", utils::defaultHeaderFileExtensions())), RawStringImplementationFileExtensions(Options.getLocalOrGlobal( "ImplementationFileExtensions", diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp @@ -73,7 +73,7 @@ WarnOnLogicalNotComparison( Options.get("WarnOnLogicalNotComparison", false)), StringCompareLikeFunctions( - Options.get("StringCompareLikeFunctions", "")) {} + Options.getList("StringCompareLikeFunctions", "")) {} void SuspiciousStringCompareCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp @@ -35,98 +35,98 @@ UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - CheckedFunctions(Options.get("CheckedFunctions", - "::std::async;" - "::std::launder;" - "::std::remove;" - "::std::remove_if;" - "::std::unique;" - "::std::unique_ptr::release;" - "::std::basic_string::empty;" - "::std::vector::empty;" - "::std::back_inserter;" - "::std::distance;" - "::std::find;" - "::std::find_if;" - "::std::inserter;" - "::std::lower_bound;" - "::std::make_pair;" - "::std::map::count;" - "::std::map::find;" - "::std::map::lower_bound;" - "::std::multimap::equal_range;" - "::std::multimap::upper_bound;" - "::std::set::count;" - "::std::set::find;" - "::std::setfill;" - "::std::setprecision;" - "::std::setw;" - "::std::upper_bound;" - "::std::vector::at;" - // C standard library - "::bsearch;" - "::ferror;" - "::feof;" - "::isalnum;" - "::isalpha;" - "::isblank;" - "::iscntrl;" - "::isdigit;" - "::isgraph;" - "::islower;" - "::isprint;" - "::ispunct;" - "::isspace;" - "::isupper;" - "::iswalnum;" - "::iswprint;" - "::iswspace;" - "::isxdigit;" - "::memchr;" - "::memcmp;" - "::strcmp;" - "::strcoll;" - "::strncmp;" - "::strpbrk;" - "::strrchr;" - "::strspn;" - "::strstr;" - "::wcscmp;" - // POSIX - "::access;" - "::bind;" - "::connect;" - "::difftime;" - "::dlsym;" - "::fnmatch;" - "::getaddrinfo;" - "::getopt;" - "::htonl;" - "::htons;" - "::iconv_open;" - "::inet_addr;" - "::isascii;" - "::isatty;" - "::mmap;" - "::newlocale;" - "::openat;" - "::pathconf;" - "::pthread_equal;" - "::pthread_getspecific;" - "::pthread_mutex_trylock;" - "::readdir;" - "::readlink;" - "::recvmsg;" - "::regexec;" - "::scandir;" - "::semget;" - "::setjmp;" - "::shm_open;" - "::shmget;" - "::sigismember;" - "::strcasecmp;" - "::strsignal;" - "::ttyname")) {} + CheckedFunctions(Options.getList("CheckedFunctions", + "::std::async;" + "::std::launder;" + "::std::remove;" + "::std::remove_if;" + "::std::unique;" + "::std::unique_ptr::release;" + "::std::basic_string::empty;" + "::std::vector::empty;" + "::std::back_inserter;" + "::std::distance;" + "::std::find;" + "::std::find_if;" + "::std::inserter;" + "::std::lower_bound;" + "::std::make_pair;" + "::std::map::count;" + "::std::map::find;" + "::std::map::lower_bound;" + "::std::multimap::equal_range;" + "::std::multimap::upper_bound;" + "::std::set::count;" + "::std::set::find;" + "::std::setfill;" + "::std::setprecision;" + "::std::setw;" + "::std::upper_bound;" + "::std::vector::at;" + // C standard library + "::bsearch;" + "::ferror;" + "::feof;" + "::isalnum;" + "::isalpha;" + "::isblank;" + "::iscntrl;" + "::isdigit;" + "::isgraph;" + "::islower;" + "::isprint;" + "::ispunct;" + "::isspace;" + "::isupper;" + "::iswalnum;" + "::iswprint;" + "::iswspace;" + "::isxdigit;" + "::memchr;" + "::memcmp;" + "::strcmp;" + "::strcoll;" + "::strncmp;" + "::strpbrk;" + "::strrchr;" + "::strspn;" + "::strstr;" + "::wcscmp;" + // POSIX + "::access;" + "::bind;" + "::connect;" + "::difftime;" + "::dlsym;" + "::fnmatch;" + "::getaddrinfo;" + "::getopt;" + "::htonl;" + "::htons;" + "::iconv_open;" + "::inet_addr;" + "::isascii;" + "::isatty;" + "::mmap;" + "::newlocale;" + "::openat;" + "::pathconf;" + "::pthread_equal;" + "::pthread_getspecific;" + "::pthread_mutex_trylock;" + "::readdir;" + "::readlink;" + "::recvmsg;" + "::regexec;" + "::scandir;" + "::semget;" + "::setjmp;" + "::shm_open;" + "::shmget;" + "::sigismember;" + "::strcasecmp;" + "::strsignal;" + "::ttyname")) {} void UnusedReturnValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "CheckedFunctions", CheckedFunctions); diff --git a/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp b/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp --- a/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cert/NonTrivialTypesLibcMemoryCallsCheck.cpp @@ -55,9 +55,9 @@ NonTrivialTypesLibcMemoryCallsCheck::NonTrivialTypesLibcMemoryCallsCheck( StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - MemSetNames(Options.get("MemSetNames", "")), - MemCpyNames(Options.get("MemCpyNames", "")), - MemCmpNames(Options.get("MemCmpNames", "")) {} + MemSetNames(Options.getList("MemSetNames", "")), + MemCpyNames(Options.getList("MemCpyNames", "")), + MemCmpNames(Options.getList("MemCmpNames", "")) {} void NonTrivialTypesLibcMemoryCallsCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NarrowingConversionsCheck.cpp @@ -37,7 +37,8 @@ WarnWithinTemplateInstantiation( Options.get("WarnWithinTemplateInstantiation", false)), WarnOnEquivalentBitWidth(Options.get("WarnOnEquivalentBitWidth", true)), - IgnoreConversionFromTypes(Options.get("IgnoreConversionFromTypes", "")), + IgnoreConversionFromTypes( + Options.getList("IgnoreConversionFromTypes", "")), PedanticMode(Options.get("PedanticMode", false)) {} void NarrowingConversionsCheck::storeOptions( diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.h --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.h @@ -27,9 +27,9 @@ /// Construct Checker and read in configuration for function names. NoMallocCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - AllocList(Options.get("Allocations", "::malloc;::calloc")), - ReallocList(Options.get("Reallocations", "::realloc")), - DeallocList(Options.get("Deallocations", "::free")) {} + AllocList(Options.getList("Allocations", "::malloc;::calloc")), + ReallocList(Options.getList("Reallocations", "::realloc")), + DeallocList(Options.getList("Deallocations", "::free")) {} bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus; diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.h @@ -24,10 +24,10 @@ public: OwningMemoryCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - LegacyResourceProducers(Options.get( + LegacyResourceProducers(Options.getList( "LegacyResourceProducers", "::malloc;::aligned_alloc;::realloc;" "::calloc;::fopen;::freopen;::tmpfile")), - LegacyResourceConsumers(Options.get( + LegacyResourceConsumers(Options.getList( "LegacyResourceConsumers", "::free;::realloc;::freopen;::fclose")) { } bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { diff --git a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp --- a/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/GlobalNamesInHeadersCheck.cpp @@ -22,7 +22,7 @@ GlobalNamesInHeadersCheck::GlobalNamesInHeadersCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - RawStringHeaderFileExtensions(Options.getLocalOrGlobal( + RawStringHeaderFileExtensions(Options.getLocalOrGlobalList( "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) { if (!utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions, diff --git a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp --- a/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp +++ b/clang-tools-extra/clang-tidy/google/UnnamedNamespaceInHeaderCheck.cpp @@ -21,7 +21,7 @@ UnnamedNamespaceInHeaderCheck::UnnamedNamespaceInHeaderCheck( StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - RawStringHeaderFileExtensions(Options.getLocalOrGlobal( + RawStringHeaderFileExtensions(Options.getLocalOrGlobalList( "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) { if (!utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions, diff --git a/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp b/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp --- a/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp @@ -31,7 +31,7 @@ ClangTidyContext *Context) : ClangTidyCheck(Name, Context), UseHeaderFileExtension(Options.get("UseHeaderFileExtension", true)), - RawStringHeaderFileExtensions(Options.getLocalOrGlobal( + RawStringHeaderFileExtensions(Options.getLocalOrGlobalList( "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) { if (!utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions, diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp @@ -111,20 +111,20 @@ UseEmplaceCheck::UseEmplaceCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IgnoreImplicitConstructors(Options.get( "IgnoreImplicitConstructors", false)), - ContainersWithPushBack(utils::options::parseStringList(Options.get( + ContainersWithPushBack(utils::options::parseStringList(Options.getList( "ContainersWithPushBack", DefaultContainersWithPushBack))), ContainersWithPush(utils::options::parseStringList( Options.get("ContainersWithPush", DefaultContainersWithPush))), - ContainersWithPushFront(utils::options::parseStringList(Options.get( + ContainersWithPushFront(utils::options::parseStringList(Options.getList( "ContainersWithPushFront", DefaultContainersWithPushFront))), SmartPointers(utils::options::parseStringList( - Options.get("SmartPointers", DefaultSmartPointers))), + Options.getList("SmartPointers", DefaultSmartPointers))), TupleTypes(utils::options::parseStringList( - Options.get("TupleTypes", DefaultTupleTypes))), + Options.getList("TupleTypes", DefaultTupleTypes))), TupleMakeFunctions(utils::options::parseStringList( - Options.get("TupleMakeFunctions", DefaultTupleMakeFunctions))), + Options.getList("TupleMakeFunctions", DefaultTupleMakeFunctions))), EmplacyFunctions(utils::options::parseStringList( - Options.get("EmplacyFunctions", DefaultEmplacyFunctions))) {} + Options.getList("EmplacyFunctions", DefaultEmplacyFunctions))) {} void UseEmplaceCheck::registerMatchers(MatchFinder *Finder) { // FIXME: Bunch of functionality that could be easily added: diff --git a/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp b/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp --- a/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp +++ b/clang-tools-extra/clang-tidy/objc/ForbiddenSubclassingCheck.cpp @@ -39,14 +39,11 @@ } // namespace -ForbiddenSubclassingCheck::ForbiddenSubclassingCheck( - StringRef Name, - ClangTidyContext *Context) +ForbiddenSubclassingCheck::ForbiddenSubclassingCheck(StringRef Name, + ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - ForbiddenSuperClassNames( - utils::options::parseStringList( - Options.get("ClassNames", DefaultForbiddenSuperClassNames))) { -} + ForbiddenSuperClassNames(utils::options::parseStringList( + Options.getList("ClassNames", DefaultForbiddenSuperClassNames))) {} void ForbiddenSubclassingCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( diff --git a/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp b/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/FasterStringFindCheck.cpp @@ -51,8 +51,8 @@ ClangTidyContext *Context) : ClangTidyCheck(Name, Context), StringLikeClasses(utils::options::parseStringList( - Options.get("StringLikeClasses", - "::std::basic_string;::std::basic_string_view"))) {} + Options.getList("StringLikeClasses", + "::std::basic_string;::std::basic_string_view"))) {} void FasterStringFindCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "StringLikeClasses", diff --git a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/ForRangeCopyCheck.cpp @@ -24,8 +24,8 @@ ForRangeCopyCheck::ForRangeCopyCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), WarnOnAllAutoCopies(Options.get("WarnOnAllAutoCopies", false)), - AllowedTypes( - utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} + AllowedTypes(utils::options::parseStringList( + Options.getList("AllowedTypes", ""))) {} void ForRangeCopyCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "WarnOnAllAutoCopies", WarnOnAllAutoCopies); diff --git a/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp b/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/InefficientVectorOperationCheck.cpp @@ -78,7 +78,7 @@ StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), VectorLikeClasses(utils::options::parseStringList( - Options.get("VectorLikeClasses", "::std::vector"))), + Options.getList("VectorLikeClasses", "::std::vector"))), EnableProto(Options.getLocalOrGlobal("EnableProto", false)) {} void InefficientVectorOperationCheck::storeOptions( diff --git a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp @@ -21,8 +21,8 @@ NoAutomaticMoveCheck::NoAutomaticMoveCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - AllowedTypes( - utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} + AllowedTypes(utils::options::parseStringList( + Options.getList("AllowedTypes", ""))) {} void NoAutomaticMoveCheck::registerMatchers(MatchFinder *Finder) { const auto ConstLocalVariable = diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp @@ -220,9 +220,9 @@ StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), AllowedTypes( - utils::options::parseStringList(Options.get("AllowedTypes", ""))), + utils::options::parseStringList(Options.getList("AllowedTypes", ""))), ExcludedContainerTypes(utils::options::parseStringList( - Options.get("ExcludedContainerTypes", ""))) {} + Options.getList("ExcludedContainerTypes", ""))) {} void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) { auto LocalVarCopiedFrom = [this](const internal::Matcher &CopyCtorArg) { diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -59,8 +59,8 @@ Inserter(Options.getLocalOrGlobal("IncludeStyle", utils::IncludeSorter::IS_LLVM), areDiagsSelfContained()), - AllowedTypes( - utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} + AllowedTypes(utils::options::parseStringList( + Options.getList("AllowedTypes", ""))) {} void UnnecessaryValueParamCheck::registerMatchers(MatchFinder *Finder) { const auto ExpensiveValueParamDecl = parmVarDecl( diff --git a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/MagicNumbersCheck.cpp @@ -68,8 +68,8 @@ IgnorePowersOf2IntegerValues( Options.get("IgnorePowersOf2IntegerValues", false)), RawIgnoredIntegerValues( - Options.get("IgnoredIntegerValues", DefaultIgnoredIntegerValues)), - RawIgnoredFloatingPointValues(Options.get( + Options.getList("IgnoredIntegerValues", DefaultIgnoredIntegerValues)), + RawIgnoredFloatingPointValues(Options.getList( "IgnoredFloatingPointValues", DefaultIgnoredFloatingPointValues)) { // Process the set of ignored integer values. const std::vector IgnoredIntegerValuesInput = diff --git a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/RedundantStringInitCheck.cpp @@ -58,7 +58,7 @@ ClangTidyContext *Context) : ClangTidyCheck(Name, Context), StringNames(utils::options::parseStringList( - Options.get("StringNames", DefaultStringNames))) {} + Options.getList("StringNames", DefaultStringNames))) {} void RedundantStringInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "StringNames", DefaultStringNames); diff --git a/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp b/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp @@ -22,9 +22,9 @@ SimplifySubscriptExprCheck::SimplifySubscriptExprCheck( StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), Types(utils::options::parseStringList( - Options.get("Types", KDefaultTypes))) { -} + : ClangTidyCheck(Name, Context), + Types(utils::options::parseStringList( + Options.getList("Types", KDefaultTypes))) {} void SimplifySubscriptExprCheck::registerMatchers(MatchFinder *Finder) { const auto TypesMatcher = hasUnqualifiedDesugaredType( diff --git a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/SuspiciousCallArgumentCheck.cpp @@ -527,7 +527,7 @@ } for (StringRef Abbreviation : optutils::parseStringList( - Options.get("Abbreviations", DefaultAbbreviations))) { + Options.getList("Abbreviations", DefaultAbbreviations))) { auto KeyAndValue = Abbreviation.split("="); assert(!KeyAndValue.first.empty() && !KeyAndValue.second.empty()); AbbreviationDictionary.insert( diff --git a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp --- a/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/UppercaseLiteralSuffixCheck.cpp @@ -188,7 +188,7 @@ StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), NewSuffixes( - utils::options::parseStringList(Options.get("NewSuffixes", ""))), + utils::options::parseStringList(Options.getList("NewSuffixes", ""))), IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {} void UppercaseLiteralSuffixCheck::storeOptions( diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -19,6 +19,7 @@ #include "../ClangTidyForceLinker.h" #include "../GlobList.h" #include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Syntax/Nodes.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/PluginLoader.h" @@ -26,6 +27,7 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/WithColor.h" +#include "llvm/Support/raw_ostream.h" using namespace clang::tooling; using namespace llvm; @@ -262,6 +264,17 @@ )"), cl::init(false), cl::cat(ClangTidyCategory)); +static cl::opt ListOptions("list-options", cl::desc(R"( +Print the available options for the enabled checks. +)"), + cl::init(false), cl::cat(ClangTidyCategory)); + +static cl::opt ListAllOptions("list-all-options", cl::desc(R"( +Print the available options for all supported checks. +)"), + cl::init(false), + cl::cat(ClangTidyCategory)); + namespace clang { namespace tidy { @@ -390,10 +403,11 @@ return FS; } -static StringRef closest(StringRef Value, const StringSet<> &Allowed) { +template +static StringRef closest(StringRef Value, Range &&Allowed) { unsigned MaxEdit = 5U; StringRef Closest; - for (auto Item : Allowed.keys()) { + for (StringRef Item : Allowed) { unsigned Cur = Value.edit_distance_insensitive(Item, true, MaxEdit); if (Cur < MaxEdit) { Closest = Item; @@ -449,7 +463,7 @@ AnyInvalid = true; llvm::raw_ostream &Output = llvm::WithColor::warning(llvm::errs(), Source) << "unknown check '" << Cur << '\''; - llvm::StringRef Closest = closest(Cur, AllChecks); + llvm::StringRef Closest = closest(Cur, AllChecks.keys()); if (!Closest.empty()) Output << "; did you mean '" << Closest << '\''; Output << VerifyConfigWarningEnd; @@ -458,6 +472,11 @@ return AnyInvalid; } +static bool sortOptCollection(const OptionsCollection::MapEntryTy *L, + const OptionsCollection::MapEntryTy *R) { + return L->getKey() < R->getKey(); +} + int clangTidyMain(int argc, const char **argv) { llvm::InitLLVM X(argc, argv); @@ -542,6 +561,95 @@ return 0; } + if (ListOptions || ListAllOptions) { + NamesAndOptions Valid = getAllChecksAndOptions( + ListAllOptions + ? "*" + : OptionsProvider->getOptions(FileName).Checks.value_or(""), + AllowEnablingAnalyzerAlphaCheckers); + std::vector Items; + std::vector GlobalItems; + for (auto &Item : Valid.Options) { + if (Item.getKey().contains('.')) + Items.push_back(&Item); + else + GlobalItems.push_back(&Item); + } + if (GlobalItems.empty() && Items.empty()) { + llvm::errs() << "No options available.\n"; + return 1; + } + llvm::sort(Items, &sortOptCollection); + llvm::sort(GlobalItems, &sortOptCollection); + + if (GlobalItems.empty() && Items.empty()) { + llvm::errs() << "No options available.\n"; + return 1; + } + + // FIXME: explore creating a json schema output format. + auto Output = [](llvm::raw_ostream &O, const OptionType &Type) { + switch (Type.getType()) { + case OptionType::String: + O << "String"; + break; + case OptionType::Boolean: + O << "Bool"; + break; + case OptionType::Unsigned: + O << "Unsigned integer"; + break; + case OptionType::Signed: + O << "Signed integer"; + break; + case OptionType::Custom: + O << "Enumeration"; + if (Type.hasEnum()) { + O << '<'; + auto Values = Type.getEnumValue(); + if (!Values.empty()) { + O << Values.front(); + for (auto Item : Values.drop_front()) { + O << '|' << Item; + } + } + O << '>'; + } + break; + case OptionType::List: + O << "List"; + break; + } + }; + if (!GlobalItems.empty()) { + llvm::outs() << "Global Options:\n"; + for (const auto *Item : GlobalItems) { + llvm::outs() << " - " << Item->getKey() << ": "; + Output(llvm::outs(), Item->getValue()); + llvm::outs() << "\n"; + } + } + + if (!Items.empty()) { + llvm::outs() << "Check Options:\n"; + StringRef Current = "**INVALID_CHECK**"; + for (const auto *Item : Items) { + StringRef Name = Item->getKey(); + if (!Name.consume_front(Current)) { + auto Idx = Name.find('.'); + assert(Idx != StringRef::npos); + Current = Name.take_front(Idx + 1); + Name = Name.substr(Idx + 1); + llvm::outs() << " - " << Current.drop_back() << ":\n"; + } + llvm::outs() << " - " << Name << ": "; + Output(llvm::outs(), Item->getValue()); + llvm::outs() << "\n"; + } + } + return 0; + } + if (DumpConfig) { EffectiveOptions.CheckOptions = getCheckOptions(EffectiveOptions, AllowEnablingAnalyzerAlphaCheckers); @@ -555,7 +663,7 @@ std::vector RawOptions = OptionsProvider->getRawOptions(FileName); NamesAndOptions Valid = - getAllChecksAndOptions(AllowEnablingAnalyzerAlphaCheckers); + getAllChecksAndOptions("*", AllowEnablingAnalyzerAlphaCheckers); bool AnyInvalid = false; for (const std::pair &OptionWithSource : RawOptions) { @@ -565,13 +673,13 @@ verifyChecks(Valid.Names, *Opts.Checks, OptionWithSource.second); for (auto Key : Opts.CheckOptions.keys()) { - if (Valid.Options.contains(Key)) + if (Valid.Options.count(Key) != 0) continue; AnyInvalid = true; auto &Output = llvm::WithColor::warning(llvm::errs(), OptionWithSource.second) << "unknown check option '" << Key << '\''; - llvm::StringRef Closest = closest(Key, Valid.Options); + llvm::StringRef Closest = closest(Key, Valid.Options.keys()); if (!Closest.empty()) Output << "; did you mean '" << Closest << '\''; Output << VerifyConfigWarningEnd; diff --git a/clang-tools-extra/clang-tidy/utils/HeaderGuard.h b/clang-tools-extra/clang-tidy/utils/HeaderGuard.h --- a/clang-tools-extra/clang-tidy/utils/HeaderGuard.h +++ b/clang-tools-extra/clang-tidy/utils/HeaderGuard.h @@ -28,7 +28,7 @@ public: HeaderGuardCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - RawStringHeaderFileExtensions(Options.getLocalOrGlobal( + RawStringHeaderFileExtensions(Options.getLocalOrGlobalList( "HeaderFileExtensions", utils::defaultHeaderFileExtensions())) { utils::parseFileExtensions(RawStringHeaderFileExtensions, HeaderFileExtensions,