From 3cae5c9a79bfd2e27eb44c32b13dfacd2ce5c66f Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 10 Jan 2011 20:53:55 +0000 Subject: [PATCH] Implement more of C++0x [temp.arg.explicit]p9, allowing extension of pack expansions in template argument lists and function parameter lists. The implementation of this paragraph should be complete *except* for cases where we're substituting into one of the unexpanded packs in a pack expansion; that's a general issue I haven't solved yet. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123188 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaTemplateDeduction.cpp | 15 ++++------ lib/Sema/TreeTransform.h | 28 +++++++++++++++++-- .../temp.fct.spec/temp.arg.explicit/p9-0x.cpp | 23 +++++++++++++++ 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 02e1a42dc3..842ad5c188 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -636,8 +636,7 @@ DeduceTemplateArguments(Sema &S, if (NumParams != NumArgs && !(NumParams && isa(Params[NumParams - 1])) && !(NumArgs && isa(Args[NumArgs - 1]))) - return NumArgs < NumParams ? Sema::TDK_TooFewArguments - : Sema::TDK_TooManyArguments; + return Sema::TDK_NonDeducedMismatch; // C++0x [temp.deduct.type]p10: // Similarly, if P has a form that contains (T), then each parameter type @@ -654,7 +653,7 @@ DeduceTemplateArguments(Sema &S, // Make sure we have an argument. if (ArgIdx >= NumArgs) - return Sema::TDK_TooFewArguments; + return Sema::TDK_NonDeducedMismatch; if (Sema::TemplateDeductionResult Result = DeduceTemplateArguments(S, TemplateParams, @@ -736,7 +735,7 @@ DeduceTemplateArguments(Sema &S, // Make sure we don't have any extra arguments. if (ArgIdx < NumArgs) - return Sema::TDK_TooManyArguments; + return Sema::TDK_NonDeducedMismatch; return Sema::TDK_Success; } @@ -788,10 +787,8 @@ DeduceTemplateArguments(Sema &S, // If the parameter type is not dependent, there is nothing to deduce. if (!Param->isDependentType()) { - if (!(TDF & TDF_SkipNonDependent) && Param != Arg) { - + if (!(TDF & TDF_SkipNonDependent) && Param != Arg) return Sema::TDK_NonDeducedMismatch; - } return Sema::TDK_Success; } @@ -1365,7 +1362,7 @@ DeduceTemplateArguments(Sema &S, // Check whether we have enough arguments. if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) - return NumberOfArgumentsMustMatch? Sema::TDK_TooFewArguments + return NumberOfArgumentsMustMatch? Sema::TDK_NonDeducedMismatch : Sema::TDK_Success; // Perform deduction for this Pi/Ai pair. @@ -1459,7 +1456,7 @@ DeduceTemplateArguments(Sema &S, // If there is an argument remaining, then we had too many arguments. if (NumberOfArgumentsMustMatch && hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) - return Sema::TDK_TooManyArguments; + return Sema::TDK_NonDeducedMismatch; return Sema::TDK_Success; } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 7eee444174..bc1ac1e6ae 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -2850,7 +2850,20 @@ bool TreeTransform::TransformTemplateArguments(InputIterator First, Outputs.addArgument(Out); } - // FIXME: Variadic templates retain expansion! + // If we're supposed to retain a pack expansion, do so by temporarily + // forgetting the partially-substituted parameter pack. + if (RetainExpansion) { + ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + + if (getDerived().TransformTemplateArgument(Pattern, Out)) + return true; + + Out = getDerived().RebuildPackExpansion(Out, Ellipsis); + if (Out.getArgument().isNull()) + return true; + + Outputs.addArgument(Out); + } continue; } @@ -3564,7 +3577,18 @@ bool TreeTransform:: continue; } - // FIXME: Variadic templates retain pack expansion! + // If we're supposed to retain a pack expansion, do so by temporarily + // forgetting the partially-substituted parameter pack. + if (RetainExpansion) { + ForgetPartiallySubstitutedPackRAII Forget(getDerived()); + QualType NewType = getDerived().TransformType(Pattern); + if (NewType.isNull()) + return true; + + OutParamTypes.push_back(NewType); + if (PVars) + PVars->push_back(0); + } // We'll substitute the parameter now without expanding the pack // expansion. diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp index 66ffb82adc..b38cc27609 100644 --- a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p9-0x.cpp @@ -43,3 +43,26 @@ void test_explicit_spec_extension(double *dp) { double *dp1 = first_arg<>(dp); } +template +struct tuple { }; + +template +void accept_tuple(tuple); + +void test_explicit_spec_extension_targs(tuple t3) { + accept_tuple(t3); + accept_tuple(t3); + accept_tuple(t3); + accept_tuple(t3); +} + +template +void accept_function_ptr(R(*)(ParmTypes...)); + +void test_explicit_spec_extension_funcparms(int (*f3)(int, float, double)) { + accept_function_ptr(f3); + accept_function_ptr(f3); + accept_function_ptr(f3); + accept_function_ptr(f3); + accept_function_ptr(f3); +} -- 2.40.0