diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
index 2a01d6cda6bed..9b30057b5257f 100644
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -4108,8 +4108,14 @@
Narrowing Matchers
Given
template<typename T> struct C {};
C<int> c;
+ template<typename T> void f() {}
+ void func() { f<int>(); };
+
classTemplateSpecializationDecl(templateArgumentCountIs(1))
matches C<int>.
+
+functionDecl(templateArgumentCountIs(1))
+ matches f<int>();
@@ -4833,6 +4839,23 @@ Narrowing Matchers
+| Matcher<FunctionDecl> | templateArgumentCountIs | unsigned N |
+Matches if the number of template arguments equals N.
+
+Given
+ template<typename T> struct C {};
+ C<int> c;
+ template<typename T> void f() {}
+ void func() { f<int>(); };
+
+classTemplateSpecializationDecl(templateArgumentCountIs(1))
+ matches C<int>.
+
+functionDecl(templateArgumentCountIs(1))
+ matches f<int>();
+ |
+
+
| Matcher<FunctionProtoType> | hasDynamicExceptionSpec | |
Matches functions that have a dynamic exception specification.
@@ -5783,14 +5806,20 @@ Narrowing Matchers
|
-| Matcher<TemplateSpecializationType> | templateArgumentCountIs | unsigned N |
-Matches if the number of template arguments equals N.
+| Matcher<TemplateSpecializationType> | templateArgumentCountIs | unsigned N |
+Matches if the number of template arguments equals N.
Given
template<typename T> struct C {};
C<int> c;
+ template<typename T> void f() {}
+ void func() { f<int>(); };
+
classTemplateSpecializationDecl(templateArgumentCountIs(1))
matches C<int>.
+
+functionDecl(templateArgumentCountIs(1))
+ matches f<int>();
|
@@ -6219,6 +6248,23 @@ Narrowing Matchers
Usable as: Matcher<FunctionDecl>, Matcher<VarDecl>, Matcher<CXXRecordDecl>
|
+
+| Matcher<VarTemplateSpecializationDecl> | templateArgumentCountIs | unsigned N |
+Matches if the number of template arguments equals N.
+
+Given
+ template<typename T> struct C {};
+ C<int> c;
+ template<typename T> void f() {}
+ void func() { f<int>(); };
+
+classTemplateSpecializationDecl(templateArgumentCountIs(1))
+ matches C<int>.
+
+functionDecl(templateArgumentCountIs(1))
+ matches f<int>();
+ |
+
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 9e68e23c15580..0afde62b6e814 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -395,6 +395,8 @@ AST Matchers
------------
- Ensure ``isDerivedFrom`` matches the correct base in case more than one alias exists.
+- Extend ``templateArgumentCountIs`` to support function and variable template
+ specialization.
clang-format
------------
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 5c12bf0f277a0..738617759eb29 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -1084,12 +1084,19 @@ AST_POLYMORPHIC_MATCHER_P2(
/// \code
/// template struct C {};
/// C c;
+/// template void f() {}
+/// void func() { f(); };
/// \endcode
+///
/// classTemplateSpecializationDecl(templateArgumentCountIs(1))
/// matches C.
+///
+/// functionDecl(templateArgumentCountIs(1))
+/// matches f();
AST_POLYMORPHIC_MATCHER_P(
templateArgumentCountIs,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
+ VarTemplateSpecializationDecl, FunctionDecl,
TemplateSpecializationType),
unsigned, N) {
return internal::getTemplateSpecializationArgs(Node).size() == N;
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 4e6baedae2be5..49abe881eeabb 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2028,6 +2028,13 @@ TEST_P(ASTMatchersTest, TemplateArgumentCountIs) {
EXPECT_TRUE(
notMatches("template struct C {}; C c;",
templateSpecializationType(templateArgumentCountIs(2))));
+
+ const char *FuncTemplateCode =
+ "template T f(); auto v = f();";
+ EXPECT_TRUE(
+ matches(FuncTemplateCode, functionDecl(templateArgumentCountIs(1))));
+ EXPECT_TRUE(
+ notMatches(FuncTemplateCode, functionDecl(templateArgumentCountIs(2))));
}
TEST_P(ASTMatchersTest, IsIntegral) {