c++: generic lambdas and local-externs from outer scopes [PR 99030]

Lambdas can refer to local externs from their enclosing scope.  When
the lambda's generic but the containing function is not a temploid,
we'll never have tsubsted the declaring decl so won't have a local
specialization.  But in that case we can just use the decl we
tsubsting directly -- it's not dependent.

	PR c++/99030
	gcc/cp
	* pt.c (tsubst_copy) [VAR_DECL]: For a DECL_LOCAL_DECL_P T is the
	answer if there's no local specialization.
	gcc/testsuite/
	* g++.dg/lookup/pr99030.C: New.
This commit is contained in:
Nathan Sidwell 2021-02-10 05:29:39 -08:00
parent 57d1b68d65
commit f8fac476b5
2 changed files with 24 additions and 3 deletions

View File

@ -16650,11 +16650,16 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
r = tsubst (t, args, complain, in_decl);
else if (DECL_LOCAL_DECL_P (t))
{
/* Local specialization will have been created when we
instantiated the DECL_EXPR_DECL. */
/* Local specialization will usually have been created when
we instantiated the DECL_EXPR_DECL. */
r = retrieve_local_specialization (t);
if (!r)
r = error_mark_node;
{
/* We're in a generic lambda referencing a local extern
from an outer block-scope of a non-template. */
gcc_checking_assert (LAMBDA_FUNCTION_P (current_function_decl));
r = t;
}
}
else if (local_variable_p (t)
&& uses_template_parms (DECL_CONTEXT (t)))

View File

@ -0,0 +1,16 @@
// PR 99030 ICE with generic lambda accessing local extern
// { dg-do compile { target c++14 } }
void foo ()
{
extern int a;
[] (auto b) { a; } (1);
}
template<typename T> void bar ()
{
extern T a;
[] (auto b) { a; } (1);
}
template void bar<int> ();