Skip to content

Commit b1c7f84

Browse files
[clang] Allow DynTypedNode to store a TemplateArgumentLoc
The patch also adds a templateArgumentLoc() AST matcher. Differential Revision: https://reviews.llvm.org/D85621
1 parent 1970eef commit b1c7f84

File tree

9 files changed

+106
-20
lines changed

9 files changed

+106
-20
lines changed

clang/docs/LibASTMatchersReference.html

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
679679
#pragma omp parallel default(firstprivate)
680680
#pragma omp parallel
681681

682-
``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and ``default(firstprivate)``.
682+
``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and
683+
``default(firstprivate)``
683684
</pre></td></tr>
684685

685686

@@ -1625,6 +1626,17 @@ <h2 id="decl-matchers">Node Matchers</h2>
16251626
</pre></td></tr>
16261627

16271628

1629+
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>&gt;</td><td class="name" onclick="toggle('templateArgumentLoc0')"><a name="templateArgumentLoc0Anchor">templateArgumentLoc</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>&gt;...</td></tr>
1630+
<tr><td colspan="4" class="doc" id="templateArgumentLoc0"><pre>Matches template arguments (with location info).
1631+
1632+
Given
1633+
template &lt;typename T&gt; struct C {};
1634+
C&lt;int&gt; c;
1635+
templateArgumentLoc()
1636+
matches 'int' in C&lt;int&gt;.
1637+
</pre></td></tr>
1638+
1639+
16281640
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('templateArgument0')"><a name="templateArgument0Anchor">templateArgument</a></td><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;...</td></tr>
16291641
<tr><td colspan="4" class="doc" id="templateArgument0"><pre>Matches template arguments.
16301642

@@ -3776,8 +3788,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
37763788
</pre></td></tr>
37773789

37783790

3779-
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>&gt;</td><td class="name" onclick="toggle('isNoneKind0')"><a name="isNoneKind0Anchor">isNoneKind</a></td><td></td></tr>
3780-
<tr><td colspan="4" class="doc" id="isNoneKind0"><pre>Matches if the OpenMP ``default`` clause has ``none`` kind specified.
3791+
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>&gt;</td><td class="name" onclick="toggle('isFirstPrivateKind0')"><a name="isFirstPrivateKind0Anchor">isFirstPrivateKind</a></td><td></td></tr>
3792+
<tr><td colspan="4" class="doc" id="isFirstPrivateKind0"><pre>Matches if the OpenMP ``default`` clause has ``firstprivate`` kind
3793+
specified.
37813794

37823795
Given
37833796

@@ -3786,12 +3799,13 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
37863799
#pragma omp parallel default(shared)
37873800
#pragma omp parallel default(firstprivate)
37883801

3789-
``ompDefaultClause(isNoneKind())`` matches only ``default(none)``.
3802+
``ompDefaultClause(isFirstPrivateKind())`` matches only
3803+
``default(firstprivate)``.
37903804
</pre></td></tr>
37913805

37923806

3793-
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>&gt;</td><td class="name" onclick="toggle('isSharedKind0')"><a name="isSharedKind0Anchor">isSharedKind</a></td><td></td></tr>
3794-
<tr><td colspan="4" class="doc" id="isSharedKind0"><pre>Matches if the OpenMP ``default`` clause has ``shared`` kind specified.
3807+
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>&gt;</td><td class="name" onclick="toggle('isNoneKind0')"><a name="isNoneKind0Anchor">isNoneKind</a></td><td></td></tr>
3808+
<tr><td colspan="4" class="doc" id="isNoneKind0"><pre>Matches if the OpenMP ``default`` clause has ``none`` kind specified.
37953809

37963810
Given
37973811

@@ -3800,12 +3814,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
38003814
#pragma omp parallel default(shared)
38013815
#pragma omp parallel default(firstprivate)
38023816

3803-
``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``.
3817+
``ompDefaultClause(isNoneKind())`` matches only ``default(none)``.
38043818
</pre></td></tr>
38053819

38063820

