]> granicus.if.org Git - clang/commitdiff
[ASTMatcher] Add templateName matcher.
authorHaojian Wu <hokein@google.com>
Fri, 29 Jul 2016 15:45:11 +0000 (15:45 +0000)
committerHaojian Wu <hokein@google.com>
Fri, 29 Jul 2016 15:45:11 +0000 (15:45 +0000)
Reviewers: klimek

Subscribers: klimek, cfe-commits

Differential Revision: https://reviews.llvm.org/D22963

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@277155 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LibASTMatchersReference.html
include/clang/AST/ASTTypeTraits.h
include/clang/ASTMatchers/ASTMatchers.h
lib/AST/ASTTypeTraits.cpp
lib/ASTMatchers/Dynamic/Registry.cpp
unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

index 222b39fcf5c313c83d3ed63d159c5dc3cfe5c419..cb6a05e3e9120c9e40cf4bac5667f24c318959a8 100644 (file)
@@ -1318,6 +1318,17 @@ templateArgument()
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt;</td><td class="name" onclick="toggle('templateName0')"><a name="templateName0Anchor">templateName</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt;...</td></tr>
+<tr><td colspan="4" class="doc" id="templateName0"><pre>Matches template name.
+
+Given
+  template &lt;typename T&gt; class X { };
+  X&lt;int&gt; xi;
+templateName()
+  matches 'X' in X&lt;int&gt;.
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;</td><td class="name" onclick="toggle('typeLoc0')"><a name="typeLoc0Anchor">typeLoc</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TypeLoc.html">TypeLoc</a>&gt;...</td></tr>
 <tr><td colspan="4" class="doc" id="typeLoc0"><pre>Matches TypeLocs in the clang AST.
 </pre></td></tr>
