Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit e1aebba

Browse files
committed
[ASTMatcher] Add hasTemplateArgument/hasAnyTemplateArgument support in functionDecl.
Reviewers: klimek Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D22957 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@277142 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 003e6f4 commit e1aebba

File tree

4 files changed

+121
-14
lines changed

4 files changed

+121
-14
lines changed

docs/LibASTMatchersReference.html

+78-8
Original file line numberDiff line numberDiff line change
@@ -4240,30 +4240,44 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
42404240

42414241

42424242
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument0')"><a name="hasAnyTemplateArgument0Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
4243-
<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument0"><pre>Matches classTemplateSpecializations that have at least one
4244-
TemplateArgument matching the given InnerMatcher.
4243+
<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument0"><pre>Matches classTemplateSpecializations, templateSpecializationType and
4244+
functionDecl that have at least one TemplateArgument matching the given
4245+
InnerMatcher.
42454246

42464247
Given
42474248
template&lt;typename T&gt; class A {};
42484249
template&lt;&gt; class A&lt;double&gt; {};
42494250
A&lt;int&gt; a;
4251+
4252+
template&lt;typenmae T&gt; f() {};
4253+
void func() { f&lt;int&gt;(); };
4254+
42504255
classTemplateSpecializationDecl(hasAnyTemplateArgument(
42514256
refersToType(asString("int"))))
42524257
matches the specialization A&lt;int&gt;
4258+
4259+
functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
4260+
matches the specialization f&lt;int&gt;
42534261
</pre></td></tr>
42544262

42554263

42564264
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1ClassTemplateSpecializationDecl.html">ClassTemplateSpecializationDecl</a>&gt;</td><td class="name" onclick="toggle('hasTemplateArgument0')"><a name="hasTemplateArgument0Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
4257-
<tr><td colspan="4" class="doc" id="hasTemplateArgument0"><pre>Matches classTemplateSpecializations where the n'th TemplateArgument
4258-
matches the given InnerMatcher.
4265+
<tr><td colspan="4" class="doc" id="hasTemplateArgument0"><pre>Matches classTemplateSpecializations, templateSpecializationType and
4266+
functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
42594267

42604268
Given
42614269
template&lt;typename T, typename U&gt; class A {};
42624270
A&lt;bool, int&gt; b;
42634271
A&lt;int, bool&gt; c;
4272+
4273+
template&lt;typenmae T&gt; f() {};
4274+
void func() { f&lt;int&gt;(); };
42644275
classTemplateSpecializationDecl(hasTemplateArgument(
42654276
1, refersToType(asString("int"))))
42664277
matches the specialization A&lt;bool, int&gt;
4278+
4279+
functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
4280+
matches the specialization f&lt;int&gt;
42674281
</pre></td></tr>
42684282

42694283

@@ -4679,6 +4693,28 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
46794693
</pre></td></tr>
46804694

46814695

4696+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument2')"><a name="hasAnyTemplateArgument2Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
4697+
<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument2"><pre>Matches classTemplateSpecializations, templateSpecializationType and
4698+
functionDecl that have at least one TemplateArgument matching the given
4699+
InnerMatcher.
4700+
4701+
Given
4702+
template&lt;typename T&gt; class A {};
4703+
template&lt;&gt; class A&lt;double&gt; {};
4704+
A&lt;int&gt; a;
4705+
4706+
template&lt;typenmae T&gt; f() {};
4707+
void func() { f&lt;int&gt;(); };
4708+
4709+
classTemplateSpecializationDecl(hasAnyTemplateArgument(
4710+
refersToType(asString("int"))))
4711+
matches the specialization A&lt;int&gt;
4712+
4713+
functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
4714+
matches the specialization f&lt;int&gt;
4715+
</pre></td></tr>
4716+
4717+
46824718
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasBody4')"><a name="hasBody4Anchor">hasBody</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>&gt; InnerMatcher</td></tr>
46834719
<tr><td colspan="4" class="doc" id="hasBody4"><pre>Matches a 'for', 'while', 'do while' statement or a function
46844720
definition that has a given body.
@@ -4704,6 +4740,26 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
47044740
</pre></td></tr>
47054741

47064742

