A clean-up pass, exploring the unification of traversals of class, variable and function templates.
llvm-svn: 189152
This commit is contained in:
parent
d07c6f06eb
commit
30616383ab
|
@ -407,9 +407,12 @@ public:
|
|||
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 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
|
|||
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 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
|
|||
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 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, {
|
|||
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 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
|
|||
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 @@ DEF_TRAVERSE_DECL(VarDecl, {
|
|||
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));
|
||||
})
|
||||
|
|
|
@ -984,8 +984,8 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
|
|||
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) {
|
||||
|
|
|
@ -2541,7 +2541,9 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
|
|||
// 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 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
|
|||
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 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
|
|||
}
|
||||
}
|
||||
|
||||
// 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().
|
||||
|
|
|
@ -2288,7 +2288,11 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
|
|||
|
||||
/// 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 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
|
|||
/// \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 @@ Sema::getMoreSpecializedPartialSpecialization(
|
|||
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,
|
||||
|
|
|
@ -1440,6 +1440,9 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue