diff options
-rw-r--r-- | include/clang/Sema/Sema.h | 9 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 44 | ||||
-rw-r--r-- | test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp | 3 |
4 files changed, 57 insertions, 6 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 368fe9dffa..d4ffd37bca 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3383,6 +3383,15 @@ public: bool &RetainExpansion, unsigned &NumExpansions); + /// \brief Determine the number of arguments in the given pack expansion + /// type. + /// + /// This routine already assumes that the pack expansion type can be + /// expanded and that the number of arguments in the expansion is + /// consistent across all of the unexpanded parameter packs in its pattern. + unsigned getNumArgumentsInExpansion(QualType T, + const MultiLevelTemplateArgumentList &TemplateArgs); + /// \brief Determine whether the given declarator contains any unexpanded /// parameter packs. /// 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()) { diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp index 4b480ddd3f..8933b63ee6 100644 --- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp @@ -78,8 +78,6 @@ void test_pair_deduction(int *ip, float *fp, double *dp) { // For a function parameter pack that does not occur at the end of the // parameter-declaration-list, the type of the parameter pack is a // non-deduced context. -// FIXME: We're not in a position to handle this yet. -#if 0 template<typename ...Types> struct tuple { }; template<typename ...Types> @@ -88,4 +86,3 @@ void pack_not_at_end(tuple<Types...>, Types... values, int); void test_pack_not_at_end(tuple<int*, double*> t2) { pack_not_at_end(t2, 0, 0, 0); } -#endif |