A clean-up pass, exploring the unification of traversals of class, variable and function templates.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189152 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index aaa2612..b09b336 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -407,9 +407,12 @@
 private:
   // These are helper methods used by more than one Traverse* method.
   bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
-  bool TraverseClassInstantiations(ClassTemplateDecl *D);
-  bool TraverseVariableInstantiations(VarTemplateDecl *D);
-  bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ;
+#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND)                                   \
+  bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D);
+  DEF_TRAVERSE_TMPL_INST(Class)
+  DEF_TRAVERSE_TMPL_INST(Var)
+  DEF_TRAVERSE_TMPL_INST(Function)
+#undef DEF_TRAVERSE_TMPL_INST
   bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
                                           unsigned Count);
   bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
@@ -1452,110 +1455,44 @@
   return true;
 }
 
-// A helper method for traversing the implicit instantiations of a
-// class template.
-template<typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
-    ClassTemplateDecl *D) {
-  ClassTemplateDecl::spec_iterator end = D->spec_end();
-  for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
-    ClassTemplateSpecializationDecl* SD = *it;
-
-    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;
+#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) {                                         \
+  TMPLDECLKIND##TemplateDecl::spec_iterator end = D->spec_end();             \
+  for (TMPLDECLKIND##TemplateDecl::spec_iterator it = D->spec_begin();       \
+       it != end; ++it) {                                                    \
+    TMPLDECLKIND##TemplateSpecializationDecl* SD = *it;                      \
+                                                                             \
+    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;                                                               \
 }
-
-DEF_TRAVERSE_DECL(ClassTemplateDecl, {
-    CXXRecordDecl* TempDecl = D->getTemplatedDecl();
-    TRY_TO(TraverseDecl(TempDecl));
-    TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
-    // By default, we do not traverse the instantiations of
-    // class templates since they do not appear in the user code. The
-    // following code optionally traverses them.
-    //
-    // We only traverse the class instantiations when we see the canonical
-    // declaration of the template, to ensure we only visit them once.
-    if (getDerived().shouldVisitTemplateInstantiations() &&
-        D == D->getCanonicalDecl())
-      TRY_TO(TraverseClassInstantiations(D));
-
-    // Note that getInstantiatedFromMemberTemplate() is just a link
-    // from a template instantiation back to the template from which
-    // it was instantiated, and thus should not be traversed.
-  })
-
-// A helper method for traversing the implicit instantiations of a
-// variable template.
-template <typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseVariableInstantiations(
-    VarTemplateDecl *D) {
-  VarTemplateDecl::spec_iterator end = D->spec_end();
-  for (VarTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
-    VarTemplateSpecializationDecl *SD = *it;
-
-    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;
-}
-
-  // FIXME: Unify traversal for variable templates, class templates and function
-  // templates.
-DEF_TRAVERSE_DECL(VarTemplateDecl, {
-  VarDecl *TempDecl = D->getTemplatedDecl();
-  TRY_TO(TraverseDecl(TempDecl));
-  TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
-  // By default, we do not traverse the instantiations of
-  // class templates since they do not appear in the user code. The
-  // following code optionally traverses them.
-  //
-  // We only traverse the class instantiations when we see the canonical
-  // declaration of the template, to ensure we only visit them once.
-  if (getDerived().shouldVisitTemplateInstantiations() &&
-      D == D->getCanonicalDecl())
-    TRY_TO(TraverseVariableInstantiations(D));
-
-      // Note that getInstantiatedFromMemberTemplate() is just a link
-      // from a template instantiation back to the template from which
-      // it was instantiated, and thus should not be traversed.
-})
+   
+DEF_TRAVERSE_TMPL_INST(Class)
+DEF_TRAVERSE_TMPL_INST(Var)
 
 // A helper method for traversing the instantiations of a
 // function while skipping its specializations.
 template<typename Derived>
-bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
+bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
     FunctionTemplateDecl *D) {
   FunctionTemplateDecl::spec_iterator end = D->spec_end();
   for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end;
@@ -1583,21 +1520,32 @@
   return true;
 }
 
-DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
-    TRY_TO(TraverseDecl(D->getTemplatedDecl()));
-    TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
-
-    // By default, we do not traverse the instantiations of
-    // function templates since they do not appear in the user code. The
-    // following code optionally traverses them.
-    //
-    // We only traverse the function instantiations when we see the canonical
-    // declaration of the template, to ensure we only visit them once.
-    if (getDerived().shouldVisitTemplateInstantiations() &&
-        D == D->getCanonicalDecl())
-      TRY_TO(TraverseFunctionInstantiations(D));
+// This macro unifies the traversal of class, variable and function
+// template declarations.
+#define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND)                                 \
+DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, {                              \
+    TRY_TO(TraverseDecl(D->getTemplatedDecl()));                             \
+    TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \
+                                                                             \
+    /* By default, we do not traverse the instantiations of
+       class templates since they do not appear in the user code. The
+       following code optionally traverses them.
+       
+       We only traverse the class instantiations when we see the canonical
+       declaration of the template, to ensure we only visit them once. */    \
+    if (getDerived().shouldVisitTemplateInstantiations() &&                  \
+        D == D->getCanonicalDecl())                                          \
+      TRY_TO(TraverseTemplateInstantiations(D));                             \
+                                                                             \
+    /* Note that getInstantiatedFromMemberTemplate() is just a link
+       from a template instantiation back to the template from which
+       it was instantiated, and thus should not be traversed. */             \
   })
 
+DEF_TRAVERSE_TMPL_DECL(Class)
+DEF_TRAVERSE_TMPL_DECL(Var)
+DEF_TRAVERSE_TMPL_DECL(Function)
+
 DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
     // D is the "T" in something like
     //   template <template <typename> class T> class container { };
@@ -1690,27 +1638,31 @@
     TRY_TO(TraverseCXXRecordHelper(D));
   })
 
-DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
-    // For implicit instantiations ("set<int> x;"), we don't want to
-    // recurse at all, since the instatiated class isn't written in
-    // the source code anywhere.  (Note the instatiated *type* --
-    // set<int> -- is written, and will still get a callback of
-    // TemplateSpecializationType).  For explicit instantiations
-    // ("template set<int>;"), we do need a callback, since this
-    // is the only callback that's made for this instantiation.
-    // We use getTypeAsWritten() to distinguish.
-    if (TypeSourceInfo *TSI = D->getTypeAsWritten())
-      TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
-
-    if (!getDerived().shouldVisitTemplateInstantiations() &&
-        D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
-      // Returning from here skips traversing the
-      // declaration context of the ClassTemplateSpecializationDecl
-      // (embedded in the DEF_TRAVERSE_DECL() macro)
-      // which contains the instantiated members of the class.
-      return true;
+#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \
+DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, {                \
+    /* For implicit instantiations ("set<int> x;"), we don't want to
+       recurse at all, since the instatiated template isn't written in
+       the source code anywhere.  (Note the instatiated *type* --
+       set<int> -- is written, and will still get a callback of
+       TemplateSpecializationType).  For explicit instantiations
+       ("template set<int>;"), we do need a callback, since this
+       is the only callback that's made for this instantiation.
+       We use getTypeAsWritten() to distinguish. */                          \
+    if (TypeSourceInfo *TSI = D->getTypeAsWritten())                         \
+      TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));                            \
+                                                                             \
+    if (!getDerived().shouldVisitTemplateInstantiations() &&                 \
+        D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)    \
+      /* Returning from here skips traversing the
+         declaration context of the *TemplateSpecializationDecl
+         (embedded in the DEF_TRAVERSE_DECL() macro)
+         which contains the instantiated members of the template. */         \
+      return true;                                                           \
   })
 
+DEF_TRAVERSE_TMPL_SPEC_DECL(Class)
+DEF_TRAVERSE_TMPL_SPEC_DECL(Var)
+
 template <typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
     const TemplateArgumentLoc *TAL, unsigned Count) {
@@ -1720,27 +1672,31 @@
   return true;
 }
 
-DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
-    // The partial specialization.
-    if (TemplateParameterList *TPL = D->getTemplateParameters()) {
-      for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
-           I != E; ++I) {
-        TRY_TO(TraverseDecl(*I));
-      }
-    }
-    // The args that remains unspecialized.
-    TRY_TO(TraverseTemplateArgumentLocsHelper(
-                      D->getTemplateArgsAsWritten()->getTemplateArgs(),
-                      D->getTemplateArgsAsWritten()->NumTemplateArgs));
-
-    // Don't need the ClassTemplatePartialSpecializationHelper, even
-    // though that's our parent class -- we already visit all the
-    // template args here.
-    TRY_TO(TraverseCXXRecordHelper(D));
-
-    // Instantiations will have been visited with the primary template.
+#define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \
+DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, {         \
+    /* The partial specialization. */                                        \
+    if (TemplateParameterList *TPL = D->getTemplateParameters()) {           \
+      for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \
+           I != E; ++I) {                                                    \
+        TRY_TO(TraverseDecl(*I));                                            \
+      }                                                                      \
+    }                                                                        \
+    /* The args that remains unspecialized. */                               \
+    TRY_TO(TraverseTemplateArgumentLocsHelper(                               \
+                      D->getTemplateArgsAsWritten()->getTemplateArgs(),      \
+                      D->getTemplateArgsAsWritten()->NumTemplateArgs));      \
+                                                                             \
+    /* Don't need the *TemplatePartialSpecializationHelper, even
+       though that's our parent class -- we already visit all the
+       template args here. */                                                \
+    TRY_TO(Traverse##DECLKIND##Helper(D));                                   \
+                                                                             \
+    /* Instantiations will have been visited with the primary template. */   \
   })
 
+DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord)
+DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var)
+
 DEF_TRAVERSE_DECL(EnumConstantDecl, {
     TRY_TO(TraverseStmt(D->getInitExpr()));
   })
@@ -1883,43 +1839,6 @@
     TRY_TO(TraverseVarHelper(D));
   })
 
-DEF_TRAVERSE_DECL(VarTemplateSpecializationDecl, {
-  // For implicit instantiations, we don't want to
-  // recurse at all, since the instatiated class isn't written in
-  // the source code anywhere.
-  if (TypeSourceInfo *TSI = D->getTypeAsWritten())
-    TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
-
-  if (!getDerived().shouldVisitTemplateInstantiations() &&
-      D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
-    // Returning from here skips traversing the
-    // declaration context of the VarTemplateSpecializationDecl
-    // (embedded in the DEF_TRAVERSE_DECL() macro).
-    return true;
-})
-
-DEF_TRAVERSE_DECL(VarTemplatePartialSpecializationDecl, {
-  // The partial specialization.
-  if (TemplateParameterList *TPL = D->getTemplateParameters()) {
-    for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
-         I != E; ++I) {
-      TRY_TO(TraverseDecl(*I));
-    }
-  }
-  // The args that remain unspecialized.
-  TRY_TO(TraverseTemplateArgumentLocsHelper(
-                      D->getTemplateArgsAsWritten()->getTemplateArgs(),
-                      D->getTemplateArgsAsWritten()->NumTemplateArgs));
-
-  // Don't need the VarTemplatePartialSpecializationHelper, even
-  // though that's our parent class -- we already visit all the
-  // template args here.
-  TRY_TO(TraverseVarHelper(D));
-
-                    // Instantiations will have been visited with the primary
-                    // template.
-})
-
 DEF_TRAVERSE_DECL(ImplicitParamDecl, {
     TRY_TO(TraverseVarHelper(D));
   })
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 52e35c6..94f05e9 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -984,8 +984,8 @@
   return new (Mem) VarTemplateDecl(EmptyShell());
 }
 
