diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-19 20:10:05 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-19 20:10:05 +0000 |
commit | 6952f1e4256c5b43aee5e98cea4e9b663bd1d413 (patch) | |
tree | 0b18dbc34cc3a9d14d470beaf483f1d618579c8d /lib/Sema/SemaTemplateInstantiate.cpp | |
parent | 61f438ac38cb7ccd40e77861b19f34553694416f (diff) |
Implement support for non-type template parameter packs whose type is
a pack expansion, e.g., the parameter pack Values in:
template<typename ...Types>
struct Outer {
template<Types ...Values>
struct Inner;
};
This new implementation approach introduces the notion of an
"expanded" non-type template parameter pack, for which we have already
expanded the types of the parameter pack (to, say, "int*, float*",
for Outer<int*, float*>) but have not yet expanded the values. Aside
from creating these expanded non-type template parameter packs, this
patch updates template argument checking and non-type template
parameter pack instantiation to make use of the appropriate types in
the parameter pack.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123845 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 0ae8804481..45fde296e3 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1016,9 +1016,19 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, // Derive the type we want the substituted decl to have. This had // better be non-dependent, or these checks will have serious problems. - QualType TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs, - E->getLocation(), - DeclarationName()); + QualType TargetType; + if (NTTP->isExpandedParameterPack()) + TargetType = NTTP->getExpansionType( + getSema().ArgumentPackSubstitutionIndex); + else if (NTTP->isParameterPack() && + isa<PackExpansionType>(NTTP->getType())) { + TargetType = SemaRef.SubstType( + cast<PackExpansionType>(NTTP->getType())->getPattern(), + TemplateArgs, E->getLocation(), + NTTP->getDeclName()); + } else + TargetType = SemaRef.SubstType(NTTP->getType(), TemplateArgs, + E->getLocation(), NTTP->getDeclName()); assert(!TargetType.isNull() && "type substitution failed for param type"); assert(!TargetType->isDependentType() && "param type still dependent"); return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, @@ -1038,7 +1048,6 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( return getSema().Owned(E); } - // FIXME: Variadic templates select Nth from type? const TemplateArgument &ArgPack = E->getArgumentPack(); unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex; assert(Index < ArgPack.pack_size() && "Substitution index out-of-range"); @@ -1058,8 +1067,17 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr( if (!VD) return ExprError(); - return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, - E->getType(), + QualType T; + NonTypeTemplateParmDecl *NTTP = E->getParameterPack(); + if (NTTP->isExpandedParameterPack()) + T = NTTP->getExpansionType(getSema().ArgumentPackSubstitutionIndex); + else if (const PackExpansionType *Expansion + = dyn_cast<PackExpansionType>(NTTP->getType())) + T = SemaRef.SubstType(Expansion->getPattern(), TemplateArgs, + E->getParameterPackLocation(), NTTP->getDeclName()); + else + T = E->getType(); + return SemaRef.BuildExpressionFromDeclTemplateArgument(Arg, T, E->getParameterPackLocation()); } @@ -1778,6 +1796,11 @@ Sema::InstantiateClassTemplateSpecialization( } } + // If we're dealing with a member template where the template parameters + // have been instantiated, this provides the original template parameters + // from which the member template's parameters were instantiated. + llvm::SmallVector<const NamedDecl *, 4> InstantiatedTemplateParameters; + if (Matched.size() >= 1) { llvm::SmallVector<MatchResult, 4>::iterator Best = Matched.begin(); if (Matched.size() == 1) { |