forked from OSchip/llvm-project
Implement template instantiation for member class templates.
When performing template instantiation of the definitions of member templates (or members thereof), we build a data structure containing the template arguments from each "level" of template instantiation. During template instantiation, we substitute all levels of template arguments simultaneously. llvm-svn: 80389
This commit is contained in:
parent
d65d22a0c5
commit
01afeeff1d
|
@ -2903,29 +2903,28 @@ public:
|
||||||
|
|
||||||
void PerformPendingImplicitInstantiations();
|
void PerformPendingImplicitInstantiations();
|
||||||
|
|
||||||
QualType SubstType(QualType T, const TemplateArgumentList &TemplateArgs,
|
QualType SubstType(QualType T,
|
||||||
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||||
SourceLocation Loc, DeclarationName Entity);
|
SourceLocation Loc, DeclarationName Entity);
|
||||||
|
|
||||||
OwningExprResult SubstExpr(Expr *E, const TemplateArgumentList &TemplateArgs);
|
OwningExprResult SubstExpr(Expr *E,
|
||||||
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
|
|
||||||
OwningStmtResult SubstStmt(Stmt *S, const TemplateArgumentList &TemplateArgs);
|
OwningStmtResult SubstStmt(Stmt *S,
|
||||||
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
|
|
||||||
Decl *SubstDecl(Decl *D, DeclContext *Owner,
|
Decl *SubstDecl(Decl *D, DeclContext *Owner,
|
||||||
const TemplateArgumentList &TemplateArgs);
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
|
SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
|
||||||
CXXRecordDecl *Pattern,
|
CXXRecordDecl *Pattern,
|
||||||
const TemplateArgumentList &TemplateArgs);
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
|
|
||||||
bool
|
|
||||||
InstantiateTemplatePattern(SourceLocation PointOfInstantiation,
|
|
||||||
CXXRecordDecl *Pattern);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
InstantiateClass(SourceLocation PointOfInstantiation,
|
InstantiateClass(SourceLocation PointOfInstantiation,
|
||||||
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
|
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
|
||||||
const TemplateArgumentList &TemplateArgs,
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||||
bool ExplicitInstantiation,
|
bool ExplicitInstantiation,
|
||||||
bool Complain = true);
|
bool Complain = true);
|
||||||
|
|
||||||
|
@ -2936,7 +2935,7 @@ public:
|
||||||
|
|
||||||
void InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
void InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
||||||
CXXRecordDecl *Instantiation,
|
CXXRecordDecl *Instantiation,
|
||||||
const TemplateArgumentList &TemplateArgs);
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
|
|
||||||
void InstantiateClassTemplateSpecializationMembers(
|
void InstantiateClassTemplateSpecializationMembers(
|
||||||
SourceLocation PointOfInstantiation,
|
SourceLocation PointOfInstantiation,
|
||||||
|
@ -2945,13 +2944,13 @@ public:
|
||||||
NestedNameSpecifier *
|
NestedNameSpecifier *
|
||||||
SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
|
SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
|
||||||
SourceRange Range,
|
SourceRange Range,
|
||||||
const TemplateArgumentList &TemplateArgs);
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
|
|
||||||
TemplateName
|
TemplateName
|
||||||
SubstTemplateName(TemplateName Name, SourceLocation Loc,
|
SubstTemplateName(TemplateName Name, SourceLocation Loc,
|
||||||
const TemplateArgumentList &TemplateArgs);
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
TemplateArgument Subst(TemplateArgument Arg,
|
TemplateArgument Subst(TemplateArgument Arg,
|
||||||
const TemplateArgumentList &TemplateArgs);
|
const MultiLevelTemplateArgumentList &TemplateArgs);
|
||||||
|
|
||||||
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||||
FunctionDecl *Function,
|
FunctionDecl *Function,
|
||||||
|
|
|
@ -2473,14 +2473,14 @@ Sema::OwningExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
|
||||||
Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
|
Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
|
||||||
|
|
||||||
// Instantiate the expression.
|
// Instantiate the expression.
|
||||||
const TemplateArgumentList &ArgList = getTemplateInstantiationArgs(FD);
|
MultiLevelTemplateArgumentList ArgList = getTemplateInstantiationArgs(FD);
|
||||||
|
|
||||||
// FIXME: We should really make a new InstantiatingTemplate ctor
|
// FIXME: We should really make a new InstantiatingTemplate ctor
|
||||||
// that has a better message - right now we're just piggy-backing
|
// that has a better message - right now we're just piggy-backing
|
||||||
// off the "default template argument" error message.
|
// off the "default template argument" error message.
|
||||||
InstantiatingTemplate Inst(*this, CallLoc, FD->getPrimaryTemplate(),
|
InstantiatingTemplate Inst(*this, CallLoc, FD->getPrimaryTemplate(),
|
||||||
ArgList.getFlatArgumentList(),
|
ArgList.getInnermost().getFlatArgumentList(),
|
||||||
ArgList.flat_size());
|
ArgList.getInnermost().flat_size());
|
||||||
|
|
||||||
OwningExprResult Result = SubstExpr(UninstExpr, ArgList);
|
OwningExprResult Result = SubstExpr(UninstExpr, ArgList);
|
||||||
if (Result.isInvalid())
|
if (Result.isInvalid())
|
||||||
|
|
|
@ -1243,7 +1243,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
||||||
|
|
||||||
TemplateArgumentList TemplateArgs(Context, Converted,
|
TemplateArgumentList TemplateArgs(Context, Converted,
|
||||||
/*TakeArgs=*/false);
|
/*TakeArgs=*/false);
|
||||||
ArgType = SubstType(ArgType, TemplateArgs,
|
ArgType = SubstType(ArgType,
|
||||||
|
MultiLevelTemplateArgumentList(TemplateArgs),
|
||||||
TTP->getDefaultArgumentLoc(),
|
TTP->getDefaultArgumentLoc(),
|
||||||
TTP->getDeclName());
|
TTP->getDeclName());
|
||||||
}
|
}
|
||||||
|
@ -1265,8 +1266,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
|
||||||
TemplateArgumentList TemplateArgs(Context, Converted,
|
TemplateArgumentList TemplateArgs(Context, Converted,
|
||||||
/*TakeArgs=*/false);
|
/*TakeArgs=*/false);
|
||||||
|
|
||||||
Sema::OwningExprResult E = SubstExpr(NTTP->getDefaultArgument(),
|
Sema::OwningExprResult E
|
||||||
TemplateArgs);
|
= SubstExpr(NTTP->getDefaultArgument(),
|
||||||
|
MultiLevelTemplateArgumentList(TemplateArgs));
|
||||||
if (E.isInvalid())
|
if (E.isInvalid())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,8 @@ namespace clang {
|
||||||
MultiLevelTemplateArgumentList() { }
|
MultiLevelTemplateArgumentList() { }
|
||||||
|
|
||||||
/// \brief Construct a single-level template argument list.
|
/// \brief Construct a single-level template argument list.
|
||||||
MultiLevelTemplateArgumentList(const TemplateArgumentList *TemplateArgs) {
|
MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
|
||||||
TemplateArgumentLists.push_back(TemplateArgs);
|
TemplateArgumentLists.push_back(&TemplateArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Determine the number of levels in this template argument
|
/// \brief Determine the number of levels in this template argument
|
||||||
|
@ -57,8 +57,21 @@ namespace clang {
|
||||||
/// \brief Retrieve the template argument at a given depth and index.
|
/// \brief Retrieve the template argument at a given depth and index.
|
||||||
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
|
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
|
||||||
assert(Depth < TemplateArgumentLists.size());
|
assert(Depth < TemplateArgumentLists.size());
|
||||||
assert(Index < TemplateArgumentLists[getNumLevels() - Depth]->size());
|
assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1]->size());
|
||||||
return TemplateArgumentLists[getNumLevels() - Depth]->get(Index);
|
return TemplateArgumentLists[getNumLevels() - Depth - 1]->get(Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Determine whether there is a non-NULL template argument at the
|
||||||
|
/// given depth and index.
|
||||||
|
///
|
||||||
|
/// There must exist a template argument list at the given depth.
|
||||||
|
bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
|
||||||
|
assert(Depth < TemplateArgumentLists.size());
|
||||||
|
|
||||||
|
if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1]->size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !(*this)(Depth, Index).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Add a new outermost level to the multi-level template argument
|
/// \brief Add a new outermost level to the multi-level template argument
|
||||||
|
@ -67,6 +80,11 @@ namespace clang {
|
||||||
TemplateArgumentLists.push_back(TemplateArgs);
|
TemplateArgumentLists.push_back(TemplateArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the innermost template argument list.
|
||||||
|
const TemplateArgumentList &getInnermost() const {
|
||||||
|
return *TemplateArgumentLists.front();
|
||||||
|
}
|
||||||
|
|
||||||
// Implicit conversion to a single template argument list, to facilitate a
|
// Implicit conversion to a single template argument list, to facilitate a
|
||||||
// gradual transition to MultiLevelTemplateArgumentLists.
|
// gradual transition to MultiLevelTemplateArgumentLists.
|
||||||
operator const TemplateArgumentList &() const {
|
operator const TemplateArgumentList &() const {
|
||||||
|
|
|
@ -26,8 +26,8 @@ using namespace clang;
|
||||||
// Template Instantiation Support
|
// Template Instantiation Support
|
||||||
//===----------------------------------------------------------------------===/
|
//===----------------------------------------------------------------------===/
|
||||||
|
|
||||||
/// \brief Retrieve the template argument list that should be used to
|
/// \brief Retrieve the template argument list(s) that should be used to
|
||||||
/// instantiate the given declaration.
|
/// instantiate the definition of the given declaration.
|
||||||
MultiLevelTemplateArgumentList
|
MultiLevelTemplateArgumentList
|
||||||
Sema::getTemplateInstantiationArgs(NamedDecl *D) {
|
Sema::getTemplateInstantiationArgs(NamedDecl *D) {
|
||||||
// Accumulate the set of template argument lists in this structure.
|
// Accumulate the set of template argument lists in this structure.
|
||||||
|
@ -298,7 +298,7 @@ namespace {
|
||||||
class VISIBILITY_HIDDEN TemplateInstantiator
|
class VISIBILITY_HIDDEN TemplateInstantiator
|
||||||
: public TreeTransform<TemplateInstantiator>
|
: public TreeTransform<TemplateInstantiator>
|
||||||
{
|
{
|
||||||
const TemplateArgumentList &TemplateArgs;
|
const MultiLevelTemplateArgumentList &TemplateArgs;
|
||||||
SourceLocation Loc;
|
SourceLocation Loc;
|
||||||
DeclarationName Entity;
|
DeclarationName Entity;
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ namespace {
|
||||||
typedef TreeTransform<TemplateInstantiator> inherited;
|
typedef TreeTransform<TemplateInstantiator> inherited;
|
||||||
|
|
||||||
TemplateInstantiator(Sema &SemaRef,
|
TemplateInstantiator(Sema &SemaRef,
|
||||||
const TemplateArgumentList &TemplateArgs,
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||||
SourceLocation Loc,
|
SourceLocation Loc,
|
||||||
DeclarationName Entity)
|
DeclarationName Entity)
|
||||||
: inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
|
: inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
|
||||||
|
@ -353,15 +353,24 @@ namespace {
|
||||||
Decl *TemplateInstantiator::TransformDecl(Decl *D) {
|
Decl *TemplateInstantiator::TransformDecl(Decl *D) {
|
||||||
if (TemplateTemplateParmDecl *TTP
|
if (TemplateTemplateParmDecl *TTP
|
||||||
= dyn_cast_or_null<TemplateTemplateParmDecl>(D)) {
|
= dyn_cast_or_null<TemplateTemplateParmDecl>(D)) {
|
||||||
// FIXME: Depth reduction
|
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
|
||||||
assert(TTP->getDepth() == 0 &&
|
assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() &&
|
||||||
"Cannot reduce depth of a template template parameter");
|
|
||||||
assert(TemplateArgs[TTP->getPosition()].getAsDecl() &&
|
|
||||||
"Wrong kind of template template argument");
|
"Wrong kind of template template argument");
|
||||||
TemplateDecl *Template
|
return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(),
|
||||||
= dyn_cast<TemplateDecl>(TemplateArgs[TTP->getPosition()].getAsDecl());
|
TTP->getPosition()).getAsDecl());
|
||||||
assert(Template && "Expected a template");
|
}
|
||||||
return Template;
|
|
||||||
|
// If the corresponding template argument is NULL or non-existent, it's
|
||||||
|
// because we are performing instantiation from explicitly-specified
|
||||||
|
// template arguments in a function template, but there were some
|
||||||
|
// arguments left unspecified.
|
||||||
|
if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
|
||||||
|
TTP->getPosition()))
|
||||||
|
return D;
|
||||||
|
|
||||||
|
// FIXME: Implement depth reduction of template template parameters
|
||||||
|
assert(false &&
|
||||||
|
"Reducing depth of template template parameters is not yet implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
return SemaRef.FindInstantiatedDecl(cast_or_null<NamedDecl>(D));
|
return SemaRef.FindInstantiatedDecl(cast_or_null<NamedDecl>(D));
|
||||||
|
@ -395,30 +404,36 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
|
||||||
// FIXME: Clean this up a bit
|
// FIXME: Clean this up a bit
|
||||||
NamedDecl *D = E->getDecl();
|
NamedDecl *D = E->getDecl();
|
||||||
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
||||||
assert(NTTP->getDepth() == 0 && "No nested templates yet");
|
if (NTTP->getDepth() >= TemplateArgs.getNumLevels()) {
|
||||||
|
assert(false && "Cannot reduce non-type template parameter depth yet");
|
||||||
|
return getSema().ExprError();
|
||||||
|
}
|
||||||
|
|
||||||
// If the corresponding template argument is NULL or non-existent, it's
|
// If the corresponding template argument is NULL or non-existent, it's
|
||||||
// because we are performing instantiation from explicitly-specified
|
// because we are performing instantiation from explicitly-specified
|
||||||
// template arguments in a function template, but there were some
|
// template arguments in a function template, but there were some
|
||||||
// arguments left unspecified.
|
// arguments left unspecified.
|
||||||
if (NTTP->getPosition() >= TemplateArgs.size() ||
|
if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
|
||||||
TemplateArgs[NTTP->getPosition()].isNull())
|
NTTP->getPosition()))
|
||||||
return SemaRef.Owned(E); // FIXME: Clone the expression!
|
return SemaRef.Owned(E->Retain());
|
||||||
|
|
||||||
const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()];
|
const TemplateArgument &Arg = TemplateArgs(NTTP->getDepth(),
|
||||||
|
NTTP->getPosition());
|
||||||
|
|
||||||
// The template argument itself might be an expression, in which
|
// The template argument itself might be an expression, in which
|
||||||
// case we just return that expression.
|
// case we just return that expression.
|
||||||
if (Arg.getKind() == TemplateArgument::Expression)
|
if (Arg.getKind() == TemplateArgument::Expression)
|
||||||
// FIXME: Clone the expression!
|
return SemaRef.Owned(Arg.getAsExpr()->Retain());
|
||||||
return SemaRef.Owned(Arg.getAsExpr());
|
|
||||||
|
|
||||||
if (Arg.getKind() == TemplateArgument::Declaration) {
|
if (Arg.getKind() == TemplateArgument::Declaration) {
|
||||||
ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
|
ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl());
|
||||||
|
|
||||||
// FIXME: Can VD ever have a dependent type?
|
VD = cast_or_null<ValueDecl>(getSema().FindInstantiatedDecl(VD));
|
||||||
|
if (!VD)
|
||||||
|
return SemaRef.ExprError();
|
||||||
|
|
||||||
return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
|
return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(),
|
||||||
false, false);
|
/*FIXME:*/false, /*FIXME:*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(Arg.getKind() == TemplateArgument::Integral);
|
assert(Arg.getKind() == TemplateArgument::Integral);
|
||||||
|
@ -464,31 +479,30 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
|
||||||
QualType
|
QualType
|
||||||
TemplateInstantiator::TransformTemplateTypeParmType(
|
TemplateInstantiator::TransformTemplateTypeParmType(
|
||||||
const TemplateTypeParmType *T) {
|
const TemplateTypeParmType *T) {
|
||||||
if (T->getDepth() == 0) {
|
if (T->getDepth() < TemplateArgs.getNumLevels()) {
|
||||||
// Replace the template type parameter with its corresponding
|
// Replace the template type parameter with its corresponding
|
||||||
// template argument.
|
// template argument.
|
||||||
|
|
||||||
// FIXME: When dealing with member templates, we might end up with multiple
|
|
||||||
/// levels of template arguments that we're substituting into concurrently.
|
|
||||||
|
|
||||||
// If the corresponding template argument is NULL or doesn't exist, it's
|
// If the corresponding template argument is NULL or doesn't exist, it's
|
||||||
// because we are performing instantiation from explicitly-specified
|
// because we are performing instantiation from explicitly-specified
|
||||||
// template arguments in a function template class, but there were some
|
// template arguments in a function template class, but there were some
|
||||||
// arguments left unspecified.
|
// arguments left unspecified.
|
||||||
if (T->getIndex() >= TemplateArgs.size() ||
|
if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
|
||||||
TemplateArgs[T->getIndex()].isNull())
|
return QualType(T, 0);
|
||||||
return QualType(T, 0); // Would be nice to keep the original type here
|
|
||||||
|
|
||||||
assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
|
assert(TemplateArgs(T->getDepth(), T->getIndex()).getKind()
|
||||||
|
== TemplateArgument::Type &&
|
||||||
"Template argument kind mismatch");
|
"Template argument kind mismatch");
|
||||||
return TemplateArgs[T->getIndex()].getAsType();
|
|
||||||
|
return TemplateArgs(T->getDepth(), T->getIndex()).getAsType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The template type parameter comes from an inner template (e.g.,
|
// The template type parameter comes from an inner template (e.g.,
|
||||||
// the template parameter list of a member template inside the
|
// the template parameter list of a member template inside the
|
||||||
// template we are instantiating). Create a new template type
|
// template we are instantiating). Create a new template type
|
||||||
// parameter with the template "level" reduced by one.
|
// parameter with the template "level" reduced by one.
|
||||||
return getSema().Context.getTemplateTypeParmType(T->getDepth() - 1,
|
return getSema().Context.getTemplateTypeParmType(
|
||||||
|
T->getDepth() - TemplateArgs.getNumLevels(),
|
||||||
T->getIndex(),
|
T->getIndex(),
|
||||||
T->isParameterPack(),
|
T->isParameterPack(),
|
||||||
T->getName());
|
T->getName());
|
||||||
|
@ -522,7 +536,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(
|
||||||
/// \returns If the instantiation succeeds, the instantiated
|
/// \returns If the instantiation succeeds, the instantiated
|
||||||
/// type. Otherwise, produces diagnostics and returns a NULL type.
|
/// type. Otherwise, produces diagnostics and returns a NULL type.
|
||||||
QualType Sema::SubstType(QualType T,
|
QualType Sema::SubstType(QualType T,
|
||||||
const TemplateArgumentList &TemplateArgs,
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||||
SourceLocation Loc, DeclarationName Entity) {
|
SourceLocation Loc, DeclarationName Entity) {
|
||||||
assert(!ActiveTemplateInstantiations.empty() &&
|
assert(!ActiveTemplateInstantiations.empty() &&
|
||||||
"Cannot perform an instantiation without some context on the "
|
"Cannot perform an instantiation without some context on the "
|
||||||
|
@ -545,7 +559,7 @@ QualType Sema::SubstType(QualType T,
|
||||||
bool
|
bool
|
||||||
Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
|
Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
|
||||||
CXXRecordDecl *Pattern,
|
CXXRecordDecl *Pattern,
|
||||||
const TemplateArgumentList &TemplateArgs) {
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||||
bool Invalid = false;
|
bool Invalid = false;
|
||||||
llvm::SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
|
llvm::SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
|
||||||
for (ClassTemplateSpecializationDecl::base_class_iterator
|
for (ClassTemplateSpecializationDecl::base_class_iterator
|
||||||
|
@ -586,38 +600,6 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
|
||||||
return Invalid;
|
return Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Force a template's pattern class to be instantiated.
|
|
||||||
///
|
|
||||||
/// \returns true if an error occurred
|
|
||||||
bool Sema::InstantiateTemplatePattern(SourceLocation PointOfInstantiation,
|
|
||||||
CXXRecordDecl *Pattern) {
|
|
||||||
if (Pattern->getDefinition(Context)) return false;
|
|
||||||
|
|
||||||
ClassTemplateDecl *PatternTemp = Pattern->getDescribedClassTemplate();
|
|
||||||
if (!PatternTemp) return false;
|
|
||||||
|
|
||||||
// Check whether this template is a lazy instantiation of a
|
|
||||||
// dependent member template, e.g. Inner<U> in
|
|
||||||
// Outer<int>::Inner<U>.
|
|
||||||
ClassTemplateDecl *PatternPatternTemp
|
|
||||||
= PatternTemp->getInstantiatedFromMemberTemplate();
|
|
||||||
if (!PatternPatternTemp) return false;
|
|
||||||
|
|
||||||
ClassTemplateSpecializationDecl *Spec = 0;
|
|
||||||
for (DeclContext *Parent = Pattern->getDeclContext();
|
|
||||||
Parent && !Spec; Parent = Parent->getParent())
|
|
||||||
Spec = dyn_cast<ClassTemplateSpecializationDecl>(Parent);
|
|
||||||
assert(Spec && "Not a member of a class template specialization?");
|
|
||||||
|
|
||||||
// TODO: the error message from a nested failure here is probably
|
|
||||||
// not ideal.
|
|
||||||
return InstantiateClass(PointOfInstantiation,
|
|
||||||
Pattern,
|
|
||||||
PatternPatternTemp->getTemplatedDecl(),
|
|
||||||
Spec->getTemplateArgs(),
|
|
||||||
/* ExplicitInstantiation = */ false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Instantiate the definition of a class from a given pattern.
|
/// \brief Instantiate the definition of a class from a given pattern.
|
||||||
///
|
///
|
||||||
/// \param PointOfInstantiation The point of instantiation within the
|
/// \param PointOfInstantiation The point of instantiation within the
|
||||||
|
@ -644,15 +626,11 @@ bool Sema::InstantiateTemplatePattern(SourceLocation PointOfInstantiation,
|
||||||
bool
|
bool
|
||||||
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
|
||||||
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
|
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
|
||||||
const TemplateArgumentList &TemplateArgs,
|
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||||
bool ExplicitInstantiation,
|
bool ExplicitInstantiation,
|
||||||
bool Complain) {
|
bool Complain) {
|
||||||
bool Invalid = false;
|
bool Invalid = false;
|
||||||
|
|
||||||
// Lazily instantiate member templates here.
|
|
||||||
if (InstantiateTemplatePattern(PointOfInstantiation, Pattern))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
CXXRecordDecl *PatternDef
|
CXXRecordDecl *PatternDef
|
||||||
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
|
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
|
||||||
if (!PatternDef) {
|
if (!PatternDef) {
|
||||||
|
@ -745,9 +723,7 @@ Sema::InstantiateClassTemplateSpecialization(
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
|
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
|
||||||
CXXRecordDecl *Pattern = Template->getTemplatedDecl();
|
CXXRecordDecl *Pattern = 0;
|
||||||
const TemplateArgumentList *TemplateArgs
|
|
||||||
= &ClassTemplateSpec->getTemplateArgs();
|
|
||||||
|
|
||||||
// C++ [temp.class.spec.match]p1:
|
// C++ [temp.class.spec.match]p1:
|
||||||
// When a class template is used in a context that requires an
|
// When a class template is used in a context that requires an
|
||||||
|
@ -782,7 +758,6 @@ Sema::InstantiateClassTemplateSpecialization(
|
||||||
// -- If exactly one matching specialization is found, the
|
// -- If exactly one matching specialization is found, the
|
||||||
// instantiation is generated from that specialization.
|
// instantiation is generated from that specialization.
|
||||||
Pattern = Matched[0].first;
|
Pattern = Matched[0].first;
|
||||||
TemplateArgs = Matched[0].second;
|
|
||||||
ClassTemplateSpec->setInstantiationOf(Matched[0].first, Matched[0].second);
|
ClassTemplateSpec->setInstantiationOf(Matched[0].first, Matched[0].second);
|
||||||
} else if (Matched.size() > 1) {
|
} else if (Matched.size() > 1) {
|
||||||
// -- If more than one matching specialization is found, the
|
// -- If more than one matching specialization is found, the
|
||||||
|
@ -796,12 +771,21 @@ Sema::InstantiateClassTemplateSpecialization(
|
||||||
// specializations.
|
// specializations.
|
||||||
Diag(ClassTemplateSpec->getLocation(),
|
Diag(ClassTemplateSpec->getLocation(),
|
||||||
diag::unsup_template_partial_spec_ordering);
|
diag::unsup_template_partial_spec_ordering);
|
||||||
|
|
||||||
|
// FIXME: Temporary hack to fall back to the primary template
|
||||||
|
ClassTemplateDecl *OrigTemplate = Template;
|
||||||
|
while (OrigTemplate->getInstantiatedFromMemberTemplate())
|
||||||
|
OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
|
||||||
|
|
||||||
|
Pattern = OrigTemplate->getTemplatedDecl();
|
||||||
} else {
|
} else {
|
||||||
// -- If no matches are found, the instantiation is generated
|
// -- If no matches are found, the instantiation is generated
|
||||||
// from the primary template.
|
// from the primary template.
|
||||||
|
ClassTemplateDecl *OrigTemplate = Template;
|
||||||
|
while (OrigTemplate->getInstantiatedFromMemberTemplate())
|
||||||
|
OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
|
||||||
|
|
||||||
// Since we initialized the pattern and template arguments from
|
Pattern = OrigTemplate->getTemplatedDecl();
|
||||||
// the primary template, there is nothing more we need to do here.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that this is an instantiation.
|
// Note that this is an instantiation.
|
||||||
|
@ -810,7 +794,8 @@ Sema::InstantiateClassTemplateSpecialization(
|
||||||
: TSK_ImplicitInstantiation);
|
: TSK_ImplicitInstantiation);
|
||||||
|
|
||||||
bool Result = InstantiateClass(ClassTemplateSpec->getLocation(),
|
bool Result = InstantiateClass(ClassTemplateSpec->getLocation(),
|
||||||
ClassTemplateSpec, Pattern, *TemplateArgs,
|
ClassTemplateSpec, Pattern,
|
||||||
|
getTemplateInstantiationArgs(ClassTemplateSpec),
|
||||||
ExplicitInstantiation,
|
ExplicitInstantiation,
|
||||||
Complain);
|
Complain);
|
||||||
|
|
||||||
|
@ -829,7 +814,7 @@ Sema::InstantiateClassTemplateSpecialization(
|
||||||
void
|
void
|
||||||
Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
|
||||||
CXXRecordDecl *Instantiation,
|
CXXRecordDecl *Instantiation,
|
||||||
const TemplateArgumentList &TemplateArgs) {
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||||
for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
|
for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
|
||||||
DEnd = Instantiation->decls_end();
|
DEnd = Instantiation->decls_end();
|
||||||
D != DEnd; ++D) {
|
D != DEnd; ++D) {
|
||||||
|
@ -866,11 +851,11 @@ void Sema::InstantiateClassTemplateSpecializationMembers(
|
||||||
// containing the explicit instantiation, except as described
|
// containing the explicit instantiation, except as described
|
||||||
// below.
|
// below.
|
||||||
InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
|
InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
|
||||||
ClassTemplateSpec->getTemplateArgs());
|
getTemplateInstantiationArgs(ClassTemplateSpec));
|
||||||
}
|
}
|
||||||
|
|
||||||
Sema::OwningStmtResult
|
Sema::OwningStmtResult
|
||||||
Sema::SubstStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
|
Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||||
if (!S)
|
if (!S)
|
||||||
return Owned(S);
|
return Owned(S);
|
||||||
|
|
||||||
|
@ -881,7 +866,7 @@ Sema::SubstStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Sema::OwningExprResult
|
Sema::OwningExprResult
|
||||||
Sema::SubstExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
|
Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||||
if (!E)
|
if (!E)
|
||||||
return Owned(E);
|
return Owned(E);
|
||||||
|
|
||||||
|
@ -895,7 +880,7 @@ Sema::SubstExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
|
||||||
NestedNameSpecifier *
|
NestedNameSpecifier *
|
||||||
Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
|
Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
|
||||||
SourceRange Range,
|
SourceRange Range,
|
||||||
const TemplateArgumentList &TemplateArgs) {
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||||
TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
|
TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
|
||||||
DeclarationName());
|
DeclarationName());
|
||||||
return Instantiator.TransformNestedNameSpecifier(NNS, Range);
|
return Instantiator.TransformNestedNameSpecifier(NNS, Range);
|
||||||
|
@ -903,14 +888,14 @@ Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
|
||||||
|
|
||||||
TemplateName
|
TemplateName
|
||||||
Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc,
|
Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc,
|
||||||
const TemplateArgumentList &TemplateArgs) {
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||||
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
|
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
|
||||||
DeclarationName());
|
DeclarationName());
|
||||||
return Instantiator.TransformTemplateName(Name);
|
return Instantiator.TransformTemplateName(Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateArgument Sema::Subst(TemplateArgument Arg,
|
TemplateArgument Sema::Subst(TemplateArgument Arg,
|
||||||
const TemplateArgumentList &TemplateArgs) {
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||||
TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
|
TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
|
||||||
DeclarationName());
|
DeclarationName());
|
||||||
return Instantiator.TransformTemplateArgument(Arg);
|
return Instantiator.TransformTemplateArgument(Arg);
|
||||||
|
|
|
@ -25,13 +25,13 @@ namespace {
|
||||||
: public DeclVisitor<TemplateDeclInstantiator, Decl *> {
|
: public DeclVisitor<TemplateDeclInstantiator, Decl *> {
|
||||||
Sema &SemaRef;
|
Sema &SemaRef;
|
||||||
DeclContext *Owner;
|
DeclContext *Owner;
|
||||||
const TemplateArgumentList &TemplateArgs;
|
const MultiLevelTemplateArgumentList &TemplateArgs;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef Sema::OwningExprResult OwningExprResult;
|
typedef Sema::OwningExprResult OwningExprResult;
|
||||||
|
|
||||||
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
|
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
|
||||||
const TemplateArgumentList &TemplateArgs)
|
const MultiLevelTemplateArgumentList &TemplateArgs)
|
||||||
: SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
|
: SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
|
||||||
|
|
||||||
// FIXME: Once we get closer to completion, replace these manually-written
|
// FIXME: Once we get closer to completion, replace these manually-written
|
||||||
|
@ -457,8 +457,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
|
||||||
if (FunctionTemplate) {
|
if (FunctionTemplate) {
|
||||||
llvm::FoldingSetNodeID ID;
|
llvm::FoldingSetNodeID ID;
|
||||||
FunctionTemplateSpecializationInfo::Profile(ID,
|
FunctionTemplateSpecializationInfo::Profile(ID,
|
||||||
TemplateArgs.getFlatArgumentList(),
|
TemplateArgs.getInnermost().getFlatArgumentList(),
|
||||||
TemplateArgs.flat_size(),
|
TemplateArgs.getInnermost().flat_size(),
|
||||||
SemaRef.Context);
|
SemaRef.Context);
|
||||||
|
|
||||||
FunctionTemplateSpecializationInfo *Info
|
FunctionTemplateSpecializationInfo *Info
|
||||||
|
@ -513,7 +513,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
|
||||||
// Record this function template specialization.
|
// Record this function template specialization.
|
||||||
Function->setFunctionTemplateSpecialization(SemaRef.Context,
|
Function->setFunctionTemplateSpecialization(SemaRef.Context,
|
||||||
FunctionTemplate,
|
FunctionTemplate,
|
||||||
&TemplateArgs,
|
&TemplateArgs.getInnermost(),
|
||||||
InsertPos);
|
InsertPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,8 +531,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
||||||
// specialization for this particular set of template arguments.
|
// specialization for this particular set of template arguments.
|
||||||
llvm::FoldingSetNodeID ID;
|
llvm::FoldingSetNodeID ID;
|
||||||
FunctionTemplateSpecializationInfo::Profile(ID,
|
FunctionTemplateSpecializationInfo::Profile(ID,
|
||||||
TemplateArgs.getFlatArgumentList(),
|
TemplateArgs.getInnermost().getFlatArgumentList(),
|
||||||
TemplateArgs.flat_size(),
|
TemplateArgs.getInnermost().flat_size(),
|
||||||
SemaRef.Context);
|
SemaRef.Context);
|
||||||
|
|
||||||
FunctionTemplateSpecializationInfo *Info
|
FunctionTemplateSpecializationInfo *Info
|
||||||
|
@ -646,7 +646,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
|
||||||
// Record this function template specialization.
|
// Record this function template specialization.
|
||||||
Method->setFunctionTemplateSpecialization(SemaRef.Context,
|
Method->setFunctionTemplateSpecialization(SemaRef.Context,
|
||||||
FunctionTemplate,
|
FunctionTemplate,
|
||||||
&TemplateArgs,
|
&TemplateArgs.getInnermost(),
|
||||||
InsertPos);
|
InsertPos);
|
||||||
|
|
||||||
bool Redeclaration = false;
|
bool Redeclaration = false;
|
||||||
|
@ -760,7 +760,7 @@ TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
|
Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
|
||||||
const TemplateArgumentList &TemplateArgs) {
|
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||||
TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
|
TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
|
||||||
return Instantiator.Visit(D);
|
return Instantiator.Visit(D);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,3 +21,25 @@ void test_X0(int *ip, double *dp) {
|
||||||
double *&dpr2 = xv.f1(ip, dp);
|
double *&dpr2 = xv.f1(ip, dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct X1 {
|
||||||
|
template<typename U>
|
||||||
|
struct Inner0 {
|
||||||
|
U x;
|
||||||
|
T y; // expected-error{{void}}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename U>
|
||||||
|
struct Inner1 {
|
||||||
|
U x; // expected-error{{void}}
|
||||||
|
T y;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_X1() {
|
||||||
|
X1<void>::Inner0<int> *xvip; // okay
|
||||||
|
X1<void>::Inner0<int> xvi; // expected-note{{instantiation}}
|
||||||
|
|
||||||
|
X1<int>::Inner1<void> *xivp; // okay
|
||||||
|
X1<int>::Inner1<void> xiv; // expected-note{{instantiation}}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue