c++: Fix behaviour of nested maybe_push_to_top_level [PR123663]
What happens in the linked PR is that when evaluating the concept we
call 'push_to_top_level', we see cfun is non-null, and so call
'push_function_context' which sets cfun to NULL and sets a flag so that
we remember to pop it later.
Then, when instantiating Foo's default constructor as part of the
concept, we call 'maybe_push_to_top_level'. Here we see that 'Foo' is
function-local, so '!push_to_top', and we call 'push_function_context'.
This allocates a new cfun for some reason, and pushes that empty cfun.
Eventually we 'maybe_pop_from_top_level', and restore that newly
allocated cfun (instead of a NULL cfun), which means that when we start
trying to build the new-expression (which requires building a statement
list) we try accessing the (uninitialized) cfun's x_stmt_tree rather
than the scope_chain's x_stmt_tree, and so crash.
This fixes the issue by also remembering whether we had a cfun when
doing maybe_push_to_top_level so that we only do push_function_context
if needed.
This also seems to fix PR123354.
PR c++/123663
PR c++/123354
gcc/cp/ChangeLog:
* name-lookup.cc (struct local_state_t): New flag has_cfun.
(local_state_t::save_and_clear): Set has_cfun, call
push_function_context iff there's a cfun to save.
(local_state_t::restore): call pop_function_context if
has_cfun is set.
(maybe_push_to_top_level): Delegte push_function_context to
local_state_t::save_and_clear.
(maybe_pop_from_top_level): Delegate pop_function_context to
local_state_t::restore.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-pr123663.C: New test.
* g++.dg/template/pr123354.C
Reviewed-by: Jason Merrill <jason@redhat.com> Reviewed-by: Patrick Palka <ppalka@redhat.com> Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>