-// FIXME: Should this be unified accross class, function and variable
-// templates? Perhaps also moved to RedeclarableTemplateDecl?
+// TODO: Unify accross class, function and variable templates?
+//       May require moving this and Common to RedeclarableTemplateDecl.
 void VarTemplateDecl::LoadLazySpecializations() const {
   Common *CommonPtr = getCommonPtr();
   if (CommonPtr->LazySpecializations) {
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 096d938..8170fb9 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2541,7 +2541,9 @@
   // a placeholder for an incomplete declarative context; which must be
   // complete by instantiation time. Thus, do not search through the partial
   // specializations yet.
-  // FIXME: Unify with InstantiateClassTemplateSpecialization()?
+  // TODO: Unify with InstantiateClassTemplateSpecialization()?
+  //       Perhaps better after unification of DeduceTemplateArguments() and
+  //       getMoreSpecializedPartialSpecialization().
   bool InstantiationDependent = false;
   if (!TemplateSpecializationType::anyDependentTemplateArguments(
           TemplateArgs, InstantiationDependent)) {
@@ -2556,6 +2558,7 @@
       if (TemplateDeductionResult Result =
               DeduceTemplateArguments(Partial, TemplateArgList, Info)) {
         // Store the failed-deduction information for use in diagnostics, later.
+        // TODO: Actually use the failed-deduction info?
         FailedCandidates.addCandidate()
             .set(Partial, MakeDeductionFailureInfo(Context, Result, Info));
         (void)Result;
@@ -2618,8 +2621,6 @@
     }
   }
 
-  // FIXME: Actually use FailedCandidates.
-
   // 2. Create the canonical declaration.
   // Note that we do not instantiate the variable just yet, since
   // instantiation is handled in DoMarkVarDeclReferenced().
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index a5878bc..47d8e16 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2288,7 +2288,11 @@
 
 /// Complete template argument deduction for a variable template partial
 /// specialization.
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version.
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
+///       May require unifying ClassTemplate(Partial)SpecializationDecl and
+///        VarTemplate(Partial)SpecializationDecl with a new data
+///        structure Template(Partial)SpecializationDecl, and
+///        using Template(Partial)SpecializationDecl as input type.
 static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
     Sema &S, VarTemplatePartialSpecializationDecl *Partial,
     const TemplateArgumentList &TemplateArgs,
@@ -2404,7 +2408,11 @@
 /// \brief Perform template argument deduction to determine whether
 /// the given template arguments match the given variable template
 /// partial specialization per C++ [temp.class.spec.match].
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version.
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
+///       May require unifying ClassTemplate(Partial)SpecializationDecl and
+///        VarTemplate(Partial)SpecializationDecl with a new data
+///        structure Template(Partial)SpecializationDecl, and
+///        using Template(Partial)SpecializationDecl as input type.
 Sema::TemplateDeductionResult
 Sema::DeduceTemplateArguments(VarTemplatePartialSpecializationDecl *Partial,
                               const TemplateArgumentList &TemplateArgs,
@@ -4458,7 +4466,11 @@
   return Better1 ? PS1 : PS2;
 }
 
-/// TODO: Unify with ClassTemplatePartialSpecializationDecl version.
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
+///       May require unifying ClassTemplate(Partial)SpecializationDecl and
+///        VarTemplate(Partial)SpecializationDecl with a new data
+///        structure Template(Partial)SpecializationDecl, and
+///        using Template(Partial)SpecializationDecl as input type.
 VarTemplatePartialSpecializationDecl *
 Sema::getMoreSpecializedPartialSpecialization(
     VarTemplatePartialSpecializationDecl *PS1,
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index b1fe8c6..3c93340 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1440,6 +1440,9 @@
   }
 }
 
+/// TODO: Unify with ClassTemplateDecl version?
+///       May require unifying ClassTemplateDecl and
+///        VarTemplateDecl beyond TemplateDecl...
 void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) {
   RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
 
@@ -1574,6 +1577,11 @@
   }
 }
 
+/// TODO: Unify with ClassTemplateSpecializationDecl version?
+///       May require unifying ClassTemplate(Partial)SpecializationDecl and
+///        VarTemplate(Partial)SpecializationDecl with a new data
+///        structure Template(Partial)SpecializationDecl, and
+///        using Template(Partial)SpecializationDecl as input type.
 ASTDeclReader::RedeclarableResult
 ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
     VarTemplateSpecializationDecl *D) {
@@ -1632,6 +1640,11 @@
   return Redecl;
 }
 
+/// TODO: Unify with ClassTemplatePartialSpecializationDecl version?
+///       May require unifying ClassTemplate(Partial)SpecializationDecl and
+///        VarTemplate(Partial)SpecializationDecl with a new data
+///        structure Template(Partial)SpecializationDecl, and
+///        using Template(Partial)SpecializationDecl as input type.
 void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
     VarTemplatePartialSpecializationDecl *D) {
   RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);