3807-
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>&gt;</td><td class="name" onclick="toggle('isFirstPrivateKind0')"><a name="isFirstPrivateKind0Anchor">isSharedKind</a></td><td></td></tr>
3808-
<tr><td colspan="4" class="doc" id="isFirstPrivateKind0"><pre>Matches if the OpenMP ``default`` clause has ``firstprivate`` kind specified.
3821+
<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>&gt;</td><td class="name" onclick="toggle('isSharedKind0')"><a name="isSharedKind0Anchor">isSharedKind</a></td><td></td></tr>
3822+
<tr><td colspan="4" class="doc" id="isSharedKind0"><pre>Matches if the OpenMP ``default`` clause has ``shared`` kind specified.
38093823

38103824
Given
38113825

@@ -3814,7 +3828,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
38143828
#pragma omp parallel default(shared)
38153829
#pragma omp parallel default(firstprivate)
38163830

3817-
``ompDefaultClause(isFirstPrivateKind())`` matches only ``default(firstprivate)``.
3831+
``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``.
38183832
</pre></td></tr>
38193833

38203834

clang/include/clang/AST/ASTTypeTraits.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class ASTNodeKind {
132132
enum NodeKindId {
133133
NKI_None,
134134
NKI_TemplateArgument,
135+
NKI_TemplateArgumentLoc,
135136
NKI_TemplateName,
136137
NKI_NestedNameSpecifierLoc,
137138
NKI_QualType,
@@ -191,6 +192,7 @@ class ASTNodeKind {
191192
};
192193
KIND_TO_KIND_ID(CXXCtorInitializer)
193194
KIND_TO_KIND_ID(TemplateArgument)
195+
KIND_TO_KIND_ID(TemplateArgumentLoc)
194196
KIND_TO_KIND_ID(TemplateName)
195197
KIND_TO_KIND_ID(NestedNameSpecifier)
196198
KIND_TO_KIND_ID(NestedNameSpecifierLoc)
@@ -456,12 +458,13 @@ class DynTypedNode {
456458
/// Note that we can store \c Decls, \c Stmts, \c Types,
457459
/// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
458460
/// guaranteed to be unique pointers pointing to dedicated storage in the AST.
459-
/// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
460-
/// \c TemplateArguments on the other hand do not have storage or unique
461-
/// pointers and thus need to be stored by value.
461+
/// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs,
462+
/// \c TemplateArguments and \c TemplateArgumentLocs on the other hand do not
463+
/// have storage or unique pointers and thus need to be stored by value.
462464
llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
463-
NestedNameSpecifierLoc, QualType,
464-
TypeLoc> Storage;
465+
TemplateArgumentLoc, NestedNameSpecifierLoc,
466+
QualType, TypeLoc>
467+
Storage;
465468
};
466469

467470
template <typename T>
@@ -496,6 +499,10 @@ template <>
496499
struct DynTypedNode::BaseConverter<
497500
TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
498501

502+
template <>
503+
struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void>
504+
: public ValueConverter<TemplateArgumentLoc> {};
505+
499506
template <>
500507
struct DynTypedNode::BaseConverter<
501508
TemplateName, void> : public ValueConverter<TemplateName> {};

clang/include/clang/ASTMatchers/ASTMatchFinder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ class MatchFinder {
159159
MatchCallback *Action);
160160
void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
161161
MatchCallback *Action);
162+
void addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
163+
MatchCallback *Action);
162164
/// @}
163165

164166
/// Adds a matcher to execute when running over the AST.
@@ -209,6 +211,8 @@ class MatchFinder {
209211
NestedNameSpecifierLoc;
210212
std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
211213
std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit;
214+
std::vector<std::pair<TemplateArgumentLocMatcher, MatchCallback *>>
215+
TemplateArgumentLoc;
212216
/// All the callbacks in one container to simplify iteration.
213217
llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
214218
};

clang/include/clang/ASTMatchers/ASTMatchers.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ using TypeLocMatcher = internal::Matcher<TypeLoc>;
145145
using NestedNameSpecifierMatcher = internal::Matcher<NestedNameSpecifier>;
146146
using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>;
147147
using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>;
148+
using TemplateArgumentLocMatcher = internal::Matcher<TemplateArgumentLoc>;
148149
/// @}
149150

