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

llvm-svn: 189152
This commit is contained in:
Larisse Voufo 2013-08-23 22:21:36 +00:00
parent d07c6f06eb
commit 30616383ab
5 changed files with 143 additions and 198 deletions

View File

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

View File

@ -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) {

View File

@ -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().

View File

@ -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,

View File

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