r204175 - In the presence of modules, we can have multiple implicit instantiations of the same template. Teach RecursiveASTVisitor to visit all of those, not just one of them. This is difficult to test by itself, but will be covered by an upcoming change.

Richard Smith richard-llvm at metafoo.co.uk
Tue Mar 18 13:31:35 PDT 2014


Author: rsmith
Date: Tue Mar 18 15:31:31 2014
New Revision: 204175

URL: http://llvm.org/viewvc/llvm-project?rev=204175&view=rev
Log:
In the presence of modules, we can have multiple implicit instantiations of the same template. Teach RecursiveASTVisitor to visit all of those, not just one of them. This is difficult to test by itself, but will be covered by an upcoming change.

Modified:
    cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h

Modified: cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=204175&r1=204174&r2=204175&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h Tue Mar 18 15:31:31 2014
@@ -1407,20 +1407,27 @@ template<typename Derived>
 bool DataRecursiveASTVisitor<Derived>::TraverseClassInstantiations(
     ClassTemplateDecl *D) {
   for (auto *SD : D->specializations()) {
-    switch (SD->getSpecializationKind()) {
-    // Visit the implicit instantiations with the requested pattern.
-    case TSK_Undeclared:
-    case TSK_ImplicitInstantiation:
-      TRY_TO(TraverseDecl(SD));
-      break;
-
-    // We don't need to do anything on an explicit instantiation
-    // or explicit specialization because there will be an explicit
-    // node for it elsewhere.
-    case TSK_ExplicitInstantiationDeclaration:
-    case TSK_ExplicitInstantiationDefinition:
-    case TSK_ExplicitSpecialization:
-      break;
+    for (auto *RD : SD->redecls()) {
+      // We don't want to visit injected-class-names in this traversal.
+      if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
+        continue;
+
+      switch (cast<ClassTemplateSpecializationDecl>(RD)->
+                  getSpecializationKind()) {
+      // Visit the implicit instantiations with the requested pattern.
+      case TSK_Undeclared:
+      case TSK_ImplicitInstantiation:
+        TRY_TO(TraverseDecl(RD));
+        break;
+
+      // We don't need to do anything on an explicit instantiation
+      // or explicit specialization because there will be an explicit
+      // node for it elsewhere.
+      case TSK_ExplicitInstantiationDeclaration:
+      case TSK_ExplicitInstantiationDefinition:
+      case TSK_ExplicitSpecialization:
+        break;
+      }
     }
   }
 
@@ -1453,20 +1460,23 @@ template <typename Derived>
 bool DataRecursiveASTVisitor<Derived>::TraverseVariableInstantiations(
     VarTemplateDecl *D) {
   for (auto *SD : D->specializations()) {
-    switch (SD->getSpecializationKind()) {
-    // Visit the implicit instantiations with the requested pattern.
-    case TSK_Undeclared:
-    case TSK_ImplicitInstantiation:
-      TRY_TO(TraverseDecl(SD));
-      break;
-
-    // We don't need to do anything on an explicit instantiation
-    // or explicit specialization because there will be an explicit
-    // node for it elsewhere.
-    case TSK_ExplicitInstantiationDeclaration:
-    case TSK_ExplicitInstantiationDefinition:
-    case TSK_ExplicitSpecialization:
-      break;
+    for (auto *RD : SD->redecls()) {
+      switch (cast<VarTemplateSpecializationDecl>(RD)->
+                  getSpecializationKind()) {
+      // Visit the implicit instantiations with the requested pattern.
+      case TSK_Undeclared:
+      case TSK_ImplicitInstantiation:
+        TRY_TO(TraverseDecl(RD));
+        break;
+
+      // We don't need to do anything on an explicit instantiation
+      // or explicit specialization because there will be an explicit
+      // node for it elsewhere.
+      case TSK_ExplicitInstantiationDeclaration:
+      case TSK_ExplicitInstantiationDefinition:
+      case TSK_ExplicitSpecialization:
+        break;
+      }
     }
   }
 
@@ -1501,21 +1511,25 @@ template<typename Derived>
 bool DataRecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
     FunctionTemplateDecl *D) {
   for (auto *FD : D->specializations()) {
-    switch (FD->getTemplateSpecializationKind()) {
-    case TSK_Undeclared:
-    case TSK_ImplicitInstantiation:
-      // We don't know what kind of FunctionDecl this is.
-      TRY_TO(TraverseDecl(FD));
-      break;
-
-    // No need to visit explicit instantiations, we'll find the node
-    // eventually.
-    case TSK_ExplicitInstantiationDeclaration:
-    case TSK_ExplicitInstantiationDefinition:
-      break;
-
-    case TSK_ExplicitSpecialization:
-      break;
+    for (auto *RD : FD->redecls()) {
+      switch (RD->getTemplateSpecializationKind()) {
+      case TSK_Undeclared:
+      case TSK_ImplicitInstantiation:
+        // We don't know what kind of FunctionDecl this is.
+        TRY_TO(TraverseDecl(RD));
+        break;
+
+      // No need to visit explicit instantiations, we'll find the node
+      // eventually.
+      // FIXME: This is incorrect; there is no other node for an explicit
+      // instantiation of a function template specialization.
+      case TSK_ExplicitInstantiationDeclaration:
+      case TSK_ExplicitInstantiationDefinition:
+        break;
+
+      case TSK_ExplicitSpecialization:
+        break;
+      }
     }
   }
 

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=204175&r1=204174&r2=204175&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Mar 18 15:31:31 2014
@@ -1488,35 +1488,59 @@ bool RecursiveASTVisitor<Derived>::Trave
   return true;
 }
 
-#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND)                                 \
-/* A helper method for traversing the implicit instantiations of a
-   class or variable template. */                                            \
-template<typename Derived>                                                   \
-bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(           \
-    TMPLDECLKIND##TemplateDecl *D) {                                         \
-  for (auto *SD : D->specializations()) {                                    \
-    switch (SD->getSpecializationKind()) {                                   \
-    /* Visit the implicit instantiations with the requested pattern. */      \
-    case TSK_Undeclared:                                                     \
-    case TSK_ImplicitInstantiation:                                          \
-      TRY_TO(TraverseDecl(SD));                                              \
-      break;                                                                 \
-                                                                             \
-    /* We don't need to do anything on an explicit instantiation             
-       or explicit specialization because there will be an explicit
-       node for it elsewhere. */                                             \
-    case TSK_ExplicitInstantiationDeclaration:                               \
-    case TSK_ExplicitInstantiationDefinition:                                \
-    case TSK_ExplicitSpecialization:                                         \
-      break;                                                                 \
-    }                                                                        \
-  }                                                                          \
-                                                                             \
-  return true;                                                               \
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
+    ClassTemplateDecl *D) {
+  for (auto *SD : D->specializations()) {
+    for (auto *RD : SD->redecls()) {
+      // We don't want to visit injected-class-names in this traversal.
+      if (cast<CXXRecordDecl>(RD)->isInjectedClassName())
+        continue;
+
+      switch (cast<ClassTemplateSpecializationDecl>(RD)->
+                  getSpecializationKind()) {
+      // Visit the implicit instantiations with the requested pattern.
+      case TSK_Undeclared:
+      case TSK_ImplicitInstantiation:
+        TRY_TO(TraverseDecl(RD));
+        break;
+
+      // We don't need to do anything on an explicit instantiation
+      // or explicit specialization because there will be an explicit
+      // node for it elsewhere.
+      case TSK_ExplicitInstantiationDeclaration:
+      case TSK_ExplicitInstantiationDefinition:
+      case TSK_ExplicitSpecialization:
+        break;
+      }
+    }
+  }
+
+  return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
+    VarTemplateDecl *D) {
+  for (auto *SD : D->specializations()) {
+    for (auto *RD : SD->redecls()) {
+      switch (cast<VarTemplateSpecializationDecl>(RD)->
+                  getSpecializationKind()) {
+      case TSK_Undeclared:
+      case TSK_ImplicitInstantiation:
+        TRY_TO(TraverseDecl(RD));
+        break;
+
+      case TSK_ExplicitInstantiationDeclaration:
+      case TSK_ExplicitInstantiationDefinition:
+      case TSK_ExplicitSpecialization:
+        break;
+      }
+    }
+  }
+
+  return true;
 }
-   
-DEF_TRAVERSE_TMPL_INST(Class)
-DEF_TRAVERSE_TMPL_INST(Var)
 
 // A helper method for traversing the instantiations of a
 // function while skipping its specializations.
@@ -1524,22 +1548,24 @@ template<typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
     FunctionTemplateDecl *D) {
   for (auto *FD : D->specializations()) {
-    switch (FD->getTemplateSpecializationKind()) {
-    case TSK_Undeclared:
-    case TSK_ImplicitInstantiation:
-      // We don't know what kind of FunctionDecl this is.
-      TRY_TO(TraverseDecl(FD));
-      break;
-
-    // FIXME: For now traverse explicit instantiations here. Change that
-    // once they are represented as dedicated nodes in the AST.
-    case TSK_ExplicitInstantiationDeclaration:
-    case TSK_ExplicitInstantiationDefinition:
-      TRY_TO(TraverseDecl(FD));
-      break;
+    for (auto *RD : FD->redecls()) {
+      switch (RD->getTemplateSpecializationKind()) {
+      case TSK_Undeclared:
+      case TSK_ImplicitInstantiation:
+        // We don't know what kind of FunctionDecl this is.
+        TRY_TO(TraverseDecl(RD));
+        break;
+
+      // FIXME: For now traverse explicit instantiations here. Change that
+      // once they are represented as dedicated nodes in the AST.
+      case TSK_ExplicitInstantiationDeclaration:
+      case TSK_ExplicitInstantiationDefinition:
+        TRY_TO(TraverseDecl(RD));
+        break;
 
-    case TSK_ExplicitSpecialization:
-      break;
+      case TSK_ExplicitSpecialization:
+        break;
+      }
     }
   }
 





More information about the cfe-commits mailing list