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);