diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-13 06:56:52 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-03-13 06:56:52 +0000 |
| commit | 9479a2e35eb316515df78d5f5499803643f3894d (patch) | |
| tree | c8ce81c9fbf881d3a6af8da0951fd9c2ad37ec8b | |
| parent | 8b5f7c5aa20f8d98d0d580605074b75a903994f2 (diff) | |
| download | bcm5719-llvm-9479a2e35eb316515df78d5f5499803643f3894d.tar.gz bcm5719-llvm-9479a2e35eb316515df78d5f5499803643f3894d.zip | |
PR11850 + duplicates: don't assume that a function parameter pack expansion is
at the end of the parameter list.
llvm-svn: 152618
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 25 | ||||
| -rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp | 46 |
2 files changed, 60 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f10670c47a6..d7da736fe62 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/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/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp index 9414a128832..d8294a1f154 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p4.cpp @@ -20,6 +20,52 @@ struct is_same<T, T> { // FIXME: Several more bullets to go +// In a function parameter pack, the pattern is the parameter-declaration +// without the ellipsis. +namespace PR11850 { + template<typename ...T> struct S { + int f(T...a, int b) { return b; } + }; + S<> s; + S<int*, char, const double&> t; + int k = s.f(0); + int l = t.f(&k, 'x', 5.9, 4); + + template<typename ...As> struct A { + template<typename ...Bs> struct B { + template<typename ...Cs> struct C { + C(As..., Bs..., int &k, Cs...); + }; + }; + }; + A<>::B<>::C<> c000(k); + A<int>::B<>::C<int> c101(1, k, 3); + A<>::B<int>::C<int> c011(1, k, 3); + A<int>::B<int>::C<> c110(1, 2, k); + A<int, int>::B<int, int>::C<int, int> c222(1, 2, 3, 4, k, 5, 6); + A<int, int, int>::B<>::C<> c300(1, 2, 3, k); + + int &f(); + char &f(void*); + template<typename ...A> struct U { + template<typename ...B> struct V { + auto g(A...a, B...b) -> decltype(f(a...)); + }; + }; + U<>::V<int*> v0; + U<int*>::V<> v1; + int &v0f = v0.g(0); + char &v1f = v1.g(0); +} +namespace PR12096 { + void Foo(int) {} + void Foo(int, int) = delete; + template<typename ...Args> struct Var { + Var(const Args &...args, int *) { Foo(args...); } + }; + Var<int> 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. |