150151
/// Matches any node.
@@ -515,6 +516,18 @@ extern const internal::VariadicAllOfMatcher<CXXCtorInitializer>
515516
/// matches 'int' in C<int>.
516517
extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
517518

519+
/// Matches template arguments (with location info).
520+
///
521+
/// Given
522+
/// \code
523+
/// template <typename T> struct C {};
524+
/// C<int> c;
525+
/// \endcode
526+
/// templateArgumentLoc()
527+
/// matches 'int' in C<int>.
528+
extern const internal::VariadicAllOfMatcher<TemplateArgumentLoc>
529+
templateArgumentLoc;
530+
518531
/// Matches template name.
519532
///
520533
/// Given

clang/include/clang/ASTMatchers/ASTMatchersInternal.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -938,14 +938,13 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
938938
template <typename T>
939939
struct IsBaseType {
940940
static const bool value =
941-
std::is_same<T, Decl>::value ||
942-
std::is_same<T, Stmt>::value ||
943-
std::is_same<T, QualType>::value ||
944-
std::is_same<T, Type>::value ||
941+
std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value ||
942+
std::is_same<T, QualType>::value || std::is_same<T, Type>::value ||
945943
std::is_same<T, TypeLoc>::value ||
946944
std::is_same<T, NestedNameSpecifier>::value ||
947945
std::is_same<T, NestedNameSpecifierLoc>::value ||
948-
std::is_same<T, CXXCtorInitializer>::value;
946+
std::is_same<T, CXXCtorInitializer>::value ||
947+
std::is_same<T, TemplateArgumentLoc>::value;
949948
};
950949
template <typename T>
951950
const bool IsBaseType<T>::value;

clang/lib/AST/ASTTypeTraits.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ using namespace clang;
2323
const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
2424
{ NKI_None, "<None>" },
2525
{ NKI_None, "TemplateArgument" },
26+
{ NKI_None, "TemplateArgumentLoc" },
2627
{ NKI_None, "TemplateName" },
2728
{ NKI_None, "NestedNameSpecifierLoc" },
2829
{ NKI_None, "QualType" },
@@ -129,6 +130,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS,
129130
const PrintingPolicy &PP) const {
130131
if (const TemplateArgument *TA = get<TemplateArgument>())
131132
TA->print(PP, OS);
133+
else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
134+
TAL->getArgument().print(PP, OS);
132135
else if (const TemplateName *TN = get<TemplateName>())
133136
TN->print(OS, PP);
134137
else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
@@ -175,6 +178,8 @@ SourceRange DynTypedNode::getSourceRange() const {
175178
return D->getSourceRange();
176179
if (const Stmt *S = get<Stmt>())
177180
return S->getSourceRange();
181+
if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
182+
return TAL->getSourceRange();
178183
if (const auto *C = get<OMPClause>())
179184
return SourceRange(C->getBeginLoc(), C->getEndLoc());
180185
return SourceRange();

clang/lib/ASTMatchers/ASTMatchFinder.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ class MatchChildASTVisitor
128128
traverse(*T);
129129
else if (const auto *C = DynNode.get<CXXCtorInitializer>())
130130
traverse(*C);
131+
else if (const TemplateArgumentLoc *TALoc =
132+
DynNode.get<TemplateArgumentLoc>())
133+
traverse(*TALoc);
131134
// FIXME: Add other base types after adding tests.
132135

133136
// It's OK to always overwrite the bound nodes, as if there was
@@ -224,6 +227,10 @@ class MatchChildASTVisitor
224227
ScopedIncrement ScopedDepth(&CurrentDepth);
225228
return traverse(*CtorInit);
226229
}
230+
bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) {
231+
ScopedIncrement ScopedDepth(&CurrentDepth);
232+
return traverse(TAL);
233+
}
227234
bool TraverseLambdaExpr(LambdaExpr *Node) {
228235
if (Finder->getASTContext().getParentMapContext().getTraversalKind() !=
229236
TK_IgnoreUnlessSpelledInSource)
@@ -304,6 +311,9 @@ class MatchChildASTVisitor
304311
return VisitorBase::TraverseConstructorInitializer(
305312
const_cast<CXXCtorInitializer *>(&CtorInit));
306313
}
314+
bool baseTraverse(TemplateArgumentLoc TAL) {
315+
return VisitorBase::TraverseTemplateArgumentLoc(TAL);
316+
}
307317

