aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2018-02-11 20:21:39 -0500
committerJason Merrill <jason@gcc.gnu.org>2018-02-11 20:21:39 -0500
commitdc58fa9f3142097bbcf2d60212041d08ab16cd8e (patch)
tree6015b7020be9ee3d06dffafcd87f625e23b96749 /gcc
parentf1ea257f3cda1f04a64a4046f77013727693eb70 (diff)
downloadgcc-dc58fa9f3142097bbcf2d60212041d08ab16cd8e.zip
gcc-dc58fa9f3142097bbcf2d60212041d08ab16cd8e.tar.gz
gcc-dc58fa9f3142097bbcf2d60212041d08ab16cd8e.tar.bz2
PR c++/84036 - ICE with variadic capture.
Handle variadic capture proxies more like non-variadic. * lambda.c (build_capture_proxy): Remove workaround. * pt.c (find_parameter_packs_r): The proxy is a pack. (instantiate_class_template_1): Remove dead lambda code. (extract_fnparm_pack): Don't make_pack_expansion. (extract_locals_r): Don't strip a pack expansion. (tsubst_pack_expansion): Handle proxy packs. Use PACK_EXPANSION_EXTRA_ARGS less. (tsubst_decl) [FIELD_DECL]: Don't register_specialization. (tsubst_copy) [FIELD_DECL]: Don't retrieve*_specialization. [VAR_DECL]: Handle ARGUMENT_PACK_SELECT. (tsubst_expr) [DECL_EXPR]: Handle proxy packs. (tsubst_copy_and_build) [VAR_DECL]: Handle proxy packs normally. From-SVN: r257575
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog17
-rw-r--r--gcc/cp/lambda.c18
-rw-r--r--gcc/cp/pt.c144
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic11.C21
4 files changed, 79 insertions, 121 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e01e73b..9b87937 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,20 @@
+2018-02-09 Jason Merrill <jason@redhat.com>
+
+ PR c++/84036 - ICE with variadic capture.
+ Handle variadic capture proxies more like non-variadic.
+ * lambda.c (build_capture_proxy): Remove workaround.
+ * pt.c (find_parameter_packs_r): The proxy is a pack.
+ (instantiate_class_template_1): Remove dead lambda code.
+ (extract_fnparm_pack): Don't make_pack_expansion.
+ (extract_locals_r): Don't strip a pack expansion.
+ (tsubst_pack_expansion): Handle proxy packs. Use
+ PACK_EXPANSION_EXTRA_ARGS less.
+ (tsubst_decl) [FIELD_DECL]: Don't register_specialization.
+ (tsubst_copy) [FIELD_DECL]: Don't retrieve*_specialization.
+ [VAR_DECL]: Handle ARGUMENT_PACK_SELECT.
+ (tsubst_expr) [DECL_EXPR]: Handle proxy packs.
+ (tsubst_copy_and_build) [VAR_DECL]: Handle proxy packs normally.
+
2018-02-10 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/83987
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 2545eae..6b5bd80 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -455,19 +455,11 @@ build_capture_proxy (tree member, tree init)
STRIP_NOPS (init);
}
- if (TREE_CODE (init) == COMPONENT_REF)
- /* We're capturing a capture of a function parameter pack, and have
- lost track of the original variable. It's not important to have
- DECL_CAPTURED_VARIABLE in this case, since a function parameter pack
- isn't a constant variable, so don't bother trying to set it. */;
- else
- {
- gcc_assert (VAR_P (init) || TREE_CODE (init) == PARM_DECL);
- while (is_normal_capture_proxy (init))
- init = DECL_CAPTURED_VARIABLE (init);
- retrofit_lang_decl (var);
- DECL_CAPTURED_VARIABLE (var) = init;
- }
+ gcc_assert (VAR_P (init) || TREE_CODE (init) == PARM_DECL);
+ while (is_normal_capture_proxy (init))
+ init = DECL_CAPTURED_VARIABLE (init);
+ retrofit_lang_decl (var);
+ DECL_CAPTURED_VARIABLE (var) = init;
}
if (name == this_identifier)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2816045..b58c60f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3561,14 +3561,13 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
/* Look through a lambda capture proxy to the field pack. */
case VAR_DECL:
- if (DECL_HAS_VALUE_EXPR_P (t))
- {
- tree v = DECL_VALUE_EXPR (t);
- cp_walk_tree (&v,
- &find_parameter_packs_r,
- ppd, ppd->visited);
- *walk_subtrees = 0;
- }
+ if (DECL_PACK_P (t))
+ {
+ /* We don't want to walk into the type of a variadic capture proxy,
+ because we don't want to see the type parameter pack. */
+ *walk_subtrees = 0;
+ parameter_pack_p = true;
+ }
else if (variable_template_specialization_p (t))
{
cp_walk_tree (&DECL_TI_ARGS (t),
@@ -10838,42 +10837,6 @@ instantiate_class_template_1 (tree type)
c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
}
- if (tree expr = CLASSTYPE_LAMBDA_EXPR (type))
- {
- tree decl = lambda_function (type);
- if (decl)
- {
- if (cxx_dialect >= cxx17)
- CLASSTYPE_LITERAL_P (type) = true;
-
- if (!DECL_TEMPLATE_INFO (decl)
- || DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (decl)) != decl)
- {
- /* Set function_depth to avoid garbage collection. */
- ++function_depth;
- instantiate_decl (decl, /*defer_ok=*/false, false);
- --function_depth;
- }
-
- /* We need to instantiate the capture list from the template
- after we've instantiated the closure members, but before we
- consider adding the conversion op. Also keep any captures
- that may have been added during instantiation of the op(). */
- tree tmpl_expr = CLASSTYPE_LAMBDA_EXPR (pattern);
- tree tmpl_cap
- = tsubst_copy_and_build (LAMBDA_EXPR_CAPTURE_LIST (tmpl_expr),
- args, tf_warning_or_error, NULL_TREE,
- false, false);
-
- LAMBDA_EXPR_CAPTURE_LIST (expr)
- = chainon (tmpl_cap, nreverse (LAMBDA_EXPR_CAPTURE_LIST (expr)));
-
- maybe_add_lambda_conv_op (type);
- }
- else
- gcc_assert (errorcount);
- }
-
/* Set the file and line number information to whatever is given for
the class itself. This puts error messages involving generated
implicit functions at a predictable point, and the same point
@@ -10970,12 +10933,7 @@ extract_fnparm_pack (tree tmpl_parm, tree *spec_p)
parmvec = make_tree_vec (len);
spec_parm = *spec_p;
for (i = 0; i < len; i++, spec_parm = DECL_CHAIN (spec_parm))
- {
- tree elt = spec_parm;
- if (DECL_PACK_P (elt))
- elt = make_pack_expansion (elt);
- TREE_VEC_ELT (parmvec, i) = elt;
- }
+ TREE_VEC_ELT (parmvec, i) = spec_parm;
/* Build the argument packs. */
SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
@@ -11125,6 +11083,7 @@ gen_elem_of_pack_expansion_instantiation (tree pattern,
/* Select the Ith argument from the pack. */
if (TREE_CODE (parm) == PARM_DECL
+ || VAR_P (parm)
|| TREE_CODE (parm) == FIELD_DECL)
{
if (index == 0)
@@ -11429,8 +11388,7 @@ extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data)
/* Pull out the actual PARM_DECL for the partial instantiation. */
tree args = ARGUMENT_PACK_ARGS (spec);
gcc_assert (TREE_VEC_LENGTH (args) == 1);
- tree arg = TREE_VEC_ELT (args, 0);
- spec = PACK_EXPANSION_PATTERN (arg);
+ spec = TREE_VEC_ELT (args, 0);
}
*extra = tree_cons (*tp, spec, *extra);
}
@@ -11551,8 +11509,12 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
where it isn't expected). */
unsubstituted_fn_pack = true;
}
- else if (TREE_CODE (parm_pack) == FIELD_DECL)
- arg_pack = tsubst_copy (parm_pack, args, complain, in_decl);
+ else if (is_normal_capture_proxy (parm_pack))
+ {
+ arg_pack = retrieve_local_specialization (parm_pack);
+ if (argument_pack_element_is_expansion_p (arg_pack, 0))
+ unsubstituted_fn_pack = true;
+ }
else
{
int idx;
@@ -11647,15 +11609,14 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
/* We cannot expand this expansion expression, because we don't have
all of the argument packs we need. */
- if (use_pack_expansion_extra_args_p (packs, len, (unsubstituted_packs
- || unsubstituted_fn_pack)))
+ if (use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs))
{
/* We got some full packs, but we can't substitute them in until we
have values for all the packs. So remember these until then. */
t = make_pack_expansion (pattern, complain);
tree extra = args;
- if (unsubstituted_fn_pack)
+ if (local_specializations)
if (tree locals = extract_local_specs (pattern))
extra = tree_cons (NULL_TREE, extra, locals);
PACK_EXPANSION_EXTRA_ARGS (t) = extra;
@@ -11713,6 +11674,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree parm = TREE_PURPOSE (pack);
if (TREE_CODE (parm) == PARM_DECL
+ || VAR_P (parm)
|| TREE_CODE (parm) == FIELD_DECL)
register_local_specialization (TREE_TYPE (pack), parm);
else
@@ -12866,9 +12828,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (PACK_EXPANSION_P (TREE_TYPE (t)))
{
/* This field is a lambda capture pack. Return a TREE_VEC of
- the expanded fields to instantiate_class_template_1 and
- store them in the specializations hash table as a
- NONTYPE_ARGUMENT_PACK so that tsubst_copy can find them. */
+ the expanded fields to instantiate_class_template_1. */
expanded_types = tsubst_pack_expansion (TREE_TYPE (t), args,
complain, in_decl);
if (TREE_CODE (expanded_types) == TREE_VEC)
@@ -12930,12 +12890,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
}
if (vec)
- {
- r = vec;
- tree pack = make_node (NONTYPE_ARGUMENT_PACK);
- SET_ARGUMENT_PACK_ARGS (pack, vec);
- register_specialization (pack, t, args, false, 0);
- }
+ r = vec;
}
break;
@@ -14827,31 +14782,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return t;
case FIELD_DECL:
- if (PACK_EXPANSION_P (TREE_TYPE (t)))
- {
- /* Check for a local specialization set up by
- tsubst_pack_expansion. */
- if (tree r = retrieve_local_specialization (t))
- {
- if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
- r = ARGUMENT_PACK_SELECT_ARG (r);
- return r;
- }
-
- /* When retrieving a capture pack from a generic lambda, remove the
- lambda call op's own template argument list from ARGS. Only the
- template arguments active for the closure type should be used to
- retrieve the pack specialization. */
- if (LAMBDA_FUNCTION_P (current_function_decl)
- && (template_class_depth (DECL_CONTEXT (t))
- != TMPL_ARGS_DEPTH (args)))
- args = strip_innermost_template_args (args, 1);
-
- /* Otherwise return the full NONTYPE_ARGUMENT_PACK that
- tsubst_decl put in the hash table. */
- return retrieve_specialization (t, args, 0);
- }
-
if (DECL_CONTEXT (t))
{
tree ctx;
@@ -14935,6 +14865,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (local_specializations)
register_local_specialization (r, t);
}
+ if (TREE_CODE (r) == ARGUMENT_PACK_SELECT)
+ r = ARGUMENT_PACK_SELECT_ARG (r);
}
else
r = t;
@@ -16104,20 +16036,24 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
else
finish_local_using_decl (decl, scope, name);
}
- else if (DECL_PACK_P (decl))
- {
- /* Don't build up decls for a variadic capture proxy, we'll
- instantiate the elements directly as needed. */
- break;
- }
else if (is_capture_proxy (decl)
&& !DECL_TEMPLATE_INSTANTIATION (current_function_decl))
{
/* We're in tsubst_lambda_expr, we've already inserted a new
capture proxy, so look it up and register it. */
- tree inst = lookup_name_real (DECL_NAME (decl), 0, 0,
- /*block_p=*/true, 0, LOOKUP_HIDDEN);
- gcc_assert (inst != decl && is_capture_proxy (inst));
+ tree inst;
+ if (DECL_PACK_P (decl))
+ {
+ inst = (retrieve_local_specialization
+ (DECL_CAPTURED_VARIABLE (decl)));
+ gcc_assert (TREE_CODE (inst) == NONTYPE_ARGUMENT_PACK);
+ }
+ else
+ {
+ inst = lookup_name_real (DECL_NAME (decl), 0, 0,
+ /*block_p=*/true, 0, LOOKUP_HIDDEN);
+ gcc_assert (inst != decl && is_capture_proxy (inst));
+ }
register_local_specialization (inst, decl);
break;
}
@@ -18265,14 +18201,6 @@ tsubst_copy_and_build (tree t,
case VAR_DECL:
if (!args)
RETURN (t);
- else if (DECL_PACK_P (t))
- {
- /* We don't build decls for an instantiation of a
- variadic capture proxy, we instantiate the elements
- when needed. */
- gcc_assert (DECL_HAS_VALUE_EXPR_P (t));
- return RECUR (DECL_VALUE_EXPR (t));
- }
/* Fall through */
case PARM_DECL:
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic11.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic11.C
new file mode 100644
index 0000000..01ef7c6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic11.C
@@ -0,0 +1,21 @@
+// PR c++/84036
+// { dg-do compile { target c++14 } }
+
+template < typename... T > void sink(T ...){}
+
+template < typename T >
+auto f(T){
+ auto l = [](auto ... i){
+ [i ...]{
+ sink(i...);
+ [=]{ sink(i ...); }();
+ }();
+ };
+ l();
+ l(42);
+ l(0.1,0.2);
+}
+
+int main(){
+ f(0);
+}