aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp7
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp44
2 files changed, 48 insertions, 3 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 50b24dc41d..a18bfbafc0 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1894,9 +1894,10 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
// Parameter pack: make the instantiation an argument pack.
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(
OldParam);
- // FIXME: Variadic templates. Figure out how many arguments are in the
- // expansion of OldParam, so we don't gobble all of the arguments here.
- while (NewIdx < NumNewParams) {
+ unsigned NumArgumentsInExpansion
+ = SemaRef.getNumArgumentsInExpansion(OldParam->getType(),
+ TemplateArgs);
+ while (NumArgumentsInExpansion--) {
ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
Params.push_back(NewParam);
SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(OldParam,
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 09e610c675..63a8394d67 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -536,6 +536,50 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
return false;
}
+unsigned Sema::getNumArgumentsInExpansion(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ QualType Pattern = cast<PackExpansionType>(T)->getPattern();
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);
+
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ // Compute the depth and index for this parameter pack.
+ unsigned Depth;
+ unsigned Index;
+
+ if (const TemplateTypeParmType *TTP
+ = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+ Depth = TTP->getDepth();
+ Index = TTP->getIndex();
+ } else {
+ NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
+ if (isa<ParmVarDecl>(ND)) {
+ // Function parameter pack.
+ typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
+ = CurrentInstantiationScope->findInstantiationOf(
+ Unexpanded[I].first.get<NamedDecl *>());
+ if (Instantiation && Instantiation->is<DeclArgumentPack *>())
+ return Instantiation->get<DeclArgumentPack *>()->size();
+
+ continue;
+ }
+
+ llvm::tie(Depth, Index) = getDepthAndIndex(ND);
+ }
+ if (Depth >= TemplateArgs.getNumLevels() ||
+ !TemplateArgs.hasTemplateArgument(Depth, Index))
+ continue;
+
+ // Determine the size of the argument pack.
+ return TemplateArgs(Depth, Index).pack_size();
+ }
+
+ llvm_unreachable("No unexpanded parameter packs in type expansion.");
+ return 0;
+}
+
bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
switch (DS.getTypeSpecType()) {