308318
// Sets 'Matched' to true if 'Matcher' matches 'Node' and:
309319
// 0 < CurrentDepth <= MaxDepth.
@@ -447,6 +457,7 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
447457
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
448458
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
449459
bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
460+
bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
450461

451462
// Matches children or descendants of 'Node' with 'BaseMatcher'.
452463
bool memoizedMatchesRecursively(const DynTypedNode &Node, ASTContext &Ctx,
@@ -557,6 +568,8 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
557568
match(*N);
558569
} else if (auto *N = Node.get<CXXCtorInitializer>()) {
559570
match(*N);
571+
} else if (auto *N = Node.get<TemplateArgumentLoc>()) {
572+
match(*N);
560573
}
561574
}
562575

@@ -680,6 +693,9 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
680693
void matchDispatch(const CXXCtorInitializer *Node) {
681694
matchWithoutFilter(*Node, Matchers->CtorInit);
682695
}
696+
void matchDispatch(const TemplateArgumentLoc *Node) {
697+
matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc);
698+
}
683699
void matchDispatch(const void *) { /* Do nothing. */ }
684700
/// @}
685701

@@ -1035,6 +1051,11 @@ bool MatchASTVisitor::TraverseConstructorInitializer(
10351051
CtorInit);
10361052
}
10371053

1054+
bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
1055+
match(Loc);
1056+
return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc);
1057+
}
1058+
10381059
class MatchASTConsumer : public ASTConsumer {
10391060
public:
10401061
MatchASTConsumer(MatchFinder *Finder,
@@ -1111,6 +1132,12 @@ void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
11111132
Matchers.AllCallbacks.insert(Action);
11121133
}
11131134

1135+
void MatchFinder::addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
1136+
MatchCallback *Action) {
1137+
Matchers.TemplateArgumentLoc.emplace_back(NodeMatch, Action);
1138+
Matchers.AllCallbacks.insert(Action);
1139+
}
1140+
11141141
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
11151142
MatchCallback *Action) {
11161143
if (NodeMatch.canConvertTo<Decl>()) {
@@ -1134,6 +1161,9 @@ bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
11341161
} else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
11351162
addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
11361163
return true;
1164+
} else if (NodeMatch.canConvertTo<TemplateArgumentLoc>()) {
1165+
addMatcher(NodeMatch.convertTo<TemplateArgumentLoc>(), Action);
1166+
return true;
11371167
}
11381168
return false;
11391169
}

clang/lib/ASTMatchers/ASTMatchersInternal.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
734734
accessSpecDecl;
735735
const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
736736
const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
737+
const internal::VariadicAllOfMatcher<TemplateArgumentLoc> templateArgumentLoc;
737738
const internal::VariadicAllOfMatcher<TemplateName> templateName;
738739
const internal::VariadicDynCastAllOfMatcher<Decl, NonTypeTemplateParmDecl>
739740
nonTypeTemplateParmDecl;

clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2637,6 +2637,19 @@ TEST(Has, DoesNotDeleteBindings) {
26372637
std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
26382638
}
26392639

2640+
TEST(TemplateArgumentLoc, Matches) {
2641+
EXPECT_TRUE(matchAndVerifyResultTrue(
2642+
R"cpp(
2643+
template <typename A, int B, template <typename> class C> class X {};
2644+
class A {};
2645+
const int B = 42;
2646+
template <typename> class C {};
2647+
X<A, B, C> x;
2648+
)cpp",
2649+
templateArgumentLoc().bind("x"),
2650+
std::make_unique<VerifyIdIsBoundTo<TemplateArgumentLoc>>("x", 3)));
2651+
}
2652+
26402653
TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
26412654
// Those matchers cover all the cases where an inner matcher is called
26422655
// and there is not a 1:1 relationship between the match of the outer

0 commit comments

Comments
 (0)