Commit 582f844c by Jason Merrill Committed by Jason Merrill

PR c++/82882 - ICE with lambda in template default argument.

	* lambda.c (record_null_lambda_scope): New.
	* pt.c (tsubst_lambda_expr): Use it.
	* name-lookup.c (do_pushtag): Don't give a lambda DECL_CONTEXT of a
	function that isn't open.

From-SVN: r261654
parent 508f1cb5
2018-06-15 Jason Merrill <jason@redhat.com>
PR c++/82882 - ICE with lambda in template default argument.
* lambda.c (record_null_lambda_scope): New.
* pt.c (tsubst_lambda_expr): Use it.
* name-lookup.c (do_pushtag): Don't give a lambda DECL_CONTEXT of a
function that isn't open.
* tree.c (maybe_warn_parm_abi): Inform the location of the class.
2018-06-14 Marek Polacek <polacek@redhat.com>
......
......@@ -7018,6 +7018,7 @@ extern tree finish_builtin_launder (location_t, tree,
tsubst_flags_t);
extern void start_lambda_scope (tree);
extern void record_lambda_scope (tree);
extern void record_null_lambda_scope (tree);
extern void finish_lambda_scope (void);
extern tree start_lambda_function (tree fn, tree lambda_expr);
extern void finish_lambda_function (tree body);
......
......@@ -1380,6 +1380,24 @@ record_lambda_scope (tree lambda)
LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++;
}
/* This lambda is an instantiation of a lambda in a template default argument
that got no LAMBDA_EXPR_EXTRA_SCOPE, so this shouldn't either. But we do
need to use and increment the global count to avoid collisions. */
void
record_null_lambda_scope (tree lambda)
{
if (vec_safe_is_empty (lambda_scope_stack))
record_lambda_scope (lambda);
else
{
tree_int *p = lambda_scope_stack->begin();
LAMBDA_EXPR_EXTRA_SCOPE (lambda) = p->t;
LAMBDA_EXPR_DISCRIMINATOR (lambda) = p->i++;
}
gcc_assert (LAMBDA_EXPR_EXTRA_SCOPE (lambda) == NULL_TREE);
}
void
finish_lambda_scope (void)
{
......
......@@ -6542,6 +6542,14 @@ do_pushtag (tree name, tree type, tag_scope scope)
{
tree cs = current_scope ();
/* Avoid setting the lambda context to a current_function_decl that
we aren't actually inside, e.g. one set by push_access_scope
during tsubst_default_argument. */
if (cs && TREE_CODE (cs) == FUNCTION_DECL
&& LAMBDA_TYPE_P (type)
&& !at_function_scope_p ())
cs = DECL_CONTEXT (cs);
if (scope == ts_current
|| (cs && TREE_CODE (cs) == FUNCTION_DECL))
context = cs;
......
......@@ -17530,7 +17530,11 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
LAMBDA_EXPR_EXTRA_SCOPE (r) = NULL_TREE;
/* A lambda in a default argument outside a class gets no
LAMBDA_EXPR_EXTRA_SCOPE, as specified by the ABI. But
tsubst_default_argument calls start_lambda_scope, so we need to
specifically ignore it here, and use the global scope. */
record_null_lambda_scope (r);
else
record_lambda_scope (r);
......
// PR c++/82282
// { dg-do compile { target c++14 } }
template<typename = int>
void f(const char* a =
([](int = []{ static int i; return 42; }()) {
static int i;
return "";
}()));
template<typename = int>
struct X {
void f(const char* a =
([](int = [] { static int i; return 42; }()) {
enum { Size = 42 - 1 };
return "";
}()));
};
void g()
{
f();
X<int>().f();
}
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