4743+
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('hasTemplateArgument2')"><a name="hasTemplateArgument2Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
4744+
<tr><td colspan="4" class="doc" id="hasTemplateArgument2"><pre>Matches classTemplateSpecializations, templateSpecializationType and
4745+
functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
4746+
4747+
Given
4748+
template&lt;typename T, typename U&gt; class A {};
4749+
A&lt;bool, int&gt; b;
4750+
A&lt;int, bool&gt; c;
4751+
4752+
template&lt;typenmae T&gt; f() {};
4753+
void func() { f&lt;int&gt;(); };
4754+
classTemplateSpecializationDecl(hasTemplateArgument(
4755+
1, refersToType(asString("int"))))
4756+
matches the specialization A&lt;bool, int&gt;
4757+
4758+
functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
4759+
matches the specialization f&lt;int&gt;
4760+
</pre></td></tr>
4761+
4762+
47074763
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1FunctionDecl.html">FunctionDecl</a>&gt;</td><td class="name" onclick="toggle('returns0')"><a name="returns0Anchor">returns</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
47084764
<tr><td colspan="4" class="doc" id="returns0"><pre>Matches the return type of a function declaration.
47094765

@@ -5311,16 +5367,24 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
53115367

53125368

53135369
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasAnyTemplateArgument1')"><a name="hasAnyTemplateArgument1Anchor">hasAnyTemplateArgument</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
5314-
<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument1"><pre>Matches classTemplateSpecializations that have at least one
5315-
TemplateArgument matching the given InnerMatcher.
5370+
<tr><td colspan="4" class="doc" id="hasAnyTemplateArgument1"><pre>Matches classTemplateSpecializations, templateSpecializationType and
5371+
functionDecl that have at least one TemplateArgument matching the given
5372+
InnerMatcher.
53165373

53175374
Given
53185375
template&lt;typename T&gt; class A {};
53195376
template&lt;&gt; class A&lt;double&gt; {};
53205377
A&lt;int&gt; a;
5378+
5379+
template&lt;typenmae T&gt; f() {};
5380+
void func() { f&lt;int&gt;(); };
5381+
53215382
classTemplateSpecializationDecl(hasAnyTemplateArgument(
53225383
refersToType(asString("int"))))
53235384
matches the specialization A&lt;int&gt;
5385+
5386+
functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
5387+
matches the specialization f&lt;int&gt;
53245388
</pre></td></tr>
53255389

53265390

@@ -5347,16 +5411,22 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2>
53475411

53485412

53495413
<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateSpecializationType.html">TemplateSpecializationType</a>&gt;</td><td class="name" onclick="toggle('hasTemplateArgument1')"><a name="hasTemplateArgument1Anchor">hasTemplateArgument</a></td><td>unsigned N, Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt; InnerMatcher</td></tr>
5350-
<tr><td colspan="4" class="doc" id="hasTemplateArgument1"><pre>Matches classTemplateSpecializations where the n'th TemplateArgument
5351-
matches the given InnerMatcher.
5414+
<tr><td colspan="4" class="doc" id="hasTemplateArgument1"><pre>Matches classTemplateSpecializations, templateSpecializationType and
5415+
functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
53525416

53535417
Given
53545418
template&lt;typename T, typename U&gt; class A {};
53555419
A&lt;bool, int&gt; b;
53565420
A&lt;int, bool&gt; c;
5421+
5422+
template&lt;typenmae T&gt; f() {};
5423+
void func() { f&lt;int&gt;(); };
53575424
classTemplateSpecializationDecl(hasTemplateArgument(
53585425
1, refersToType(asString("int"))))
53595426
matches the specialization A&lt;bool, int&gt;
5427+
5428+
functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
5429+
matches the specialization f&lt;int&gt;
53605430
</pre></td></tr>
53615431

53625432

include/clang/ASTMatchers/ASTMatchers.h

+23-6
Original file line numberDiff line numberDiff line change
@@ -556,22 +556,32 @@ AST_MATCHER(Decl, isImplicit) {
556556
return Node.isImplicit();
557557
}
558558

