Commit 373d1f5f by Jason Merrill Committed by Jason Merrill

PR c++/82514 - ICE with local class in generic lambda.

	* pt.c (regenerated_lambda_fn_p): Remove.
	(enclosing_instantiation_of): Don't use it.
	(tsubst_function_decl): Call enclosing_instantiation_of.

	* pt.c (lookup_template_class_1): Add sanity check.
	* name-lookup.c (do_pushtag): Don't add closures to local_classes.

From-SVN: r257093
parent a9ea161d
2018-01-26 Jason Merrill <jason@redhat.com>
PR c++/82514 - ICE with local class in generic lambda.
* pt.c (regenerated_lambda_fn_p): Remove.
(enclosing_instantiation_of): Don't use it.
(tsubst_function_decl): Call enclosing_instantiation_of.
* pt.c (lookup_template_class_1): Add sanity check.
* name-lookup.c (do_pushtag): Don't add closures to local_classes.
2018-01-25 Jakub Jelinek <jakub@redhat.com>
PR c++/84031
......
......@@ -6451,7 +6451,8 @@ do_pushtag (tree name, tree type, tag_scope scope)
template instantiation rather than in some nested context. */
add_decl_expr (decl);
}
else
/* Lambdas use LAMBDA_EXPR_DISCRIMINATOR instead. */
else if (!LAMBDA_TYPE_P (type))
vec_safe_push (local_classes, type);
}
}
......
......@@ -222,6 +222,7 @@ static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree);
static tree canonicalize_expr_argument (tree, tsubst_flags_t);
static tree make_argument_pack (tree);
static void register_parameter_specializations (tree, tree);
static tree enclosing_instantiation_of (tree tctx);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
......@@ -8951,6 +8952,10 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
}
else if (CLASS_TYPE_P (template_type))
{
/* Lambda closures are regenerated in tsubst_lambda_expr, not
instantiated here. */
gcc_assert (!LAMBDA_TYPE_P (template_type));
t = make_class_type (TREE_CODE (template_type));
CLASSTYPE_DECLARED_CLASS (t)
= CLASSTYPE_DECLARED_CLASS (template_type);
......@@ -12183,9 +12188,20 @@ tsubst_function_decl (tree t, tree args, tsubst_flags_t complain,
return t;
/* Calculate the most general template of which R is a
specialization, and the complete set of arguments used to
specialize R. */
specialization. */
gen_tmpl = most_general_template (DECL_TI_TEMPLATE (t));
/* We're substituting a lambda function under tsubst_lambda_expr but not
directly from it; find the matching function we're already inside.
But don't do this if T is a generic lambda with a single level of
template parms, as in that case we're doing a normal instantiation. */
if (LAMBDA_FUNCTION_P (t) && !lambda_fntype
&& (!generic_lambda_fn_p (t)
|| TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (gen_tmpl)) > 1))
return enclosing_instantiation_of (t);
/* Calculate the complete set of arguments used to
specialize R. */
argvec = tsubst_template_args (DECL_TI_ARGS
(DECL_TEMPLATE_RESULT
(DECL_TI_TEMPLATE (t))),
......@@ -12609,24 +12625,15 @@ lambda_fn_in_template_p (tree fn)
return CLASSTYPE_TEMPLATE_INFO (closure) != NULL_TREE;
}
/* True if FN is the op() for a lambda regenerated from a lambda in an
uninstantiated template. */
bool
regenerated_lambda_fn_p (tree fn)
{
return (LAMBDA_FUNCTION_P (fn)
&& !DECL_TEMPLATE_INSTANTIATION (fn));
}
/* We're instantiating a variable from template function TCTX. Return the
corresponding current enclosing scope. This gets complicated because lambda
functions in templates are regenerated rather than instantiated, but generic
lambda functions are subsequently instantiated. */
static tree
enclosing_instantiation_of (tree tctx)
enclosing_instantiation_of (tree otctx)
{
tree tctx = otctx;
tree fn = current_function_decl;
int lambda_count = 0;
......@@ -12635,22 +12642,18 @@ enclosing_instantiation_of (tree tctx)
++lambda_count;
for (; fn; fn = decl_function_context (fn))
{
tree lambda = fn;
tree ofn = fn;
int flambda_count = 0;
for (; fn && regenerated_lambda_fn_p (fn);
for (; flambda_count < lambda_count && fn && LAMBDA_FUNCTION_P (fn);
fn = decl_function_context (fn))
++flambda_count;
if (DECL_TEMPLATE_INFO (fn)
? most_general_template (fn) != most_general_template (tctx)
: fn != tctx)
continue;
if (lambda_count)
{
fn = lambda;
while (flambda_count-- > lambda_count)
fn = decl_function_context (fn);
}
return fn;
gcc_assert (DECL_NAME (ofn) == DECL_NAME (otctx)
|| DECL_CONV_FN_P (ofn));
return ofn;
}
gcc_unreachable ();
}
......
// PR c++/82514
// { dg-do compile { target c++14 } }
void g();
template <typename h> void i(h) { g(); }
template <int> void n() {
[](auto) {
struct p { };
i(p{});
} ('\n');
}
auto f = n<1>;
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