From: Richard Smith Date: Tue, 13 Mar 2012 06:56:52 +0000 (+0000) Subject: PR11850 + duplicates: don't assume that a function parameter pack expansion is X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7c5d28b6342229fb648aea59dc063f67ff16bc81;p=clang PR11850 + duplicates: don't assume that a function parameter pack expansion is at the end of the parameter list. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152618 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index f10670c47a..d7da736fe6 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2115,6 +2115,8 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, OldIdx != NumOldParams; ++OldIdx) { ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx); if (!OldParam->isParameterPack() || + // FIXME: Is this right? OldParam could expand to an empty parameter + // pack and the next parameter could be an unexpanded parameter pack (NewIdx < NumNewParams && NewProtoLoc->getArg(NewIdx)->isParameterPack())) { // Simple case: normal parameter, or a parameter pack that's @@ -2458,6 +2460,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, LocalInstantiationScope Scope(*this, MergeWithParentScope); + // Enter the scope of this instantiation. We don't use + // PushDeclContext because we don't have a scope. + Sema::ContextRAII savedContext(*this, Function); + + MultiLevelTemplateArgumentList TemplateArgs = + getTemplateInstantiationArgs(Function, 0, false, PatternDecl); + // Introduce the instantiated function parameters into the local // instantiation scope, and set the parameter names to those used // in the template. @@ -2467,7 +2476,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (!PatternParam->isParameterPack()) { // Simple case: not a parameter pack. assert(FParamIdx < Function->getNumParams()); - ParmVarDecl *FunctionParam = Function->getParamDecl(I); + ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); FunctionParam->setDeclName(PatternParam->getDeclName()); Scope.InstantiatedLocal(PatternParam, FunctionParam); ++FParamIdx; @@ -2476,22 +2485,16 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // Expand the parameter pack. Scope.MakeInstantiatedLocalArgPack(PatternParam); - for (unsigned NumFParams = Function->getNumParams(); - FParamIdx < NumFParams; - ++FParamIdx) { + unsigned NumArgumentsInExpansion + = getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); + for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) { ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); FunctionParam->setDeclName(PatternParam->getDeclName()); Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); + ++FParamIdx; } } - // Enter the scope of this instantiation. We don't use - // PushDeclContext because we don't have a scope. - Sema::ContextRAII savedContext(*this, Function); - - MultiLevelTemplateArgumentList TemplateArgs = - getTemplateInstantiationArgs(Function, 0, false, PatternDecl); - if (PatternDecl->isDefaulted()) { ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true); diff --git a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp index 9414a12883..d8294a1f15 100644 --- a/test/CXX/temp/temp.decls/temp.variadic/p4.cpp +++ b/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -20,6 +20,52 @@ struct is_same { // FIXME: Several more bullets to go +// In a function parameter pack, the pattern is the parameter-declaration +// without the ellipsis. +namespace PR11850 { + template struct S { + int f(T...a, int b) { return b; } + }; + S<> s; + S t; + int k = s.f(0); + int l = t.f(&k, 'x', 5.9, 4); + + template struct A { + template struct B { + template struct C { + C(As..., Bs..., int &k, Cs...); + }; + }; + }; + A<>::B<>::C<> c000(k); + A::B<>::C c101(1, k, 3); + A<>::B::C c011(1, k, 3); + A::B::C<> c110(1, 2, k); + A::B::C c222(1, 2, 3, 4, k, 5, 6); + A::B<>::C<> c300(1, 2, 3, k); + + int &f(); + char &f(void*); + template struct U { + template struct V { + auto g(A...a, B...b) -> decltype(f(a...)); + }; + }; + U<>::V v0; + U::V<> v1; + int &v0f = v0.g(0); + char &v1f = v1.g(0); +} +namespace PR12096 { + void Foo(int) {} + void Foo(int, int) = delete; + template struct Var { + Var(const Args &...args, int *) { Foo(args...); } + }; + Var var(1, 0); +} + // In an initializer-list (8.5); the pattern is an initializer-clause. // Note: this also covers expression-lists, since expression-list is // just defined as initializer-list.