Author: Stephen Kelly Date: 2021-03-03T11:41:20Z New Revision: 243cd0afadc7b406ed6c314f7645b1d72748ddd1
URL: https://github.com/llvm/llvm-project/commit/243cd0afadc7b406ed6c314f7645b1d72748ddd1 DIFF: https://github.com/llvm/llvm-project/commit/243cd0afadc7b406ed6c314f7645b1d72748ddd1.diff LOG: [ASTMatchers] Make Param functors variadic Differential Revision: https://reviews.llvm.org/D97156 Added: Modified: clang/docs/tools/dump_ast_matchers.py clang/include/clang/ASTMatchers/ASTMatchers.h clang/include/clang/ASTMatchers/ASTMatchersInternal.h clang/include/clang/ASTMatchers/ASTMatchersMacros.h Removed: ################################################################################ diff --git a/clang/docs/tools/dump_ast_matchers.py b/clang/docs/tools/dump_ast_matchers.py index 18afbdd36c6e..2a26d10f7a04 100755 --- a/clang/docs/tools/dump_ast_matchers.py +++ b/clang/docs/tools/dump_ast_matchers.py @@ -351,13 +351,17 @@ def act_on_decl(declaration, comment, allowed_types): m = re.match( r"""^.*internal::VariadicFunction\s*<\s* - internal::PolymorphicMatcherWithParam1<[\S\s]+ - AST_POLYMORPHIC_SUPPORTED_TYPES\(([^)]*)\)>,\s*([^,]+), - \s*[^>]+>\s*([a-zA-Z]*);$""", + internal::PolymorphicMatcher<[\S\s]+ + AST_POLYMORPHIC_SUPPORTED_TYPES\(([^)]*)\),\s*(.*);$""", declaration, flags=re.X) if m: - results, arg, name = m.groups()[:3] + results, trailing = m.groups() + trailing, name = trailing.rsplit(">", 1) + name = name.strip() + trailing, _ = trailing.rsplit(",", 1) + _, arg = trailing.rsplit(",", 1) + arg = arg.strip() result_types = [r.strip() for r in results.split(',')] for result_type in result_types: diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index b82929019f6c..885bc74ad3ea 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -835,26 +835,16 @@ traverse(TraversalKind TK, const internal::ArgumentAdaptingMatcherFuncAdaptor< ToTypes>>(TK, InnerMatcher); } -template <template <typename T, typename P1> class MatcherT, typename P1, +template <template <typename T, typename... P> class MatcherT, typename... P, typename ReturnTypesF> internal::TraversalWrapper< - internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>> -traverse(TraversalKind TK, const internal::PolymorphicMatcherWithParam1< - MatcherT, P1, ReturnTypesF> &InnerMatcher) { - return internal::TraversalWrapper< - internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>>( - TK, InnerMatcher); -} - -template <template <typename T, typename P1, typename P2> class MatcherT, - typename P1, typename P2, typename ReturnTypesF> -internal::TraversalWrapper< - internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>> -traverse(TraversalKind TK, const internal::PolymorphicMatcherWithParam2< - MatcherT, P1, P2, ReturnTypesF> &InnerMatcher) { + internal::PolymorphicMatcher<MatcherT, ReturnTypesF, P...>> +traverse(TraversalKind TK, + const internal::PolymorphicMatcher<MatcherT, ReturnTypesF, P...> + &InnerMatcher) { return internal::TraversalWrapper< - internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>>( - TK, InnerMatcher); + internal::PolymorphicMatcher<MatcherT, ReturnTypesF, P...>>(TK, + InnerMatcher); } template <typename... T> @@ -2996,14 +2986,15 @@ AST_MATCHER_REGEX(NamedDecl, matchesName, RegExp) { /// matches the declaration of \c A. /// /// Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl> -inline internal::PolymorphicMatcherWithParam1< - internal::HasOverloadedOperatorNameMatcher, std::vector<std::string>, - AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)> +inline internal::PolymorphicMatcher< + internal::HasOverloadedOperatorNameMatcher, + AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl), + std::vector<std::string>> hasOverloadedOperatorName(StringRef Name) { - return internal::PolymorphicMatcherWithParam1< - internal::HasOverloadedOperatorNameMatcher, std::vector<std::string>, - AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>( - {std::string(Name)}); + return internal::PolymorphicMatcher< + internal::HasOverloadedOperatorNameMatcher, + AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl), + std::vector<std::string>>({std::string(Name)}); } /// Matches overloaded operator names. @@ -3015,9 +3006,10 @@ hasOverloadedOperatorName(StringRef Name) { /// Is equivalent to /// anyOf(hasOverloadedOperatorName("+"), hasOverloadedOperatorName("-")) extern const internal::VariadicFunction< - internal::PolymorphicMatcherWithParam1< - internal::HasOverloadedOperatorNameMatcher, std::vector<std::string>, - AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>, + internal::PolymorphicMatcher<internal::HasOverloadedOperatorNameMatcher, + AST_POLYMORPHIC_SUPPORTED_TYPES( + CXXOperatorCallExpr, FunctionDecl), + std::vector<std::string>>, StringRef, internal::hasAnyOverloadedOperatorNameFunc> hasAnyOverloadedOperatorName; @@ -3506,13 +3498,14 @@ extern const internal::VariadicOperatorMatcherFunc<1, 1> unless; /// Matcher<TagType>, Matcher<TemplateSpecializationType>, /// Matcher<TemplateTypeParmType>, Matcher<TypedefType>, /// Matcher<UnresolvedUsingType> -inline internal::PolymorphicMatcherWithParam1< - internal::HasDeclarationMatcher, internal::Matcher<Decl>, - void(internal::HasDeclarationSupportedTypes)> +inline internal::PolymorphicMatcher< + internal::HasDeclarationMatcher, + void(internal::HasDeclarationSupportedTypes), internal::Matcher<Decl>> hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { - return internal::PolymorphicMatcherWithParam1< - internal::HasDeclarationMatcher, internal::Matcher<Decl>, - void(internal::HasDeclarationSupportedTypes)>(InnerMatcher); + return internal::PolymorphicMatcher< + internal::HasDeclarationMatcher, + void(internal::HasDeclarationSupportedTypes), internal::Matcher<Decl>>( + InnerMatcher); } /// Matches a \c NamedDecl whose underlying declaration matches the given @@ -5299,11 +5292,12 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { /// Usable as: Matcher<CharacterLiteral>, Matcher<CXXBoolLiteralExpr>, /// Matcher<FloatingLiteral>, Matcher<IntegerLiteral> template <typename ValueT> -internal::PolymorphicMatcherWithParam1<internal::ValueEqualsMatcher, ValueT> +internal::PolymorphicMatcher<internal::ValueEqualsMatcher, + void(internal::AllNodeBaseTypes), ValueT> equals(const ValueT &Value) { - return internal::PolymorphicMatcherWithParam1< - internal::ValueEqualsMatcher, - ValueT>(Value); + return internal::PolymorphicMatcher<internal::ValueEqualsMatcher, + void(internal::AllNodeBaseTypes), ValueT>( + Value); } AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals, @@ -5358,11 +5352,11 @@ AST_POLYMORPHIC_MATCHER_P( /// Is equivalent to /// anyOf(hasOperatorName("+"), hasOperatorName("-")) extern const internal::VariadicFunction< - internal::PolymorphicMatcherWithParam1< - internal::HasAnyOperatorNameMatcher, std::vector<std::string>, - AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, CXXOperatorCallExpr, - CXXRewrittenBinaryOperator, - UnaryOperator)>, + internal::PolymorphicMatcher<internal::HasAnyOperatorNameMatcher, + AST_POLYMORPHIC_SUPPORTED_TYPES( + BinaryOperator, CXXOperatorCallExpr, + CXXRewrittenBinaryOperator, UnaryOperator), + std::vector<std::string>>, StringRef, internal::hasAnyOperatorNameFunc> hasAnyOperatorName; diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index 5e3af4a2a34b..19b8941746dd 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -836,7 +836,7 @@ class has_getDecl { /// Matches overloaded operators with a specific name. /// /// The type argument ArgT is not used by this matcher but is used by -/// PolymorphicMatcherWithParam1 and should be StringRef. +/// PolymorphicMatcher and should be StringRef. template <typename T, typename ArgT> class HasOverloadedOperatorNameMatcher : public SingleNodeMatcherInterface<T> { static_assert(std::is_same<T, CXXOperatorCallExpr>::value || @@ -919,7 +919,7 @@ Matcher<ObjCMessageExpr> hasAnySelectorFunc( /// Matches declarations for QualType and CallExpr. /// -/// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but +/// Type argument DeclMatcherT is required by PolymorphicMatcher but /// not actually used. template <typename T, typename DeclMatcherT> class HasDeclarationMatcher : public MatcherInterface<T> { @@ -1157,6 +1157,18 @@ template <class T> struct ExtractFunctionArgMeta<void(T)> { using type = T; }; +template <class T, class Tuple, std::size_t... I> +constexpr T *new_from_tuple_impl(Tuple &&t, std::index_sequence<I...>) { + return new T(std::get<I>(std::forward<Tuple>(t))...); +} + +template <class T, class Tuple> constexpr T *new_from_tuple(Tuple &&t) { + return new_from_tuple_impl<T>( + std::forward<Tuple>(t), + std::make_index_sequence< + std::tuple_size<std::remove_reference_t<Tuple>>::value>{}); +} + /// Default type lists for ArgumentAdaptingMatcher matchers. using AdaptativeDefaultFromTypes = AllNodeBaseTypes; using AdaptativeDefaultToTypes = @@ -1426,7 +1438,7 @@ class ArgumentAdaptingMatcherFuncAdaptor { /// \c HasMatcher<To, T>(InnerMatcher). /// /// If a matcher does not need knowledge about the inner type, prefer to use -/// PolymorphicMatcherWithParam1. +/// PolymorphicMatcher. template <template <typename ToArg, typename FromArg> class ArgumentAdapterT, typename FromTypes = AdaptativeDefaultFromTypes, typename ToTypes = AdaptativeDefaultToTypes> @@ -1491,60 +1503,23 @@ template <typename MatcherType> class TraversalWrapper { MatcherType InnerMatcher; }; -/// A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be +/// A PolymorphicMatcher<MatcherT, P1, ..., PN> object can be /// created from N parameters p1, ..., pN (of type P1, ..., PN) and /// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN) /// can be constructed. /// /// For example: -/// - PolymorphicMatcherWithParam0<IsDefinitionMatcher>() +/// - PolymorphicMatcher<IsDefinitionMatcher>() /// creates an object that can be used as a Matcher<T> for any type T /// where an IsDefinitionMatcher<T>() can be constructed. -/// - PolymorphicMatcherWithParam1<ValueEqualsMatcher, int>(42) +/// - PolymorphicMatcher<ValueEqualsMatcher, int>(42) /// creates an object that can be used as a Matcher<T> for any type T /// where a ValueEqualsMatcher<T, int>(42) can be constructed. -template <template <typename T> class MatcherT, - typename ReturnTypesF = void(AllNodeBaseTypes)> -class PolymorphicMatcherWithParam0 { -public: - using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type; - - template <typename T> - operator Matcher<T>() const { - static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, - "right polymorphic conversion"); - return Matcher<T>(new MatcherT<T>()); - } -}; - -template <template <typename T, typename P1> class MatcherT, - typename P1, - typename ReturnTypesF = void(AllNodeBaseTypes)> -class PolymorphicMatcherWithParam1 { -public: - explicit PolymorphicMatcherWithParam1(const P1 &Param1) - : Param1(Param1) {} - - using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type; - - template <typename T> - operator Matcher<T>() const { - static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, - "right polymorphic conversion"); - return Matcher<T>(new MatcherT<T, P1>(Param1)); - } - -private: - const P1 Param1; -}; - -template <template <typename T, typename P1, typename P2> class MatcherT, - typename P1, typename P2, - typename ReturnTypesF = void(AllNodeBaseTypes)> -class PolymorphicMatcherWithParam2 { +template <template <typename T, typename... Params> class MatcherT, + typename ReturnTypesF, typename... ParamTypes> +class PolymorphicMatcher { public: - PolymorphicMatcherWithParam2(const P1 &Param1, const P2 &Param2) - : Param1(Param1), Param2(Param2) {} + PolymorphicMatcher(const ParamTypes &... Params) : Params(Params...) {} using ReturnTypes = typename ExtractFunctionArgMeta<ReturnTypesF>::type; @@ -1552,12 +1527,11 @@ class PolymorphicMatcherWithParam2 { operator Matcher<T>() const { static_assert(TypeListContainsSuperOf<ReturnTypes, T>::value, "right polymorphic conversion"); - return Matcher<T>(new MatcherT<T, P1, P2>(Param1, Param2)); + return Matcher<T>(new_from_tuple<MatcherT<T, ParamTypes...>>(Params)); } private: - const P1 Param1; - const P2 Param2; + const std::tuple<ParamTypes...> Params; }; /// Matches nodes of type T that have child nodes of type ChildT for @@ -2174,7 +2148,7 @@ inline Optional<StringRef> getOpName(const CXXOperatorCallExpr &Node) { /// Matches overloaded operators with a specific name. /// /// The type argument ArgT is not used by this matcher but is used by -/// PolymorphicMatcherWithParam1 and should be std::vector<std::string>>. +/// PolymorphicMatcher and should be std::vector<std::string>>. template <typename T, typename ArgT = std::vector<std::string>> class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> { static_assert(std::is_same<T, BinaryOperator>::value || @@ -2223,16 +2197,19 @@ class HasAnyOperatorNameMatcher : public SingleNodeMatcherInterface<T> { const std::vector<std::string> Names; }; -using HasOpNameMatcher = PolymorphicMatcherWithParam1< - HasAnyOperatorNameMatcher, std::vector<std::string>, - void(TypeList<BinaryOperator, CXXOperatorCallExpr, - CXXRewrittenBinaryOperator, UnaryOperator>)>; +using HasOpNameMatcher = + PolymorphicMatcher<HasAnyOperatorNameMatcher, + void( + TypeList<BinaryOperator, CXXOperatorCallExpr, + CXXRewrittenBinaryOperator, UnaryOperator>), + std::vector<std::string>>; HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef<const StringRef *> NameRefs); -using HasOverloadOpNameMatcher = PolymorphicMatcherWithParam1< - HasOverloadedOperatorNameMatcher, std::vector<std::string>, - void(TypeList<CXXOperatorCallExpr, FunctionDecl>)>; +using HasOverloadOpNameMatcher = + PolymorphicMatcher<HasOverloadedOperatorNameMatcher, + void(TypeList<CXXOperatorCallExpr, FunctionDecl>), + std::vector<std::string>>; HasOverloadOpNameMatcher hasAnyOverloadedOperatorNameFunc(ArrayRef<const StringRef *> NameRefs); diff --git a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h index 7e01ab0c6ee9..b7fe907f9414 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -239,10 +239,10 @@ *Builder) const override; \ }; \ } \ - inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \ + inline ::clang::ast_matchers::internal::PolymorphicMatcher< \ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF> \ DefineMatcher() { \ - return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam0< \ + return ::clang::ast_matchers::internal::PolymorphicMatcher< \ internal::matcher_##DefineMatcher##Matcher, ReturnTypesF>(); \ } \ template <typename NodeType> \ @@ -284,18 +284,17 @@ ParamType const Param; \ }; \ } \ - inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ - ReturnTypesF> \ + inline ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + ParamType> \ DefineMatcher(ParamType const &Param) { \ - return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ - ReturnTypesF>(Param); \ + return ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + ParamType>(Param); \ } \ - typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType, \ - ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ - ParamType const &Param); \ + typedef ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + ParamType> (&DefineMatcher##_Type##OverloadId)(ParamType const &Param); \ template <typename NodeType, typename ParamT> \ bool internal:: \ matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \ @@ -338,17 +337,17 @@ ParamType2 const Param2; \ }; \ } \ - inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ - ParamType2, ReturnTypesF> \ + inline ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + ParamType1, ParamType2> \ DefineMatcher(ParamType1 const &Param1, ParamType2 const &Param2) { \ - return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ - ParamType2, ReturnTypesF>(Param1, Param2); \ + return ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + ParamType1, ParamType2>(Param1, Param2); \ } \ - typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam2< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, ParamType1, \ - ParamType2, ReturnTypesF>(&DefineMatcher##_Type##OverloadId)( \ + typedef ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + ParamType1, ParamType2> (&DefineMatcher##_Type##OverloadId)( \ ParamType1 const &Param1, ParamType2 const &Param2); \ template <typename NodeType, typename ParamT1, typename ParamT2> \ bool internal::matcher_##DefineMatcher##OverloadId##Matcher< \ @@ -525,31 +524,31 @@ std::shared_ptr<llvm::Regex> const Param; \ }; \ } \ - inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, \ - std::shared_ptr<llvm::Regex>, ReturnTypesF> \ + inline ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + std::shared_ptr<llvm::Regex>> \ DefineMatcher(llvm::StringRef Param, llvm::Regex::RegexFlags RegexFlags) { \ - return ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, \ - std::shared_ptr<llvm::Regex>, ReturnTypesF>( \ + return ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + std::shared_ptr<llvm::Regex>>( \ ::clang::ast_matchers::internal::createAndVerifyRegex( \ Param, RegexFlags, #DefineMatcher)); \ } \ - inline ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, \ - std::shared_ptr<llvm::Regex>, ReturnTypesF> \ + inline ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + std::shared_ptr<llvm::Regex>> \ DefineMatcher(llvm::StringRef Param) { \ return DefineMatcher(Param, llvm::Regex::NoFlags); \ } \ - typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, \ - std::shared_ptr<llvm::Regex>, ReturnTypesF> ( \ + typedef ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + std::shared_ptr<llvm::Regex>> ( \ &DefineMatcher##_Type##OverloadId##Flags)( \ llvm::StringRef Param, llvm::Regex::RegexFlags RegexFlags); \ - typedef ::clang::ast_matchers::internal::PolymorphicMatcherWithParam1< \ - internal::matcher_##DefineMatcher##OverloadId##Matcher, \ - std::shared_ptr<llvm::Regex>, ReturnTypesF> ( \ - &DefineMatcher##_Type##OverloadId)(llvm::StringRef Param); \ + typedef ::clang::ast_matchers::internal::PolymorphicMatcher< \ + internal::matcher_##DefineMatcher##OverloadId##Matcher, ReturnTypesF, \ + std::shared_ptr<llvm::Regex>> (&DefineMatcher##_Type##OverloadId)( \ + llvm::StringRef Param); \ template <typename NodeType, typename ParamT> \ bool internal:: \ matcher_##DefineMatcher##OverloadId##Matcher<NodeType, ParamT>::matches( \ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits