From bfa28724748054a50075ce6f39b18c5ce111c73c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 1 Feb 2018 13:44:41 -0500 Subject: [PATCH] PR c++/84126 - ICE with variadic generic lambda PR c++/84036 PR c++/82249 * pt.c (tsubst_pack_expansion): Handle function parameter_packs in PACK_EXPANSION_EXTRA_ARGS. From-SVN: r257307 --- gcc/cp/ChangeLog | 8 ++++ gcc/cp/cp-tree.h | 6 ++- gcc/cp/pt.c | 38 ++++++++++++++++++- .../g++.dg/cpp1y/lambda-generic-variadic9.C | 19 ++++++++++ 4 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8fc9042ea01..897774e43f7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2018-02-01 Jason Merrill + + PR c++/84126 - ICE with variadic generic lambda + PR c++/84036 + PR c++/82249 + * pt.c (tsubst_pack_expansion): Handle function parameter_packs in + PACK_EXPANSION_EXTRA_ARGS. + 2018-02-01 Paolo Carlini PR c++/83796 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8983674881d..5f14e514638 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3496,7 +3496,11 @@ extern void decl_shadowed_for_var_insert (tree, tree); : &TYPE_MIN_VALUE_RAW (TYPE_PACK_EXPANSION_CHECK (NODE))) /* Any additional template args to be applied when substituting into - the pattern, set by tsubst_pack_expansion for partial instantiations. */ + the pattern, set by tsubst_pack_expansion for partial instantiations. + If this is a TREE_LIST, the TREE_VALUE of the first element is the + usual template argument TREE_VEC, and the TREE_PURPOSE of later elements + are enclosing functions that provided function parameter packs we'll need + to map appropriately. */ #define PACK_EXPANSION_EXTRA_ARGS(NODE) \ *(TREE_CODE (NODE) == TYPE_PACK_EXPANSION \ ? &TYPE_MAX_VALUE_RAW (NODE) \ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 9516be893aa..ca73bb18d97 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11439,7 +11439,20 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, pattern = PACK_EXPANSION_PATTERN (t); /* Add in any args remembered from an earlier partial instantiation. */ - args = add_to_template_args (PACK_EXPANSION_EXTRA_ARGS (t), args); + tree extra = PACK_EXPANSION_EXTRA_ARGS (t); + if (extra && TREE_CODE (extra) == TREE_LIST) + { + /* The partial instantiation involved function parameter packs; map + from the general template to our current context. */ + for (tree fns = TREE_CHAIN (extra); fns; fns = TREE_CHAIN (fns)) + { + tree fn = TREE_PURPOSE (fns); + tree inst = enclosing_instantiation_of (fn); + register_parameter_specializations (fn, inst); + } + extra = TREE_VALUE (extra); + } + args = add_to_template_args (extra, args); levels = TMPL_ARGS_DEPTH (args); @@ -11610,7 +11623,28 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, have values for all the packs. So remember these until then. */ t = make_pack_expansion (pattern, complain); - PACK_EXPANSION_EXTRA_ARGS (t) = args; + tree extra = args; + if (unsubstituted_fn_pack) + { + /* For function parameter packs it's more complicated; we need to + remember which enclosing function(s) provided them to this pack + expansion so we can map their parameters to the parameters of a + later full instantiation. */ + tree fns = NULL_TREE; + for (tree p = packs; p; p = TREE_CHAIN (p)) + { + tree parm = TREE_PURPOSE (p); + if (TREE_CODE (parm) != PARM_DECL) + continue; + parm = DECL_CONTEXT (parm); + if (purpose_member (parm, fns)) + continue; + fns = tree_cons (parm, NULL_TREE, fns); + } + if (fns) + extra = tree_cons (NULL_TREE, extra, fns); + } + PACK_EXPANSION_EXTRA_ARGS (t) = extra; return t; } else if (unsubstituted_packs) diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic9.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic9.C new file mode 100644 index 00000000000..1b3a6442efd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic9.C @@ -0,0 +1,19 @@ +// PR c++/84126 +// { dg-do compile { target c++14 } } + +template +void sink(Ts...); + +template +int bar(T&); // ICE with reference, work with just T + +template +void foo(T){ + [](auto ... k){ + sink (bar(k) ...); + }(0); +} + +int main() { + foo(0); +} -- 2.30.2