From ebfefb41d9ba815813e222db19748bc7072eb240 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 11 Jul 2011 17:03:19 -0400 Subject: [PATCH] re PR c++/49672 ([C++0x] Internal error when passing variadic template args to a lambda function) PR c++/49672 * pt.c (extract_fnparm_pack): Split out from... (make_fnparm_pack): ...here. (instantiate_decl): Handle non-pack parms after a pack. * semantics.c (maybe_add_lambda_conv_op): Don't in a template. From-SVN: r176183 --- gcc/cp/ChangeLog | 6 +++ gcc/cp/pt.c | 54 ++++++++++++------- gcc/cp/semantics.c | 3 ++ .../g++.dg/cpp0x/lambda/lambda-variadic1.C | 15 ++++++ 4 files changed, 60 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a6df4fb6fac..6d44bf2f5ef 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2011-07-11 Jason Merrill + PR c++/49672 + * pt.c (extract_fnparm_pack): Split out from... + (make_fnparm_pack): ...here. + (instantiate_decl): Handle non-pack parms after a pack. + * semantics.c (maybe_add_lambda_conv_op): Don't in a template. + * decl2.c (decl_constant_var_p): Use decl_maybe_constant_var_p. PR c++/44609 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7c735ef75b7..33b5b5fab0c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8711,11 +8711,12 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl) return r; } -/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a - NONTYPE_ARGUMENT_PACK. */ +/* Given a function parameter pack TMPL_PARM and some function parameters + instantiated from it at *SPEC_P, return a NONTYPE_ARGUMENT_PACK of them + and set *SPEC_P to point at the next point in the list. */ static tree -make_fnparm_pack (tree spec_parm) +extract_fnparm_pack (tree tmpl_parm, tree *spec_p) { /* Collect all of the extra "packed" parameters into an argument pack. */ @@ -8723,11 +8724,18 @@ make_fnparm_pack (tree spec_parm) tree parmtypevec; tree argpack = make_node (NONTYPE_ARGUMENT_PACK); tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK); - int i, len = list_length (spec_parm); + tree spec_parm = *spec_p; + int i, len; + + for (len = 0; spec_parm; ++len, spec_parm = TREE_CHAIN (spec_parm)) + if (tmpl_parm + && !function_parameter_expanded_from_pack_p (spec_parm, tmpl_parm)) + break; /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */ parmvec = make_tree_vec (len); parmtypevec = make_tree_vec (len); + spec_parm = *spec_p; for (i = 0; i < len; i++, spec_parm = DECL_CHAIN (spec_parm)) { TREE_VEC_ELT (parmvec, i) = spec_parm; @@ -8738,9 +8746,19 @@ make_fnparm_pack (tree spec_parm) SET_ARGUMENT_PACK_ARGS (argpack, parmvec); SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec); TREE_TYPE (argpack) = argtypepack; + *spec_p = spec_parm; return argpack; -} +} + +/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a + NONTYPE_ARGUMENT_PACK. */ + +static tree +make_fnparm_pack (tree spec_parm) +{ + return extract_fnparm_pack (NULL_TREE, &spec_parm); +} /* Substitute ARGS into T, which is an pack expansion (i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a @@ -17830,21 +17848,21 @@ instantiate_decl (tree d, int defer_ok, spec_parm = skip_artificial_parms_for (d, spec_parm); tmpl_parm = skip_artificial_parms_for (subst_decl, tmpl_parm); } - while (tmpl_parm && !FUNCTION_PARAMETER_PACK_P (tmpl_parm)) + for (; tmpl_parm; tmpl_parm = DECL_CHAIN (tmpl_parm)) { - register_local_specialization (spec_parm, tmpl_parm); - tmpl_parm = DECL_CHAIN (tmpl_parm); - spec_parm = DECL_CHAIN (spec_parm); + if (!FUNCTION_PARAMETER_PACK_P (tmpl_parm)) + { + register_local_specialization (spec_parm, tmpl_parm); + spec_parm = DECL_CHAIN (spec_parm); + } + else + { + /* Register the (value) argument pack as a specialization of + TMPL_PARM, then move on. */ + tree argpack = extract_fnparm_pack (tmpl_parm, &spec_parm); + register_local_specialization (argpack, tmpl_parm); + } } - if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm)) - { - /* Register the (value) argument pack as a specialization of - TMPL_PARM, then move on. */ - tree argpack = make_fnparm_pack (spec_parm); - register_local_specialization (argpack, tmpl_parm); - tmpl_parm = DECL_CHAIN (tmpl_parm); - spec_parm = NULL_TREE; - } gcc_assert (!spec_parm); /* Substitute into the body of the function. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 84b0dd8559f..fd00e2976da 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -8808,6 +8808,9 @@ maybe_add_lambda_conv_op (tree type) if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE) return; + if (processing_template_decl) + return; + stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)), FUNCTION_ARG_CHAIN (callop)); diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C new file mode 100644 index 00000000000..f17b33618aa --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C @@ -0,0 +1,15 @@ +// PR c++/49672 +// { dg-options -std=c++0x } + +template +static void foo() +{ + [](Args..., int x) { + x; + }; +} + +int main() +{ + foo(); +} -- 2.30.2