diff --git a/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.h b/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.h --- a/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/ReservedIdentifierCheck.h @@ -30,7 +30,8 @@ /// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/reserved-identifier.html class ReservedIdentifierCheck final : public RenamerClangTidyCheck { const bool Invert; - const std::vector AllowedIdentifiers; + const std::vector AllowedIdentifiersRaw; + const llvm::SmallVector AllowedIdentifiers; public: ReservedIdentifierCheck(StringRef Name, ClangTidyContext *Context); @@ -46,6 +47,7 @@ const SourceManager &SM) const override; DiagInfo getDiagInfo(const NamingCheckId &ID, const NamingCheckFailure &Failure) const override; + llvm::SmallVector parseAllowedIdentifiers() const; }; } // namespace clang::tidy::bugprone 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 @@ -39,18 +39,33 @@ return 0; } +llvm::SmallVector +ReservedIdentifierCheck::parseAllowedIdentifiers() const { + llvm::SmallVector AllowedIdentifiers; + AllowedIdentifiers.reserve(AllowedIdentifiersRaw.size()); + + for (const auto &Identifier : AllowedIdentifiersRaw) { + AllowedIdentifiers.emplace_back(Identifier.str()); + if (!AllowedIdentifiers.back().isValid()) + configurationDiag("Invalid allowed identifier regex '%0'") << Identifier; + } + + return AllowedIdentifiers; +} + ReservedIdentifierCheck::ReservedIdentifierCheck(StringRef Name, ClangTidyContext *Context) : RenamerClangTidyCheck(Name, Context), Invert(Options.get("Invert", false)), - AllowedIdentifiers(utils::options::parseStringList( - Options.get("AllowedIdentifiers", ""))) {} + AllowedIdentifiersRaw(utils::options::parseStringList( + Options.get("AllowedIdentifiers", ""))), + AllowedIdentifiers(parseAllowedIdentifiers()) {} void ReservedIdentifierCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { RenamerClangTidyCheck::storeOptions(Opts); Options.store(Opts, "Invert", Invert); Options.store(Opts, "AllowedIdentifiers", - utils::options::serializeStringList(AllowedIdentifiers)); + utils::options::serializeStringList(AllowedIdentifiersRaw)); } static std::string collapseConsecutive(StringRef Str, char C) { @@ -108,11 +123,14 @@ static std::optional getFailureInfoImpl(StringRef Name, bool IsInGlobalNamespace, const LangOptions &LangOpts, bool Invert, - ArrayRef AllowedIdentifiers) { + ArrayRef AllowedIdentifiers) { assert(!Name.empty()); - if (llvm::is_contained(AllowedIdentifiers, Name)) - return std::nullopt; + if (llvm::any_of(AllowedIdentifiers, [&](const llvm::Regex &Regex) { + return Regex.match(Name); + })) { + return std::nullopt; + } // TODO: Check for names identical to language keywords, and other names // specifically reserved by language standards, e.g. C++ 'zombie names' and C // future library directions diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -243,6 +243,10 @@ ` check by adding support for other floating point representations in float constant like ``0.5L``. +- Improved option `AllowedIdentifiers` from :doc:`bugprone-reserved-identifier + ` to support regular + expressions. + - Deprecated check-local options `HeaderFileExtensions` and `ImplementationFileExtensions` in :doc:`bugprone-suspicious-include ` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/reserved-identifier.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/reserved-identifier.rst --- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/reserved-identifier.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/reserved-identifier.rst @@ -53,5 +53,5 @@ .. option:: AllowedIdentifiers - Semicolon-separated list of names that the check ignores. Default is an + Semicolon-separated list of regular expressions that the check ignores. Default is an empty list. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/reserved-identifier-invert.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/reserved-identifier-invert.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/reserved-identifier-invert.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/reserved-identifier-invert.cpp @@ -1,7 +1,7 @@ // RUN: %check_clang_tidy %s bugprone-reserved-identifier %t -- \ // RUN: -config='{CheckOptions: [ \ // RUN: {key: bugprone-reserved-identifier.Invert, value: true}, \ -// RUN: {key: bugprone-reserved-identifier.AllowedIdentifiers, value: std;reference_wrapper;ref;cref;type;get}, \ +// RUN: {key: bugprone-reserved-identifier.AllowedIdentifiers, value: "std;reference_wrapper;^c?ref;type;get"}, \ // RUN: ]}' -- \ // RUN: -I%S/Inputs/reserved-identifier \ // RUN: -isystem %S/Inputs/reserved-identifier/system