r281345 - Traversing template paramter lists of DeclaratorDecls and/or TagDecls.

Nico Weber via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 13 08:05:04 PDT 2016


Author: nico
Date: Tue Sep 13 10:05:04 2016
New Revision: 281345

URL: http://llvm.org/viewvc/llvm-project?rev=281345&view=rev
Log:
Traversing template paramter lists of DeclaratorDecls and/or TagDecls.

The unit tests in this patch demonstrate the need to traverse template
parameter lists of DeclaratorDecls (e.g. VarDecls, CXXMethodDecls) and
TagDecls (e.g. EnumDecls, RecordDecls).

Fixes PR29042.
https://reviews.llvm.org/D24268

Patch from Lukasz
Ɓukasz Anforowicz <lukasza at chromium.org>!

Modified:
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=281345&r1=281344&r2=281345&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Sep 13 10:05:04 2016
@@ -482,6 +482,11 @@ public:
 private:
   // These are helper methods used by more than one Traverse* method.
   bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
+
+  // Traverses template parameter lists of either a DeclaratorDecl or TagDecl.
+  template <typename T>
+  bool TraverseDeclTemplateParameterLists(T *D);
+
 #define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND)                                   \
   bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D);
   DEF_TRAVERSE_TMPL_INST(Class)
@@ -1534,6 +1539,16 @@ bool RecursiveASTVisitor<Derived>::Trave
 }
 
 template <typename Derived>
+template <typename T>
+bool RecursiveASTVisitor<Derived>::TraverseDeclTemplateParameterLists(T *D) {
+  for (unsigned i = 0; i < D->getNumTemplateParameterLists(); i++) {
+    TemplateParameterList *TPL = D->getTemplateParameterList(i);
+    TraverseTemplateParameterListHelper(TPL);
+  }
+  return true;
+}
+
+template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
     ClassTemplateDecl *D) {
   for (auto *SD : D->specializations()) {
@@ -1694,6 +1709,8 @@ DEF_TRAVERSE_DECL(UnresolvedUsingTypenam
 })
 
 DEF_TRAVERSE_DECL(EnumDecl, {
+  TRY_TO(TraverseDeclTemplateParameterLists(D));
+
   if (D->getTypeForDecl())
     TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
 
@@ -1708,6 +1725,7 @@ bool RecursiveASTVisitor<Derived>::Trave
   // We shouldn't traverse D->getTypeForDecl(); it's a result of
   // declaring the type, not something that was written in the source.
 
+  TRY_TO(TraverseDeclTemplateParameterLists(D));
   TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
   return true;
 }
@@ -1802,6 +1820,7 @@ DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
 
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
+  TRY_TO(TraverseDeclTemplateParameterLists(D));
   TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
   if (D->getTypeSourceInfo())
     TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
@@ -1848,6 +1867,7 @@ DEF_TRAVERSE_DECL(ObjCIvarDecl, {
 
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
+  TRY_TO(TraverseDeclTemplateParameterLists(D));
   TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
   TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
 

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp?rev=281345&r1=281344&r2=281345&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Tue Sep 13 10:05:04 2016
@@ -641,6 +641,89 @@ TEST(TemplateArgument, Matches) {
     functionDecl(hasAnyTemplateArgument(templateArgument()))));
 }
 
+TEST(TemplateTypeParmDecl, CXXMethodDecl) {
+  const char input[] =
+      "template<typename T>\n"
+      "class Class {\n"
+      "  void method();\n"
+      "};\n"
+      "template<typename U>\n"
+      "void Class<U>::method() {}\n";
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
+TEST(TemplateTypeParmDecl, VarDecl) {
+  const char input[] =
+      "template<typename T>\n"
+      "class Class {\n"
+      "  static T pi;\n"
+      "};\n"
+      "template<typename U>\n"
+      "U Class<U>::pi = U(3.1415926535897932385);\n";
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
+TEST(TemplateTypeParmDecl, VarTemplatePartialSpecializationDecl) {
+  const char input[] =
+      "template<typename T>\n"
+      "struct Struct {\n"
+      "  template<typename T2> static int field;\n"
+      "};\n"
+      "template<typename U>\n"
+      "template<typename U2>\n"
+      "int Struct<U>::field<char> = 123;\n";
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T2"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U2"))));
+}
+
+TEST(TemplateTypeParmDecl, ClassTemplatePartialSpecializationDecl) {
+  const char input[] =
+      "template<typename T>\n"
+      "class Class {\n"
+      "  template<typename T2> struct Struct;\n"
+      "};\n"
+      "template<typename U>\n"
+      "template<typename U2>\n"
+      "struct Class<U>::Struct<int> {};\n";
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T2"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U2"))));
+}
+
+TEST(TemplateTypeParmDecl, EnumDecl) {
+  const char input[] =
+      "template<typename T>\n"
+      "struct Struct {\n"
+      "  enum class Enum : T;\n"
+      "};\n"
+      "template<typename U>\n"
+      "enum class Struct<U>::Enum : U {\n"
+      "  e1,\n"
+      "  e2\n"
+      "};\n";
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
+TEST(TemplateTypeParmDecl, RecordDecl) {
+  const char input[] =
+      "template<typename T>\n"
+      "class Class {\n"
+      "  struct Struct;\n"
+      "};\n"
+      "template<typename U>\n"
+      "struct Class<U>::Struct {\n"
+      "  U field;\n"
+      "};\n";
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("T"))));
+  EXPECT_TRUE(matches(input, templateTypeParmDecl(hasName("U"))));
+}
+
 TEST(RefersToIntegralType, Matches) {
   EXPECT_TRUE(matches("template<int T> struct C {}; C<42> c;",
                       classTemplateSpecializationDecl(




More information about the cfe-commits mailing list