559-
/// \brief Matches classTemplateSpecializations that have at least one
560-
/// TemplateArgument matching the given InnerMatcher.
559+
/// \brief Matches classTemplateSpecializations, templateSpecializationType and
560+
/// functionDecl that have at least one TemplateArgument matching the given
561+
/// InnerMatcher.
561562
///
562563
/// Given
563564
/// \code
564565
/// template<typename T> class A {};
565566
/// template<> class A<double> {};
566567
/// A<int> a;
568+
///
569+
/// template<typenmae T> f() {};
570+
/// void func() { f<int>(); };
571+
/// \endcode
572+
///
567573
/// \endcode
568574
/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
569575
/// refersToType(asString("int"))))
570576
/// matches the specialization \c A<int>
577+
///
578+
/// functionDecl(hasAnyTemplateArgument(refersToType(asString("int"))))
579+
/// matches the specialization \c f<int>
571580
AST_POLYMORPHIC_MATCHER_P(
572581
hasAnyTemplateArgument,
573582
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
574-
TemplateSpecializationType),
583+
TemplateSpecializationType,
584+
FunctionDecl),
575585
internal::Matcher<TemplateArgument>, InnerMatcher) {
576586
ArrayRef<TemplateArgument> List =
577587
internal::getTemplateSpecializationArgs(Node);
@@ -698,22 +708,29 @@ AST_MATCHER_P(QualType, ignoringParens,
698708
return InnerMatcher.matches(Node.IgnoreParens(), Finder, Builder);
699709
}
700710

701-
/// \brief Matches classTemplateSpecializations where the n'th TemplateArgument
702-
/// matches the given InnerMatcher.
711+
/// \brief Matches classTemplateSpecializations, templateSpecializationType and
712+
/// functionDecl where the n'th TemplateArgument matches the given InnerMatcher.
703713
///
704714
/// Given
705715
/// \code
706716
/// template<typename T, typename U> class A {};
707717
/// A<bool, int> b;
708718
/// A<int, bool> c;
719+
///
720+
/// template<typenmae T> f() {};
721+
/// void func() { f<int>(); };
709722
/// \endcode
710723
/// classTemplateSpecializationDecl(hasTemplateArgument(
711724
/// 1, refersToType(asString("int"))))
712725
/// matches the specialization \c A<bool, int>
726+
///
727+
/// functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))
728+
/// matches the specialization \c f<int>
713729
AST_POLYMORPHIC_MATCHER_P2(
714730
hasTemplateArgument,
715731
AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl,
716-
TemplateSpecializationType),
732+
TemplateSpecializationType,
733+
FunctionDecl),
717734
unsigned, N, internal::Matcher<TemplateArgument>, InnerMatcher) {
718735
ArrayRef<TemplateArgument> List =
719736
internal::getTemplateSpecializationArgs(Node);

include/clang/ASTMatchers/ASTMatchersInternal.h

+7
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,13 @@ getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
16381638
return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
16391639
}
16401640

1641+
inline ArrayRef<TemplateArgument>
1642+
getTemplateSpecializationArgs(const FunctionDecl &FD) {
1643+
if (const auto* TemplateArgs = FD.getTemplateSpecializationArgs())
1644+
return TemplateArgs->asArray();
1645+
return ArrayRef<TemplateArgument>();
1646+
}
1647+
16411648
struct NotEqualsBoundNodePredicate {
16421649
bool operator()(const internal::BoundNodesMap &Nodes) const {
16431650
return Nodes.getNode(ID) != Node;

unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,14 @@ TEST(Matcher, MatchesSpecificArgument) {
594594
"A<int, bool> a;",
595595
templateSpecializationType(hasTemplateArgument(
596596
1, refersToType(asString("int"))))));
597+
598+
EXPECT_TRUE(matches(
599+
"template<typename T> void f() {};"
600+
"void func() { f<int>(); }",
601+
functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
602+
EXPECT_TRUE(notMatches(
603+
"template<typename T> void f() {};",
604+
functionDecl(hasTemplateArgument(0, refersToType(asString("int"))))));
597605
}
598606

599607
TEST(TemplateArgument, Matches) {
@@ -603,6 +611,11 @@ TEST(TemplateArgument, Matches) {
603611
EXPECT_TRUE(matches(
604612
"template<typename T> struct C {}; C<int> c;",
605613
templateSpecializationType(hasAnyTemplateArgument(templateArgument()))));
614+
615+
EXPECT_TRUE(matches(
616+
"template<typename T> void f() {};"
617+
"void func() { f<int>(); }",
618+
functionDecl(hasAnyTemplateArgument(templateArgument()))));
606619
}
607620

608621
TEST(RefersToIntegralType, Matches) {

0 commit comments

Comments
 (0)