[cfe-commits] r80389 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplate.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/instantiate-member-template.cpp
Douglas Gregor
dgregor at apple.com
Fri Aug 28 13:31:08 PDT 2009
Author: dgregor
Date: Fri Aug 28 15:31:08 2009
New Revision: 80389
URL: http://llvm.org/viewvc/llvm-project?rev=80389&view=rev
Log:
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.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplate.h
cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=80389&r1=80388&r2=80389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Aug 28 15:31:08 2009
@@ -2903,29 +2903,28 @@
void PerformPendingImplicitInstantiations();
- QualType SubstType(QualType T, const TemplateArgumentList &TemplateArgs,
+ QualType SubstType(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
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,
- const TemplateArgumentList &TemplateArgs);
+ const MultiLevelTemplateArgumentList &TemplateArgs);
bool
SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
CXXRecordDecl *Pattern,
- const TemplateArgumentList &TemplateArgs);
-
- bool
- InstantiateTemplatePattern(SourceLocation PointOfInstantiation,
- CXXRecordDecl *Pattern);
+ const MultiLevelTemplateArgumentList &TemplateArgs);
bool
InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
- const TemplateArgumentList &TemplateArgs,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
bool ExplicitInstantiation,
bool Complain = true);
@@ -2936,7 +2935,7 @@
void InstantiateClassMembers(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation,
- const TemplateArgumentList &TemplateArgs);
+ const MultiLevelTemplateArgumentList &TemplateArgs);
void InstantiateClassTemplateSpecializationMembers(
SourceLocation PointOfInstantiation,
@@ -2945,13 +2944,13 @@
NestedNameSpecifier *
SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
SourceRange Range,
- const TemplateArgumentList &TemplateArgs);
+ const MultiLevelTemplateArgumentList &TemplateArgs);
TemplateName
SubstTemplateName(TemplateName Name, SourceLocation Loc,
- const TemplateArgumentList &TemplateArgs);
+ const MultiLevelTemplateArgumentList &TemplateArgs);
TemplateArgument Subst(TemplateArgument Arg,
- const TemplateArgumentList &TemplateArgs);
+ const MultiLevelTemplateArgumentList &TemplateArgs);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=80389&r1=80388&r2=80389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Aug 28 15:31:08 2009
@@ -2473,14 +2473,14 @@
Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
// Instantiate the expression.
- const TemplateArgumentList &ArgList = getTemplateInstantiationArgs(FD);
+ MultiLevelTemplateArgumentList ArgList = getTemplateInstantiationArgs(FD);
// FIXME: We should really make a new InstantiatingTemplate ctor
// that has a better message - right now we're just piggy-backing
// off the "default template argument" error message.
InstantiatingTemplate Inst(*this, CallLoc, FD->getPrimaryTemplate(),
- ArgList.getFlatArgumentList(),
- ArgList.flat_size());
+ ArgList.getInnermost().getFlatArgumentList(),
+ ArgList.getInnermost().flat_size());
OwningExprResult Result = SubstExpr(UninstExpr, ArgList);
if (Result.isInvalid())
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=80389&r1=80388&r2=80389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Aug 28 15:31:08 2009
@@ -1243,7 +1243,8 @@
TemplateArgumentList TemplateArgs(Context, Converted,
/*TakeArgs=*/false);
- ArgType = SubstType(ArgType, TemplateArgs,
+ ArgType = SubstType(ArgType,
+ MultiLevelTemplateArgumentList(TemplateArgs),
TTP->getDefaultArgumentLoc(),
TTP->getDeclName());
}
@@ -1265,8 +1266,9 @@
TemplateArgumentList TemplateArgs(Context, Converted,
/*TakeArgs=*/false);
- Sema::OwningExprResult E = SubstExpr(NTTP->getDefaultArgument(),
- TemplateArgs);
+ Sema::OwningExprResult E
+ = SubstExpr(NTTP->getDefaultArgument(),
+ MultiLevelTemplateArgumentList(TemplateArgs));
if (E.isInvalid())
return true;
Modified: cfe/trunk/lib/Sema/SemaTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.h?rev=80389&r1=80388&r2=80389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.h (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.h Fri Aug 28 15:31:08 2009
@@ -46,8 +46,8 @@
MultiLevelTemplateArgumentList() { }
/// \brief Construct a single-level template argument list.
- MultiLevelTemplateArgumentList(const TemplateArgumentList *TemplateArgs) {
- TemplateArgumentLists.push_back(TemplateArgs);
+ MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
+ TemplateArgumentLists.push_back(&TemplateArgs);
}
/// \brief Determine the number of levels in this template argument
@@ -57,8 +57,21 @@
/// \brief Retrieve the template argument at a given depth and index.
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
assert(Depth < TemplateArgumentLists.size());
- assert(Index < TemplateArgumentLists[getNumLevels() - Depth]->size());
- return TemplateArgumentLists[getNumLevels() - Depth]->get(Index);
+ assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1]->size());
+ 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
@@ -67,6 +80,11 @@
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
// gradual transition to MultiLevelTemplateArgumentLists.
operator const TemplateArgumentList &() const {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=80389&r1=80388&r2=80389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Aug 28 15:31:08 2009
@@ -26,8 +26,8 @@
// Template Instantiation Support
//===----------------------------------------------------------------------===/
-/// \brief Retrieve the template argument list that should be used to
-/// instantiate the given declaration.
+/// \brief Retrieve the template argument list(s) that should be used to
+/// instantiate the definition of the given declaration.
MultiLevelTemplateArgumentList
Sema::getTemplateInstantiationArgs(NamedDecl *D) {
// Accumulate the set of template argument lists in this structure.
@@ -298,7 +298,7 @@
class VISIBILITY_HIDDEN TemplateInstantiator
: public TreeTransform<TemplateInstantiator>
{
- const TemplateArgumentList &TemplateArgs;
+ const MultiLevelTemplateArgumentList &TemplateArgs;
SourceLocation Loc;
DeclarationName Entity;
@@ -306,7 +306,7 @@
typedef TreeTransform<TemplateInstantiator> inherited;
TemplateInstantiator(Sema &SemaRef,
- const TemplateArgumentList &TemplateArgs,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc,
DeclarationName Entity)
: inherited(SemaRef), TemplateArgs(TemplateArgs), Loc(Loc),
@@ -353,15 +353,24 @@
Decl *TemplateInstantiator::TransformDecl(Decl *D) {
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(D)) {
- // FIXME: Depth reduction
- assert(TTP->getDepth() == 0 &&
- "Cannot reduce depth of a template template parameter");
- assert(TemplateArgs[TTP->getPosition()].getAsDecl() &&
- "Wrong kind of template template argument");
- TemplateDecl *Template
- = dyn_cast<TemplateDecl>(TemplateArgs[TTP->getPosition()].getAsDecl());
- assert(Template && "Expected a template");
- return Template;
+ if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
+ assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() &&
+ "Wrong kind of template template argument");
+ return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(),
+ TTP->getPosition()).getAsDecl());
+ }
+
+ // 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));
@@ -395,59 +404,65 @@
// FIXME: Clean this up a bit
NamedDecl *D = E->getDecl();
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
// because we are performing instantiation from explicitly-specified
// template arguments in a function template, but there were some
// arguments left unspecified.
- if (NTTP->getPosition() >= TemplateArgs.size() ||
- TemplateArgs[NTTP->getPosition()].isNull())
- return SemaRef.Owned(E); // FIXME: Clone the expression!
+ if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(),
+ NTTP->getPosition()))
+ 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
// case we just return that expression.
if (Arg.getKind() == TemplateArgument::Expression)
- // FIXME: Clone the expression!
- return SemaRef.Owned(Arg.getAsExpr());
+ return SemaRef.Owned(Arg.getAsExpr()->Retain());
if (Arg.getKind() == TemplateArgument::Declaration) {
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(),
- false, false);
+ /*FIXME:*/false, /*FIXME:*/false);
}
assert(Arg.getKind() == TemplateArgument::Integral);
QualType T = Arg.getIntegralType();
if (T->isCharType() || T->isWideCharType())
return SemaRef.Owned(new (SemaRef.Context) CharacterLiteral(
- Arg.getAsIntegral()->getZExtValue(),
- T->isWideCharType(),
- T,
- E->getSourceRange().getBegin()));
+ Arg.getAsIntegral()->getZExtValue(),
+ T->isWideCharType(),
+ T,
+ E->getSourceRange().getBegin()));
if (T->isBooleanType())
return SemaRef.Owned(new (SemaRef.Context) CXXBoolLiteralExpr(
- Arg.getAsIntegral()->getBoolValue(),
- T,
- E->getSourceRange().getBegin()));
+ Arg.getAsIntegral()->getBoolValue(),
+ T,
+ E->getSourceRange().getBegin()));
assert(Arg.getAsIntegral()->getBitWidth() == SemaRef.Context.getIntWidth(T));
return SemaRef.Owned(new (SemaRef.Context) IntegerLiteral(
- *Arg.getAsIntegral(),
- T,
- E->getSourceRange().getBegin()));
+ *Arg.getAsIntegral(),
+ T,
+ E->getSourceRange().getBegin()));
}
if (OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D)) {
// FIXME: instantiate each decl in the overload set
return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(Ovl,
- SemaRef.Context.OverloadTy,
- E->getLocation(),
- false, false));
+ SemaRef.Context.OverloadTy,
+ E->getLocation(),
+ false, false));
}
NamedDecl *InstD = SemaRef.FindInstantiatedDecl(D);
@@ -464,31 +479,30 @@
QualType
TemplateInstantiator::TransformTemplateTypeParmType(
const TemplateTypeParmType *T) {
- if (T->getDepth() == 0) {
+ if (T->getDepth() < TemplateArgs.getNumLevels()) {
// Replace the template type parameter with its corresponding
// 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
// because we are performing instantiation from explicitly-specified
// template arguments in a function template class, but there were some
// arguments left unspecified.
- if (T->getIndex() >= TemplateArgs.size() ||
- TemplateArgs[T->getIndex()].isNull())
- return QualType(T, 0); // Would be nice to keep the original type here
-
- assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
+ if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
+ return QualType(T, 0);
+
+ assert(TemplateArgs(T->getDepth(), T->getIndex()).getKind()
+ == TemplateArgument::Type &&
"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 parameter list of a member template inside the
// template we are instantiating). Create a new template type
// 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->isParameterPack(),
T->getName());
@@ -522,7 +536,7 @@
/// \returns If the instantiation succeeds, the instantiated
/// type. Otherwise, produces diagnostics and returns a NULL type.
QualType Sema::SubstType(QualType T,
- const TemplateArgumentList &TemplateArgs,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
SourceLocation Loc, DeclarationName Entity) {
assert(!ActiveTemplateInstantiations.empty() &&
"Cannot perform an instantiation without some context on the "
@@ -545,7 +559,7 @@
bool
Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
CXXRecordDecl *Pattern,
- const TemplateArgumentList &TemplateArgs) {
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
bool Invalid = false;
llvm::SmallVector<CXXBaseSpecifier*, 4> InstantiatedBases;
for (ClassTemplateSpecializationDecl::base_class_iterator
@@ -586,38 +600,6 @@
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.
///
/// \param PointOfInstantiation The point of instantiation within the
@@ -644,15 +626,11 @@
bool
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
- const TemplateArgumentList &TemplateArgs,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
bool ExplicitInstantiation,
bool Complain) {
bool Invalid = false;
- // Lazily instantiate member templates here.
- if (InstantiateTemplatePattern(PointOfInstantiation, Pattern))
- return true;
-
CXXRecordDecl *PatternDef
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
if (!PatternDef) {
@@ -745,9 +723,7 @@
return true;
ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
- CXXRecordDecl *Pattern = Template->getTemplatedDecl();
- const TemplateArgumentList *TemplateArgs
- = &ClassTemplateSpec->getTemplateArgs();
+ CXXRecordDecl *Pattern = 0;
// C++ [temp.class.spec.match]p1:
// When a class template is used in a context that requires an
@@ -782,7 +758,6 @@
// -- If exactly one matching specialization is found, the
// instantiation is generated from that specialization.
Pattern = Matched[0].first;
- TemplateArgs = Matched[0].second;
ClassTemplateSpec->setInstantiationOf(Matched[0].first, Matched[0].second);
} else if (Matched.size() > 1) {
// -- If more than one matching specialization is found, the
@@ -796,21 +771,31 @@
// specializations.
Diag(ClassTemplateSpec->getLocation(),
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 {
// -- If no matches are found, the instantiation is generated
// from the primary template.
-
- // Since we initialized the pattern and template arguments from
- // the primary template, there is nothing more we need to do here.
+ ClassTemplateDecl *OrigTemplate = Template;
+ while (OrigTemplate->getInstantiatedFromMemberTemplate())
+ OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate();
+
+ Pattern = OrigTemplate->getTemplatedDecl();
}
- // Note that this is an instantiation.
+ // Note that this is an instantiation.
ClassTemplateSpec->setSpecializationKind(
ExplicitInstantiation? TSK_ExplicitInstantiation
: TSK_ImplicitInstantiation);
bool Result = InstantiateClass(ClassTemplateSpec->getLocation(),
- ClassTemplateSpec, Pattern, *TemplateArgs,
+ ClassTemplateSpec, Pattern,
+ getTemplateInstantiationArgs(ClassTemplateSpec),
ExplicitInstantiation,
Complain);
@@ -829,7 +814,7 @@
void
Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation,
- const TemplateArgumentList &TemplateArgs) {
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
DEnd = Instantiation->decls_end();
D != DEnd; ++D) {
@@ -866,11 +851,11 @@
// containing the explicit instantiation, except as described
// below.
InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
- ClassTemplateSpec->getTemplateArgs());
+ getTemplateInstantiationArgs(ClassTemplateSpec));
}
Sema::OwningStmtResult
-Sema::SubstStmt(Stmt *S, const TemplateArgumentList &TemplateArgs) {
+Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!S)
return Owned(S);
@@ -881,7 +866,7 @@
}
Sema::OwningExprResult
-Sema::SubstExpr(Expr *E, const TemplateArgumentList &TemplateArgs) {
+Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!E)
return Owned(E);
@@ -894,8 +879,8 @@
/// \brief Do template substitution on a nested-name-specifier.
NestedNameSpecifier *
Sema::SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
- SourceRange Range,
- const TemplateArgumentList &TemplateArgs) {
+ SourceRange Range,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, Range.getBegin(),
DeclarationName());
return Instantiator.TransformNestedNameSpecifier(NNS, Range);
@@ -903,14 +888,14 @@
TemplateName
Sema::SubstTemplateName(TemplateName Name, SourceLocation Loc,
- const TemplateArgumentList &TemplateArgs) {
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, Loc,
DeclarationName());
return Instantiator.TransformTemplateName(Name);
}
TemplateArgument Sema::Subst(TemplateArgument Arg,
- const TemplateArgumentList &TemplateArgs) {
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
DeclarationName());
return Instantiator.TransformTemplateArgument(Arg);
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=80389&r1=80388&r2=80389&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Aug 28 15:31:08 2009
@@ -25,13 +25,13 @@
: public DeclVisitor<TemplateDeclInstantiator, Decl *> {
Sema &SemaRef;
DeclContext *Owner;
- const TemplateArgumentList &TemplateArgs;
+ const MultiLevelTemplateArgumentList &TemplateArgs;
public:
typedef Sema::OwningExprResult OwningExprResult;
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
- const TemplateArgumentList &TemplateArgs)
+ const MultiLevelTemplateArgumentList &TemplateArgs)
: SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { }
// FIXME: Once we get closer to completion, replace these manually-written
@@ -457,8 +457,8 @@
if (FunctionTemplate) {
llvm::FoldingSetNodeID ID;
FunctionTemplateSpecializationInfo::Profile(ID,
- TemplateArgs.getFlatArgumentList(),
- TemplateArgs.flat_size(),
+ TemplateArgs.getInnermost().getFlatArgumentList(),
+ TemplateArgs.getInnermost().flat_size(),
SemaRef.Context);
FunctionTemplateSpecializationInfo *Info
@@ -513,7 +513,7 @@
// Record this function template specialization.
Function->setFunctionTemplateSpecialization(SemaRef.Context,
FunctionTemplate,
- &TemplateArgs,
+ &TemplateArgs.getInnermost(),
InsertPos);
}
@@ -531,8 +531,8 @@
// specialization for this particular set of template arguments.
llvm::FoldingSetNodeID ID;
FunctionTemplateSpecializationInfo::Profile(ID,
- TemplateArgs.getFlatArgumentList(),
- TemplateArgs.flat_size(),
+ TemplateArgs.getInnermost().getFlatArgumentList(),
+ TemplateArgs.getInnermost().flat_size(),
SemaRef.Context);
FunctionTemplateSpecializationInfo *Info
@@ -646,7 +646,7 @@
// Record this function template specialization.
Method->setFunctionTemplateSpecialization(SemaRef.Context,
FunctionTemplate,
- &TemplateArgs,
+ &TemplateArgs.getInnermost(),
InsertPos);
bool Redeclaration = false;
@@ -760,7 +760,7 @@
}
Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner,
- const TemplateArgumentList &TemplateArgs) {
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs);
return Instantiator.Visit(D);
}
Modified: cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp?rev=80389&r1=80388&r2=80389&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-member-template.cpp Fri Aug 28 15:31:08 2009
@@ -21,3 +21,25 @@
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}}
+}
More information about the cfe-commits
mailing list