diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 44 |
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()) { |