aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaTemplate.cpp5
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp45
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp4
-rw-r--r--lib/Sema/TreeTransform.h7
4 files changed, 57 insertions, 4 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 868458c2a9..6a37482d66 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2713,6 +2713,11 @@ bool UnnamedLocalNoLinkageFinder::VisitTemplateTypeParmType(
return false;
}
+bool UnnamedLocalNoLinkageFinder::VisitSubstTemplateTypeParmPackType(
+ const SubstTemplateTypeParmPackType *) {
+ return false;
+}
+
bool UnnamedLocalNoLinkageFinder::VisitTemplateSpecializationType(
const TemplateSpecializationType*) {
return false;
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 5f181fb5e1..629dc58958 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -712,6 +712,12 @@ namespace {
QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
TemplateTypeParmTypeLoc TL);
+ /// \brief Transforms an already-substituted template type parameter pack
+ /// into either itself (if we aren't substituting into its pack expansion)
+ /// or the appropriate substituted argument.
+ QualType TransformSubstTemplateTypeParmPackType(TypeLocBuilder &TLB,
+ SubstTemplateTypeParmPackTypeLoc TL);
+
ExprResult TransformCallExpr(CallExpr *CE) {
getSema().CallsUndergoingInstantiation.push_back(CE);
ExprResult Result =
@@ -1024,10 +1030,15 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
"Missing argument pack");
if (getSema().ArgumentPackSubstitutionIndex == -1) {
- // FIXME: Variadic templates fun case.
- getSema().Diag(TL.getSourceRange().getBegin(),
- diag::err_pack_expansion_mismatch_unsupported);
- return QualType();
+ // We have the template argument pack, but we're not expanding the
+ // enclosing pack expansion yet. Just save the template argument
+ // pack for later substitution.
+ QualType Result
+ = getSema().Context.getSubstTemplateTypeParmPackType(T, Arg);
+ SubstTemplateTypeParmPackTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmPackTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
}
assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
@@ -1063,6 +1074,32 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
return Result;
}
+QualType
+TemplateInstantiator::TransformSubstTemplateTypeParmPackType(
+ TypeLocBuilder &TLB,
+ SubstTemplateTypeParmPackTypeLoc TL) {
+ if (getSema().ArgumentPackSubstitutionIndex == -1) {
+ // We aren't expanding the parameter pack, so just return ourselves.
+ SubstTemplateTypeParmPackTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmPackTypeLoc>(TL.getType());
+ NewTL.setNameLoc(TL.getNameLoc());
+ return TL.getType();
+ }
+
+ const TemplateArgument &ArgPack = TL.getTypePtr()->getArgumentPack();
+ unsigned Index = (unsigned)getSema().ArgumentPackSubstitutionIndex;
+ assert(Index < ArgPack.pack_size() && "Substitution index out-of-range");
+
+ QualType Result = ArgPack.pack_begin()[Index].getAsType();
+ Result = getSema().Context.getSubstTemplateTypeParmType(
+ TL.getTypePtr()->getReplacedParameter(),
+ Result);
+ SubstTemplateTypeParmTypeLoc NewTL
+ = TLB.push<SubstTemplateTypeParmTypeLoc>(Result);
+ NewTL.setNameLoc(TL.getNameLoc());
+ return Result;
+}
+
/// \brief Perform substitution on the type T with a given set of template
/// arguments.
///
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 473dcb7d1f..dc5013c25d 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -456,6 +456,10 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
bool HaveFirstPack = false;
+ // FIXME: Variadic templates. Even if we don't expand, we'd still like to
+ // return the number of expansions back to the caller, perhaps as an
+ // llvm::Optional, so that it can be embedded in the pack expansion. This
+ // is important for the multi-level substitution case.
for (unsigned I = 0; I != NumUnexpanded; ++I) {
// Compute the depth and index for this parameter pack.
unsigned Depth;
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 43d89e2875..4127d5045a 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -3927,6 +3927,13 @@ QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType(
}
template<typename Derived>
+QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmPackType(
+ TypeLocBuilder &TLB,
+ SubstTemplateTypeParmPackTypeLoc TL) {
+ return TransformTypeSpecType(TLB, TL);
+}
+
+template<typename Derived>
QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
TypeLocBuilder &TLB,
TemplateSpecializationTypeLoc TL) {