[clang] b1c7f84 - [clang] Allow DynTypedNode to store a TemplateArgumentLoc
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 10 00:09:40 PDT 2020
Author: Nathan Ridge
Date: 2020-08-10T03:09:18-04:00
New Revision: b1c7f84643ffa63e72733b7089cea89723b82afc
URL: https://github.com/llvm/llvm-project/commit/b1c7f84643ffa63e72733b7089cea89723b82afc
DIFF: https://github.com/llvm/llvm-project/commit/b1c7f84643ffa63e72733b7089cea89723b82afc.diff
LOG: [clang] Allow DynTypedNode to store a TemplateArgumentLoc
The patch also adds a templateArgumentLoc() AST matcher.
Differential Revision: https://reviews.llvm.org/D85621
Added:
Modified:
clang/docs/LibASTMatchersReference.html
clang/include/clang/AST/ASTTypeTraits.h
clang/include/clang/ASTMatchers/ASTMatchFinder.h
clang/include/clang/ASTMatchers/ASTMatchers.h
clang/include/clang/ASTMatchers/ASTMatchersInternal.h
clang/lib/AST/ASTTypeTraits.cpp
clang/lib/ASTMatchers/ASTMatchFinder.cpp
clang/lib/ASTMatchers/ASTMatchersInternal.cpp
clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html
index 60ff6ffe6056..eb85e420e7e4 100644
--- a/clang/docs/LibASTMatchersReference.html
+++ b/clang/docs/LibASTMatchersReference.html
@@ -679,7 +679,8 @@ <h2 id="decl-matchers">Node Matchers</h2>
#pragma omp parallel default(firstprivate)
#pragma omp parallel
-``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and ``default(firstprivate)``.
+``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and
+``default(firstprivate)``
</pre></td></tr>
@@ -1625,6 +1626,17 @@ <h2 id="decl-matchers">Node Matchers</h2>
</pre></td></tr>
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>></td><td class="name" onclick="toggle('templateArgumentLoc0')"><a name="templateArgumentLoc0Anchor">templateArgumentLoc</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgumentLoc.html">TemplateArgumentLoc</a>>...</td></tr>
+<tr><td colspan="4" class="doc" id="templateArgumentLoc0"><pre>Matches template arguments (with location info).
+
+Given
+ template <typename T> struct C {};
+ C<int> c;
+templateArgumentLoc()
+ matches 'int' in C<int>.
+</pre></td></tr>
+
+
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>></td><td class="name" onclick="toggle('templateArgument0')"><a name="templateArgument0Anchor">templateArgument</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>>...</td></tr>
<tr><td colspan="4" class="doc" id="templateArgument0"><pre>Matches template arguments.
@@ -3776,8 +3788,9 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>></td><td class="name" onclick="toggle('isNoneKind0')"><a name="isNoneKind0Anchor">isNoneKind</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="isNoneKind0"><pre>Matches if the OpenMP ``default`` clause has ``none`` kind specified.
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>></td><td class="name" onclick="toggle('isFirstPrivateKind0')"><a name="isFirstPrivateKind0Anchor">isFirstPrivateKind</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isFirstPrivateKind0"><pre>Matches if the OpenMP ``default`` clause has ``firstprivate`` kind
+specified.
Given
@@ -3786,12 +3799,13 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
#pragma omp parallel default(shared)
#pragma omp parallel default(firstprivate)
-``ompDefaultClause(isNoneKind())`` matches only ``default(none)``.
+``ompDefaultClause(isFirstPrivateKind())`` matches only
+``default(firstprivate)``.
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>></td><td class="name" onclick="toggle('isSharedKind0')"><a name="isSharedKind0Anchor">isSharedKind</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="isSharedKind0"><pre>Matches if the OpenMP ``default`` clause has ``shared`` kind specified.
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>></td><td class="name" onclick="toggle('isNoneKind0')"><a name="isNoneKind0Anchor">isNoneKind</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isNoneKind0"><pre>Matches if the OpenMP ``default`` clause has ``none`` kind specified.
Given
@@ -3800,12 +3814,12 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
#pragma omp parallel default(shared)
#pragma omp parallel default(firstprivate)
-``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``.
+``ompDefaultClause(isNoneKind())`` matches only ``default(none)``.
</pre></td></tr>
-<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>></td><td class="name" onclick="toggle('isFirstPrivateKind0')"><a name="isFirstPrivateKind0Anchor">isSharedKind</a></td><td></td></tr>
-<tr><td colspan="4" class="doc" id="isFirstPrivateKind0"><pre>Matches if the OpenMP ``default`` clause has ``firstprivate`` kind specified.
+<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1OMPDefaultClause.html">OMPDefaultClause</a>></td><td class="name" onclick="toggle('isSharedKind0')"><a name="isSharedKind0Anchor">isSharedKind</a></td><td></td></tr>
+<tr><td colspan="4" class="doc" id="isSharedKind0"><pre>Matches if the OpenMP ``default`` clause has ``shared`` kind specified.
Given
@@ -3814,7 +3828,7 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
#pragma omp parallel default(shared)
#pragma omp parallel default(firstprivate)
-``ompDefaultClause(isFirstPrivateKind())`` matches only ``default(firstprivate)``.
+``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``.
</pre></td></tr>
diff --git a/clang/include/clang/AST/ASTTypeTraits.h b/clang/include/clang/AST/ASTTypeTraits.h
index 328b7bce6ba5..bd817b75bb84 100644
--- a/clang/include/clang/AST/ASTTypeTraits.h
+++ b/clang/include/clang/AST/ASTTypeTraits.h
@@ -132,6 +132,7 @@ class ASTNodeKind {
enum NodeKindId {
NKI_None,
NKI_TemplateArgument,
+ NKI_TemplateArgumentLoc,
NKI_TemplateName,
NKI_NestedNameSpecifierLoc,
NKI_QualType,
@@ -191,6 +192,7 @@ class ASTNodeKind {
};
KIND_TO_KIND_ID(CXXCtorInitializer)
KIND_TO_KIND_ID(TemplateArgument)
+KIND_TO_KIND_ID(TemplateArgumentLoc)
KIND_TO_KIND_ID(TemplateName)
KIND_TO_KIND_ID(NestedNameSpecifier)
KIND_TO_KIND_ID(NestedNameSpecifierLoc)
@@ -456,12 +458,13 @@ class DynTypedNode {
/// Note that we can store \c Decls, \c Stmts, \c Types,
/// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
/// guaranteed to be unique pointers pointing to dedicated storage in the AST.
- /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
- /// \c TemplateArguments on the other hand do not have storage or unique
- /// pointers and thus need to be stored by value.
+ /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs,
+ /// \c TemplateArguments and \c TemplateArgumentLocs on the other hand do not
+ /// have storage or unique pointers and thus need to be stored by value.
llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
- NestedNameSpecifierLoc, QualType,
- TypeLoc> Storage;
+ TemplateArgumentLoc, NestedNameSpecifierLoc,
+ QualType, TypeLoc>
+ Storage;
};
template <typename T>
@@ -496,6 +499,10 @@ template <>
struct DynTypedNode::BaseConverter<
TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
+template <>
+struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void>
+ : public ValueConverter<TemplateArgumentLoc> {};
+
template <>
struct DynTypedNode::BaseConverter<
TemplateName, void> : public ValueConverter<TemplateName> {};
diff --git a/clang/include/clang/ASTMatchers/ASTMatchFinder.h b/clang/include/clang/ASTMatchers/ASTMatchFinder.h
index 0af98438ab52..81125ad8d96d 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -159,6 +159,8 @@ class MatchFinder {
MatchCallback *Action);
void addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
MatchCallback *Action);
+ void addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
+ MatchCallback *Action);
/// @}
/// Adds a matcher to execute when running over the AST.
@@ -209,6 +211,8 @@ class MatchFinder {
NestedNameSpecifierLoc;
std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc;
std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit;
+ std::vector<std::pair<TemplateArgumentLocMatcher, MatchCallback *>>
+ TemplateArgumentLoc;
/// All the callbacks in one container to simplify iteration.
llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks;
};
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index 643419743a11..e37c68a8f156 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -145,6 +145,7 @@ using TypeLocMatcher = internal::Matcher<TypeLoc>;
using NestedNameSpecifierMatcher = internal::Matcher<NestedNameSpecifier>;
using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>;
using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>;
+using TemplateArgumentLocMatcher = internal::Matcher<TemplateArgumentLoc>;
/// @}
/// Matches any node.
@@ -515,6 +516,18 @@ extern const internal::VariadicAllOfMatcher<CXXCtorInitializer>
/// matches 'int' in C<int>.
extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+/// Matches template arguments (with location info).
+///
+/// Given
+/// \code
+/// template <typename T> struct C {};
+/// C<int> c;
+/// \endcode
+/// templateArgumentLoc()
+/// matches 'int' in C<int>.
+extern const internal::VariadicAllOfMatcher<TemplateArgumentLoc>
+ templateArgumentLoc;
+
/// Matches template name.
///
/// Given
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
index 3992850c992d..09774b3c912c 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -938,14 +938,13 @@ class HasDeclarationMatcher : public MatcherInterface<T> {
template <typename T>
struct IsBaseType {
static const bool value =
- std::is_same<T, Decl>::value ||
- std::is_same<T, Stmt>::value ||
- std::is_same<T, QualType>::value ||
- std::is_same<T, Type>::value ||
+ std::is_same<T, Decl>::value || std::is_same<T, Stmt>::value ||
+ std::is_same<T, QualType>::value || std::is_same<T, Type>::value ||
std::is_same<T, TypeLoc>::value ||
std::is_same<T, NestedNameSpecifier>::value ||
std::is_same<T, NestedNameSpecifierLoc>::value ||
- std::is_same<T, CXXCtorInitializer>::value;
+ std::is_same<T, CXXCtorInitializer>::value ||
+ std::is_same<T, TemplateArgumentLoc>::value;
};
template <typename T>
const bool IsBaseType<T>::value;
diff --git a/clang/lib/AST/ASTTypeTraits.cpp b/clang/lib/AST/ASTTypeTraits.cpp
index 34fc587694be..ce8a321a691f 100644
--- a/clang/lib/AST/ASTTypeTraits.cpp
+++ b/clang/lib/AST/ASTTypeTraits.cpp
@@ -23,6 +23,7 @@ using namespace clang;
const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
{ NKI_None, "<None>" },
{ NKI_None, "TemplateArgument" },
+ { NKI_None, "TemplateArgumentLoc" },
{ NKI_None, "TemplateName" },
{ NKI_None, "NestedNameSpecifierLoc" },
{ NKI_None, "QualType" },
@@ -129,6 +130,8 @@ void DynTypedNode::print(llvm::raw_ostream &OS,
const PrintingPolicy &PP) const {
if (const TemplateArgument *TA = get<TemplateArgument>())
TA->print(PP, OS);
+ else if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
+ TAL->getArgument().print(PP, OS);
else if (const TemplateName *TN = get<TemplateName>())
TN->print(OS, PP);
else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
@@ -175,6 +178,8 @@ SourceRange DynTypedNode::getSourceRange() const {
return D->getSourceRange();
if (const Stmt *S = get<Stmt>())
return S->getSourceRange();
+ if (const TemplateArgumentLoc *TAL = get<TemplateArgumentLoc>())
+ return TAL->getSourceRange();
if (const auto *C = get<OMPClause>())
return SourceRange(C->getBeginLoc(), C->getEndLoc());
return SourceRange();
diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
index e88da16dd3d4..dc937dde88e3 100644
--- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp
@@ -128,6 +128,9 @@ class MatchChildASTVisitor
traverse(*T);
else if (const auto *C = DynNode.get<CXXCtorInitializer>())
traverse(*C);
+ else if (const TemplateArgumentLoc *TALoc =
+ DynNode.get<TemplateArgumentLoc>())
+ traverse(*TALoc);
// FIXME: Add other base types after adding tests.
// It's OK to always overwrite the bound nodes, as if there was
@@ -224,6 +227,10 @@ class MatchChildASTVisitor
ScopedIncrement ScopedDepth(&CurrentDepth);
return traverse(*CtorInit);
}
+ bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL) {
+ ScopedIncrement ScopedDepth(&CurrentDepth);
+ return traverse(TAL);
+ }
bool TraverseLambdaExpr(LambdaExpr *Node) {
if (Finder->getASTContext().getParentMapContext().getTraversalKind() !=
TK_IgnoreUnlessSpelledInSource)
@@ -304,6 +311,9 @@ class MatchChildASTVisitor
return VisitorBase::TraverseConstructorInitializer(
const_cast<CXXCtorInitializer *>(&CtorInit));
}
+ bool baseTraverse(TemplateArgumentLoc TAL) {
+ return VisitorBase::TraverseTemplateArgumentLoc(TAL);
+ }
// Sets 'Matched' to true if 'Matcher' matches 'Node' and:
// 0 < CurrentDepth <= MaxDepth.
@@ -447,6 +457,7 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
bool TraverseConstructorInitializer(CXXCtorInitializer *CtorInit);
+ bool TraverseTemplateArgumentLoc(TemplateArgumentLoc TAL);
// Matches children or descendants of 'Node' with 'BaseMatcher'.
bool memoizedMatchesRecursively(const DynTypedNode &Node, ASTContext &Ctx,
@@ -557,6 +568,8 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
match(*N);
} else if (auto *N = Node.get<CXXCtorInitializer>()) {
match(*N);
+ } else if (auto *N = Node.get<TemplateArgumentLoc>()) {
+ match(*N);
}
}
@@ -680,6 +693,9 @@ class MatchASTVisitor : public RecursiveASTVisitor<MatchASTVisitor>,
void matchDispatch(const CXXCtorInitializer *Node) {
matchWithoutFilter(*Node, Matchers->CtorInit);
}
+ void matchDispatch(const TemplateArgumentLoc *Node) {
+ matchWithoutFilter(*Node, Matchers->TemplateArgumentLoc);
+ }
void matchDispatch(const void *) { /* Do nothing. */ }
/// @}
@@ -1035,6 +1051,11 @@ bool MatchASTVisitor::TraverseConstructorInitializer(
CtorInit);
}
+bool MatchASTVisitor::TraverseTemplateArgumentLoc(TemplateArgumentLoc Loc) {
+ match(Loc);
+ return RecursiveASTVisitor<MatchASTVisitor>::TraverseTemplateArgumentLoc(Loc);
+}
+
class MatchASTConsumer : public ASTConsumer {
public:
MatchASTConsumer(MatchFinder *Finder,
@@ -1111,6 +1132,12 @@ void MatchFinder::addMatcher(const CXXCtorInitializerMatcher &NodeMatch,
Matchers.AllCallbacks.insert(Action);
}
+void MatchFinder::addMatcher(const TemplateArgumentLocMatcher &NodeMatch,
+ MatchCallback *Action) {
+ Matchers.TemplateArgumentLoc.emplace_back(NodeMatch, Action);
+ Matchers.AllCallbacks.insert(Action);
+}
+
bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
MatchCallback *Action) {
if (NodeMatch.canConvertTo<Decl>()) {
@@ -1134,6 +1161,9 @@ bool MatchFinder::addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch,
} else if (NodeMatch.canConvertTo<CXXCtorInitializer>()) {
addMatcher(NodeMatch.convertTo<CXXCtorInitializer>(), Action);
return true;
+ } else if (NodeMatch.canConvertTo<TemplateArgumentLoc>()) {
+ addMatcher(NodeMatch.convertTo<TemplateArgumentLoc>(), Action);
+ return true;
}
return false;
}
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 4b9baf7a0e75..5b9476f3098a 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -734,6 +734,7 @@ const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl>
accessSpecDecl;
const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
+const internal::VariadicAllOfMatcher<TemplateArgumentLoc> templateArgumentLoc;
const internal::VariadicAllOfMatcher<TemplateName> templateName;
const internal::VariadicDynCastAllOfMatcher<Decl, NonTypeTemplateParmDecl>
nonTypeTemplateParmDecl;
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index 380538697f46..c7db52b37a50 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -2637,6 +2637,19 @@ TEST(Has, DoesNotDeleteBindings) {
std::make_unique<VerifyIdIsBoundTo<Decl>>("x", 1)));
}
+TEST(TemplateArgumentLoc, Matches) {
+ EXPECT_TRUE(matchAndVerifyResultTrue(
+ R"cpp(
+ template <typename A, int B, template <typename> class C> class X {};
+ class A {};
+ const int B = 42;
+ template <typename> class C {};
+ X<A, B, C> x;
+ )cpp",
+ templateArgumentLoc().bind("x"),
+ std::make_unique<VerifyIdIsBoundTo<TemplateArgumentLoc>>("x", 3)));
+}
+
TEST(LoopingMatchers, DoNotOverwritePreviousMatchResultOnFailure) {
// Those matchers cover all the cases where an inner matcher is called
// and there is not a 1:1 relationship between the match of the outer
More information about the cfe-commits
mailing list