@@ -5353,6 +5364,19 @@ classTemplateSpecializationDecl(
 </pre></td></tr>
 
 
+<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToTemplate0')"><a name="refersToTemplate0Anchor">refersToTemplate</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateName.html">TemplateName</a>&gt; InnerMatcher</td></tr>
+<tr><td colspan="4" class="doc" id="refersToTemplate0"><pre>Matches a TemplateArgument that refers to a certain template.
+
+Given
+  template&lt;template &lt;typename&gt; class S&gt; class X {};
+  template&lt;typename T&gt; class Y {};"
+  X&lt;Y&gt; xi;
+classTemplateSpecializationDecl(hasAnyTemplateArgument(
+    refersToTemplate(templateName())))
+  matches the specialization X&lt;Y&gt;
+</pre></td></tr>
+
+
 <tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1TemplateArgument.html">TemplateArgument</a>&gt;</td><td class="name" onclick="toggle('refersToType0')"><a name="refersToType0Anchor">refersToType</a></td><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1QualType.html">QualType</a>&gt; InnerMatcher</td></tr>
 <tr><td colspan="4" class="doc" id="refersToType0"><pre>Matches a TemplateArgument that refers to a certain type.
 
index ad301b14829e52bde2267ed5e3ef31bf8b242783..51d60a90a146b39e4182df704b2546da34dc7f97 100644 (file)
@@ -121,6 +121,7 @@ private:
   enum NodeKindId {
     NKI_None,
     NKI_TemplateArgument,
+    NKI_TemplateName,
     NKI_NestedNameSpecifierLoc,
     NKI_QualType,
     NKI_TypeLoc,
@@ -175,6 +176,7 @@ private:
   };
 KIND_TO_KIND_ID(CXXCtorInitializer)
 KIND_TO_KIND_ID(TemplateArgument)
+KIND_TO_KIND_ID(TemplateName)
 KIND_TO_KIND_ID(NestedNameSpecifier)
 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
 KIND_TO_KIND_ID(QualType)
@@ -470,6 +472,10 @@ template <>
 struct DynTypedNode::BaseConverter<
     TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
 
+template <>
+struct DynTypedNode::BaseConverter<
+    TemplateName, void> : public ValueConverter<TemplateName> {};
+
 template <>
 struct DynTypedNode::BaseConverter<
     NestedNameSpecifierLoc,
index 6f59b825202c4f52c9d749670200cdb6532dcc73..4e7e721c91a0bc24b9fe05c126159bd8eddfc681 100644 (file)
@@ -446,6 +446,17 @@ const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer;
 ///   matches 'int' in C<int>.
 const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument;
 
+/// \brief Matches template name.
+///
+/// Given
+/// \code
+///   template <typename T> class X { };
+///   X<int> xi;
+/// \endcode
+/// templateName()
+///   matches 'X' in X<int>.
+const internal::VariadicAllOfMatcher<TemplateName> templateName;
+
 /// \brief Matches non-type template parameter declarations.
 ///
 /// Given
@@ -774,6 +785,24 @@ AST_MATCHER_P(TemplateArgument, refersToType,
   return InnerMatcher.matches(Node.getAsType(), Finder, Builder);
 }
 
+/// \brief Matches a TemplateArgument that refers to a certain template.
+///
+/// Given
+/// \code
+///   template<template <typename> class S> class X {};
+///   template<typename T> class Y {};"
+///   X<Y> xi;
+/// \endcode
+/// classTemplateSpecializationDecl(hasAnyTemplateArgument(
+///     refersToTemplate(templateName())))
+///   matches the specialization \c X<Y>
+AST_MATCHER_P(TemplateArgument, refersToTemplate,
+              internal::Matcher<TemplateName>, InnerMatcher) {
+  if (Node.getKind() != TemplateArgument::Template)
+    return false;
+  return InnerMatcher.matches(Node.getAsTemplate(), Finder, Builder);
+}
+
 /// \brief Matches a canonical TemplateArgument that refers to a certain
 /// declaration.
 ///
index 2336c98fe049e7aaffaf4f39d63e2ed11f6bc046..680f526f00da0140f4797613435ec92e4f7b8cf8 100644 (file)
@@ -23,6 +23,7 @@ namespace ast_type_traits {
 const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = {
   { NKI_None, "<None>" },
   { NKI_None, "TemplateArgument" },
+  { NKI_None, "TemplateName" },
   { NKI_None, "NestedNameSpecifierLoc" },
   { NKI_None, "QualType" },
   { NKI_None, "TypeLoc" },
@@ -109,6 +110,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 TemplateName *TN = get<TemplateName>())
+    TN->print(OS, PP);
   else if (const NestedNameSpecifier *NNS = get<NestedNameSpecifier>())
     NNS->print(OS, PP);
   else if (const NestedNameSpecifierLoc *NNSL = get<NestedNameSpecifierLoc>())
index a8d4b88d8580970f458b1d4c551445b9d4b20495..24ff30cd7bc745acba3de8c621b6c73e6f6d15aa 100644 (file)
@@ -391,6 +391,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(switchCase);
   REGISTER_MATCHER(switchStmt);
   REGISTER_MATCHER(templateArgument);
+  REGISTER_MATCHER(templateName);
   REGISTER_MATCHER(templateArgumentCountIs);
   REGISTER_MATCHER(templateSpecializationType);
   REGISTER_MATCHER(templateTypeParmType);
index 7c496647b4c602a59b875818afca01cff94aff94..41d588f122b35ffbfc9e2fc856c1ddc5415261ba 100644 (file)
@@ -543,6 +543,14 @@ TEST(Matcher, MatchesTypeTemplateArgument) {
       asString("int"))))));
 }
 
+TEST(Matcher, MatchesTemplateTemplateArgument) {
+  EXPECT_TRUE(matches("template<template <typename> class S> class X {};"
+                      "template<typename T> class Y {};"
+                      "X<Y> xi;",
+                      classTemplateSpecializationDecl(hasAnyTemplateArgument(
+                          refersToTemplate(templateName())))));
+}
+
 TEST(Matcher, MatchesDeclarationReferenceTemplateArgument) {
   EXPECT_TRUE(matches(
     "struct B { int next; };"