[AstMatcher]templateArgumentCountIs support FunctionDecl (#130416)

`hasTemplateArgument` and `templateArgumentCountIs` are always used together. It is more convenient to make then support `FunctionDecl`.
This commit is contained in:
Congcong Cai 2025-03-12 06:08:10 +08:00 committed by GitHub
parent 009dfb435f
commit 4d6ca11622
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 64 additions and 2 deletions

View File

@ -4108,8 +4108,14 @@ Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1Char
Given
template&lt;typename T&gt; struct C {};
C&lt;int&gt; c;
template&lt;typename T&gt; void f() {}
void func() { f&lt;int&gt;(); };
classTemplateSpecializationDecl(templateArgumentCountIs(1))
matches C&lt;int&gt;.
functionDecl(templateArgumentCountIs(1))
matches f&lt;int&gt;();
</pre></td></tr>
@ -4833,6 +4839,23 @@ functionProtoType(parameterCountIs(3))
</pre></td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('templateArgumentCountIs2')"><a name="templateArgumentCountIs2Anchor">templateArgumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="templateArgumentCountIs2"><pre>Matches if the number of template arguments equals N.
Given
template&lt;typename T&gt; struct C {};
C&lt;int&gt; c;
template&lt;typename T&gt; void f() {}
void func() { f&lt;int&gt;(); };
classTemplateSpecializationDecl(templateArgumentCountIs(1))
matches C&lt;int&gt;.
functionDecl(templateArgumentCountIs(1))
matches f&lt;int&gt;();
</pre></td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionProtoType.html">FunctionProtoType</a>&gt;</td><td class="name" onclick="toggle('hasDynamicExceptionSpec1')"><a name="hasDynamicExceptionSpec1Anchor">hasDynamicExceptionSpec</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDynamicExceptionSpec1"><pre>Matches functions that have a dynamic exception specification.
@ -5783,14 +5806,20 @@ classTemplateSpecializationDecl(
</pre></td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('templateArgumentCountIs1')"><a name="templateArgumentCountIs1Anchor">templateArgumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="templateArgumentCountIs1"><pre>Matches if the number of template arguments equals N.
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('templateArgumentCountIs3')"><a name="templateArgumentCountIs3Anchor">templateArgumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="templateArgumentCountIs3"><pre>Matches if the number of template arguments equals N.
Given
template&lt;typename T&gt; struct C {};
C&lt;int&gt; c;
template&lt;typename T&gt; void f() {}
void func() { f&lt;int&gt;(); };
classTemplateSpecializationDecl(templateArgumentCountIs(1))
matches C&lt;int&gt;.
functionDecl(templateArgumentCountIs(1))
matches f&lt;int&gt;();
</pre></td></tr>
@ -6219,6 +6248,23 @@ cxxRecordDecl(hasName("::X"), isTemplateInstantiation())
Usable as: Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarDecl.html">VarDecl</a>&gt;, Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;
</pre></td></tr>
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1VarTemplateSpecializationDecl.html">VarTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('templateArgumentCountIs1')"><a name="templateArgumentCountIs1Anchor">templateArgumentCountIs</a></td><td>unsigned N</td></tr>
<tr><td colspan="4" class="doc" id="templateArgumentCountIs1"><pre>Matches if the number of template arguments equals N.
Given
template&lt;typename T&gt; struct C {};
C&lt;int&gt; c;
template&lt;typename T&gt; void f() {}
void func() { f&lt;int&gt;(); };
classTemplateSpecializationDecl(templateArgumentCountIs(1))
matches C&lt;int&gt;.
functionDecl(templateArgumentCountIs(1))
matches f&lt;int&gt;();
</pre></td></tr>
<!--END_NARROWING_MATCHERS -->
</table>

View File

@ -397,6 +397,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
------------

View File

@ -1084,12 +1084,19 @@ AST_POLYMORPHIC_MATCHER_P2(
/// \code
/// template<typename T> struct C {};
/// C<int> c;
/// template<typename T> void f() {}
/// void func() { f<int>(); };
/// \endcode
///
/// classTemplateSpecializationDecl(templateArgumentCountIs(1))
/// matches C<int>.
///
/// functionDecl(templateArgumentCountIs(1))
/// matches f<int>();
AST_POLYMORPHIC_MATCHER_P(
templateArgumentCountIs,
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
VarTemplateSpecializationDecl, FunctionDecl,
TemplateSpecializationType),
unsigned, N) {
return internal::getTemplateSpecializationArgs(Node).size() == N;

View File

@ -2028,6 +2028,13 @@ TEST_P(ASTMatchersTest, TemplateArgumentCountIs) {
EXPECT_TRUE(
notMatches("template<typename T> struct C {}; C<int> c;",
templateSpecializationType(templateArgumentCountIs(2))));
const char *FuncTemplateCode =
"template<typename T> T f(); auto v = f<int>();";
EXPECT_TRUE(
matches(FuncTemplateCode, functionDecl(templateArgumentCountIs(1))));
EXPECT_TRUE(
notMatches(FuncTemplateCode, functionDecl(templateArgumentCountIs(2))));
}
TEST_P(ASTMatchersTest, IsIntegral) {