Index: cfe/trunk/docs/LibASTMatchersReference.html =================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html +++ cfe/trunk/docs/LibASTMatchersReference.html @@ -4240,30 +4240,44 @@ Matcher<ClassTemplateSpecializationDecl>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecializations that have at least one
-TemplateArgument matching the given InnerMatcher.
+
Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl that have at least one TemplateArgument matching the given
+InnerMatcher.
 
 Given
   template<typename T> class A {};
   template<> class A<double> {};
   A<int> a;
+
+  template<typenmae T> f() {};
+  void func() { f<int>(); };
+
 classTemplateSpecializationDecl(hasAnyTemplateArgument(
     refersToType(asString("int"))))
   matches the specialization A<int>
+
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+  matches the specialization f<int>
 
Matcher<ClassTemplateSpecializationDecl>hasTemplateArgumentunsigned N, Matcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecializations where the n'th TemplateArgument
-matches the given InnerMatcher.
+
Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
 
 Given
   template<typename T, typename U> class A {};
   A<bool, int> b;
   A<int, bool> c;
+
+  template<typenmae T> f() {};
+  void func() { f<int>(); };
 classTemplateSpecializationDecl(hasTemplateArgument(
     1, refersToType(asString("int"))))
   matches the specialization A<bool, int>
+
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+  matches the specialization f<int>
 
@@ -4679,6 +4693,28 @@
+Matcher<FunctionDecl>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher +
Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl that have at least one TemplateArgument matching the given
+InnerMatcher.
+
+Given
+  template<typename T> class A {};
+  template<> class A<double> {};
+  A<int> a;
+
+  template<typenmae T> f() {};
+  void func() { f<int>(); };
+
+classTemplateSpecializationDecl(hasAnyTemplateArgument(
+    refersToType(asString("int"))))
+  matches the specialization A<int>
+
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+  matches the specialization f<int>
+
+ + Matcher<FunctionDecl>hasBodyMatcher<Stmt> InnerMatcher
Matches a 'for', 'while', 'do while' statement or a function
 definition that has a given body.
@@ -4704,6 +4740,26 @@
 
+Matcher<FunctionDecl>hasTemplateArgumentunsigned N, Matcher<TemplateArgument> InnerMatcher +
Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
+
+Given
+  template<typename T, typename U> class A {};
+  A<bool, int> b;
+  A<int, bool> c;
+
+  template<typenmae T> f() {};
+  void func() { f<int>(); };
+classTemplateSpecializationDecl(hasTemplateArgument(
+    1, refersToType(asString("int"))))
+  matches the specialization A<bool, int>
+
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+  matches the specialization f<int>
+
+ + Matcher<FunctionDecl>returnsMatcher<QualType> InnerMatcher
Matches the return type of a function declaration.
 
@@ -5311,16 +5367,24 @@
 
 
 Matcher<TemplateSpecializationType>hasAnyTemplateArgumentMatcher<TemplateArgument> InnerMatcher
-
Matches classTemplateSpecializations that have at least one
-TemplateArgument matching the given InnerMatcher.
+
Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl that have at least one TemplateArgument matching the given
+InnerMatcher.
 
 Given
   template<typename T> class A {};
   template<> class A<double> {};
   A<int> a;
+
+  template<typenmae T> f() {};
+  void func() { f<int>(); };
+
 classTemplateSpecializationDecl(hasAnyTemplateArgument(
     refersToType(asString("int"))))
   matches the specialization A<int>
+
+functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
+  matches the specialization f<int>
 
@@ -5347,16 +5411,22 @@ Matcher<TemplateSpecializationType>hasTemplateArgumentunsigned N, Matcher<TemplateArgument> InnerMatcher -
Matches classTemplateSpecializations where the n'th TemplateArgument
-matches the given InnerMatcher.
+
Matches classTemplateSpecializations, templateSpecializationType and
+functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
 
 Given
   template<typename T, typename U> class A {};
   A<bool, int> b;
   A<int, bool> c;
+
+  template<typenmae T> f() {};
+  void func() { f<int>(); };
 classTemplateSpecializationDecl(hasTemplateArgument(
     1, refersToType(asString("int"))))
   matches the specialization A<bool, int>
+
+functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
+  matches the specialization f<int>
 
Index: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h @@ -556,22 +556,32 @@ return Node.isImplicit(); } -/// \brief Matches classTemplateSpecializations that have at least one -/// TemplateArgument matching the given InnerMatcher. +/// \brief Matches classTemplateSpecializations, templateSpecializationType and +/// functionDecl that have at least one TemplateArgument matching the given +/// InnerMatcher. /// /// Given /// \code /// template class A {}; /// template<> class A {}; /// A a; +/// +/// template f() {}; +/// void func() { f(); }; +/// \endcode +/// /// \endcode /// classTemplateSpecializationDecl(hasAnyTemplateArgument( /// refersToType(asString("int")))) /// matches the specialization \c A +/// +/// functionDecl(hasAnyTemplateArgument(refersToType(asString("int")))) +/// matches the specialization \c f AST_POLYMORPHIC_MATCHER_P( hasAnyTemplateArgument, AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - TemplateSpecializationType), + TemplateSpecializationType, + FunctionDecl), internal::Matcher, InnerMatcher) { ArrayRef List = internal::getTemplateSpecializationArgs(Node); @@ -698,22 +708,29 @@ return InnerMatcher.matches(Node.IgnoreParens(), Finder, Builder); } -/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument -/// matches the given InnerMatcher. +/// \brief Matches classTemplateSpecializations, templateSpecializationType and +/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher. /// /// Given /// \code /// template class A {}; /// A b; /// A c; +/// +/// template f() {}; +/// void func() { f(); }; /// \endcode /// classTemplateSpecializationDecl(hasTemplateArgument( /// 1, refersToType(asString("int")))) /// matches the specialization \c A +/// +/// functionDecl(hasTemplateArgument(0, refersToType(asString("int")))) +/// matches the specialization \c f AST_POLYMORPHIC_MATCHER_P2( hasTemplateArgument, AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, - TemplateSpecializationType), + TemplateSpecializationType, + FunctionDecl), unsigned, N, internal::Matcher, InnerMatcher) { ArrayRef List = internal::getTemplateSpecializationArgs(Node); Index: cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h =================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -1638,6 +1638,13 @@ return llvm::makeArrayRef(T.getArgs(), T.getNumArgs()); } +inline ArrayRef +getTemplateSpecializationArgs(const FunctionDecl &FD) { + if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs()) + return TemplateArgs->asArray(); + return ArrayRef(); +} + struct NotEqualsBoundNodePredicate { bool operator()(const internal::BoundNodesMap &Nodes) const { return Nodes.getNode(ID) != Node; Index: cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -594,6 +594,14 @@ "A a;", templateSpecializationType(hasTemplateArgument( 1, refersToType(asString("int")))))); + + EXPECT_TRUE(matches( + "template void f() {};" + "void func() { f(); }", + functionDecl(hasTemplateArgument(0, refersToType(asString("int")))))); + EXPECT_TRUE(notMatches( + "template void f() {};", + functionDecl(hasTemplateArgument(0, refersToType(asString("int")))))); } TEST(TemplateArgument, Matches) { @@ -603,6 +611,11 @@ EXPECT_TRUE(matches( "template struct C {}; C c;", templateSpecializationType(hasAnyTemplateArgument(templateArgument())))); + + EXPECT_TRUE(matches( + "template void f() {};" + "void func() { f(); }", + functionDecl(hasAnyTemplateArgument(templateArgument())))); } TEST(RefersToIntegralType, Matches) {