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 @@ -8,6 +8,7 @@ #include "StringFindStartswithCheck.h" +#include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -33,8 +34,8 @@ void StringFindStartswithCheck::registerMatchers(MatchFinder *Finder) { auto ZeroLiteral = integerLiteral(equals(0)); - auto StringClassMatcher = cxxRecordDecl(hasAnyName(SmallVector( - StringLikeClasses.begin(), StringLikeClasses.end()))); + auto StringClassMatcher = + cxxRecordDecl(matchers::hasAnyListedName(StringLikeClasses)); auto StringType = hasUnqualifiedDesugaredType( recordType(hasDeclaration(StringClassMatcher))); 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 @@ -94,8 +94,7 @@ HandleClasses(utils::options::parseStringList(Options.get( "HandleClasses", "std::basic_string_view;std::experimental::basic_string_view"))), - IsAHandle(cxxRecordDecl(hasAnyName(std::vector( - HandleClasses.begin(), HandleClasses.end()))) + IsAHandle(cxxRecordDecl(matchers::hasAnyListedName(HandleClasses)) .bind("handle")) {} void DanglingHandleCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { 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 @@ -96,8 +96,7 @@ // Match a call to a string compare functions. const auto FunctionCompareDecl = - functionDecl(hasAnyName(std::vector(FunctionNames.begin(), - FunctionNames.end()))) + functionDecl(matchers::hasAnyListedName(FunctionNames)) .bind("decl"); const auto DirectStringCompareCallExpr = callExpr(hasDeclaration(FunctionCompareDecl)).bind("call"); 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 @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "UnusedReturnValueCheck.h" +#include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -55,8 +56,7 @@ callExpr(callee(functionDecl( // Don't match void overloads of checked functions. unless(returns(voidType())), - isInstantiatedFrom(hasAnyName( - std::vector(FunVec.begin(), FunVec.end())))))) + isInstantiatedFrom(matchers::hasAnyListedName(FunVec))))) .bind("match")))); auto UnusedInCompoundStmt = 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 @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "NonTrivialTypesLibcMemoryCallsCheck.h" +#include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/AST/Decl.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -30,10 +31,6 @@ AST_MATCHER(CXXRecordDecl, isTriviallyCopyable) { return Node.hasTrivialCopyAssignment() && Node.hasTrivialCopyConstructor(); } -AST_MATCHER_P(NamedDecl, hasAnyNameStdString, std::vector, - String) { - return ast_matchers::internal::HasNameMatcher(String).matchesNode(Node); -} } // namespace static const char BuiltinMemSet[] = "::std::memset;" @@ -104,20 +101,20 @@ }; Finder->addMatcher( - callExpr(callee(namedDecl(hasAnyNameStdString( + callExpr(callee(namedDecl(matchers::hasAnyListedName( parseStringListPair(BuiltinMemSet, MemSetNames)))), ArgChecker(unless(isTriviallyDefaultConstructible()), expr(integerLiteral(equals(0))))) .bind("lazyConstruct"), this); Finder->addMatcher( - callExpr(callee(namedDecl(hasAnyNameStdString( + callExpr(callee(namedDecl(matchers::hasAnyListedName( parseStringListPair(BuiltinMemCpy, MemCpyNames)))), ArgChecker(unless(isTriviallyCopyable()), IsStructPointer())) .bind("lazyCopy"), this); Finder->addMatcher( - callExpr(callee(namedDecl(hasAnyNameStdString( + callExpr(callee(namedDecl(matchers::hasAnyListedName( parseStringListPair(BuiltinMemCmp, MemCmpNames)))), ArgChecker(hasMethod(hasAnyName(ComparisonOperators)), IsStructPointer())) diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/NoMallocCheck.cpp @@ -22,14 +22,6 @@ namespace tidy { namespace cppcoreguidelines { -namespace { -Matcher hasAnyListedName(const std::string &FunctionNames) { - const std::vector NameList = - utils::options::parseStringList(FunctionNames); - return hasAnyName(std::vector(NameList.begin(), NameList.end())); -} -} // namespace - void NoMallocCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "Allocations", AllocList); Options.store(Opts, "Reallocations", ReallocList); @@ -38,19 +30,20 @@ void NoMallocCheck::registerMatchers(MatchFinder *Finder) { // Registering malloc, will suggest RAII. - Finder->addMatcher(callExpr(callee(functionDecl(hasAnyListedName(AllocList)))) - .bind("allocation"), - this); + Finder->addMatcher( + callExpr(callee(functionDecl(matchers::hasAnyListedName(AllocList)))) + .bind("allocation"), + this); // Registering realloc calls, suggest std::vector or std::string. Finder->addMatcher( - callExpr(callee(functionDecl(hasAnyListedName(ReallocList)))) + callExpr(callee(functionDecl(matchers::hasAnyListedName(ReallocList)))) .bind("realloc"), this); // Registering free calls, will suggest RAII instead. Finder->addMatcher( - callExpr(callee(functionDecl(hasAnyListedName(DeallocList)))) + callExpr(callee(functionDecl(matchers::hasAnyListedName(DeallocList)))) .bind("free"), this); } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/OwningMemoryCheck.cpp @@ -21,16 +21,6 @@ namespace tidy { namespace cppcoreguidelines { -// FIXME: Copied from 'NoMallocCheck.cpp'. Has to be refactored into 'util' or -// something like that. -namespace { -Matcher hasAnyListedName(const std::string &FunctionNames) { - const std::vector NameList = - utils::options::parseStringList(FunctionNames); - return hasAnyName(std::vector(NameList.begin(), NameList.end())); -} -} // namespace - void OwningMemoryCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "LegacyResourceProducers", LegacyResourceProducers); Options.store(Opts, "LegacyResourceConsumers", LegacyResourceConsumers); @@ -42,9 +32,10 @@ const auto OwnerDecl = typeAliasTemplateDecl(hasName("::gsl::owner")); const auto IsOwnerType = hasType(OwnerDecl); - const auto LegacyCreatorFunctions = hasAnyListedName(LegacyResourceProducers); + const auto LegacyCreatorFunctions = + matchers::hasAnyListedName(LegacyResourceProducers); const auto LegacyConsumerFunctions = - hasAnyListedName(LegacyResourceConsumers); + matchers::hasAnyListedName(LegacyResourceConsumers); // Legacy functions that are use for resource management but cannot be // updated to use `gsl::owner<>`, like standard C memory management. 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 @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "UseEmplaceCheck.h" +#include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" using namespace clang::ast_matchers; @@ -50,15 +51,15 @@ // + match for emplace calls that should be replaced with insertion auto CallPushBack = cxxMemberCallExpr( hasDeclaration(functionDecl(hasName("push_back"))), - on(hasType(cxxRecordDecl(hasAnyName(SmallVector( - ContainersWithPushBack.begin(), ContainersWithPushBack.end())))))); + on(hasType( + cxxRecordDecl(matchers::hasAnyListedName(ContainersWithPushBack))))); // We can't replace push_backs of smart pointer because // if emplacement fails (f.e. bad_alloc in vector) we will have leak of // passed pointer because smart pointer won't be constructed // (and destructed) as in push_back case. - auto IsCtorOfSmartPtr = hasDeclaration(cxxConstructorDecl(ofClass(hasAnyName( - SmallVector(SmartPointers.begin(), SmartPointers.end()))))); + auto IsCtorOfSmartPtr = hasDeclaration( + cxxConstructorDecl(ofClass(matchers::hasAnyListedName(SmartPointers)))); // Bitfields binds only to consts and emplace_back take it by universal ref. auto BitFieldAsArgument = hasAnyArgument( @@ -90,20 +91,19 @@ .bind("ctor"); auto HasConstructExpr = has(ignoringImplicit(SoughtConstructExpr)); - auto MakeTuple = ignoringImplicit( - callExpr( - callee(expr(ignoringImplicit(declRefExpr( - unless(hasExplicitTemplateArgs()), - to(functionDecl(hasAnyName(SmallVector( - TupleMakeFunctions.begin(), TupleMakeFunctions.end()))))))))) - .bind("make")); + auto MakeTuple = + ignoringImplicit(callExpr(callee(expr(ignoringImplicit(declRefExpr( + unless(hasExplicitTemplateArgs()), + to(functionDecl(matchers::hasAnyListedName( + TupleMakeFunctions)))))))) + .bind("make")); // make_something can return type convertible to container's element type. // Allow the conversion only on containers of pairs. - auto MakeTupleCtor = ignoringImplicit(cxxConstructExpr( - has(materializeTemporaryExpr(MakeTuple)), - hasDeclaration(cxxConstructorDecl(ofClass(hasAnyName( - SmallVector(TupleTypes.begin(), TupleTypes.end()))))))); + auto MakeTupleCtor = ignoringImplicit( + cxxConstructExpr(has(materializeTemporaryExpr(MakeTuple)), + hasDeclaration(cxxConstructorDecl( + ofClass(matchers::hasAnyListedName(TupleTypes)))))); auto SoughtParam = materializeTemporaryExpr( anyOf(has(MakeTuple), has(MakeTupleCtor), 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 @@ -7,11 +7,12 @@ //===----------------------------------------------------------------------===// #include "ForbiddenSubclassingCheck.h" +#include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" -#include "../utils/OptionsUtils.h" using namespace clang::ast_matchers; @@ -51,14 +52,10 @@ void ForbiddenSubclassingCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( objcInterfaceDecl( - isDerivedFrom( - objcInterfaceDecl( - hasAnyName( - std::vector( - ForbiddenSuperClassNames.begin(), - ForbiddenSuperClassNames.end()))) - .bind("superclass"))) - .bind("subclass"), + isDerivedFrom(objcInterfaceDecl(matchers::hasAnyListedName( + ForbiddenSuperClassNames)) + .bind("superclass"))) + .bind("subclass"), this); } 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 @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "FasterStringFindCheck.h" +#include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -75,8 +76,7 @@ hasArgument(0, SingleChar), on(expr( hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration( - recordDecl(hasAnyName(SmallVector( - StringLikeClasses.begin(), StringLikeClasses.end()))))))), + recordDecl(matchers::hasAnyListedName(StringLikeClasses)))))), unless(hasSubstitutedType())))), this); } 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 @@ -20,12 +20,6 @@ const char DefaultStringNames[] = "::std::basic_string"; -static ast_matchers::internal::Matcher -hasAnyNameStdString(std::vector Names) { - return ast_matchers::internal::Matcher( - new ast_matchers::internal::HasNameMatcher(std::move(Names))); -} - static std::vector removeNamespaces(const std::vector &Names) { std::vector Result; @@ -71,9 +65,9 @@ } void RedundantStringInitCheck::registerMatchers(MatchFinder *Finder) { - const auto hasStringTypeName = hasAnyNameStdString(StringNames); + const auto hasStringTypeName = matchers::hasAnyListedName(StringNames); const auto hasStringCtorName = - hasAnyNameStdString(removeNamespaces(StringNames)); + matchers::hasAnyListedName(removeNamespaces(StringNames)); // Match string constructor. const auto StringConstructorExpr = expr( 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 @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "SimplifySubscriptExprCheck.h" +#include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" @@ -27,9 +28,8 @@ } void SimplifySubscriptExprCheck::registerMatchers(MatchFinder *Finder) { - const auto TypesMatcher = hasUnqualifiedDesugaredType( - recordType(hasDeclaration(cxxRecordDecl(hasAnyName( - llvm::SmallVector(Types.begin(), Types.end())))))); + const auto TypesMatcher = hasUnqualifiedDesugaredType(recordType( + hasDeclaration(cxxRecordDecl(matchers::hasAnyListedName(Types))))); Finder->addMatcher( arraySubscriptExpr(hasBase(ignoringParenImpCasts( diff --git a/clang-tools-extra/clang-tidy/utils/CMakeLists.txt b/clang-tools-extra/clang-tidy/utils/CMakeLists.txt --- a/clang-tools-extra/clang-tidy/utils/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/utils/CMakeLists.txt @@ -11,6 +11,7 @@ IncludeInserter.cpp IncludeSorter.cpp LexerUtils.cpp + Matchers.cpp NamespaceAliaser.cpp OptionsUtils.cpp RenamerClangTidyCheck.cpp diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.h b/clang-tools-extra/clang-tidy/utils/Matchers.h --- a/clang-tools-extra/clang-tidy/utils/Matchers.h +++ b/clang-tools-extra/clang-tidy/utils/Matchers.h @@ -50,6 +50,13 @@ }); } +ast_matchers::internal::Matcher +hasAnyListedName(std::vector Names); + +// NameList must be a semi-colon; seperated list. +ast_matchers::internal::Matcher +hasAnyListedName(llvm::StringRef NameList); + } // namespace matchers } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.cpp b/clang-tools-extra/clang-tidy/utils/Matchers.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clang-tidy/utils/Matchers.cpp @@ -0,0 +1,27 @@ +//===--- Matchers.cpp - clang-tidy ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Matchers.h" +#include "OptionsUtils.h" + +namespace clang { +namespace tidy { +namespace matchers { +using namespace ast_matchers::internal; + +Matcher hasAnyListedName(std::vector Names) { + return Matcher(new HasNameMatcher(std::move(Names))); +} + +Matcher hasAnyListedName(llvm::StringRef NameList) { + return hasAnyListedName(utils::options::parseStringList(NameList)); +} + +} // namespace matchers +} // namespace tidy +} // namespace clang