Commit dc58fa9f by Jason Merrill Committed by Jason Merrill

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
parent f1ea257f
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
......
......@@ -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)
......
......@@ -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:
......
// 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment