From: Jason Merrill Date: Mon, 1 May 2023 14:57:20 +0000 (-0400) Subject: c++: array DMI and member fn [PR109666] X-Git-Tag: releases/gcc-11.5.0~602 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0d7e5f90597167c36c7816f5bcf689472e8b1940;p=thirdparty%2Fgcc.git c++: array DMI and member fn [PR109666] Here it turns out I also needed to adjust cfun when stepping out of the member function to instantiate the DMI. But instead of adding that tweak, let's unify with instantiate_body and just push_to_top_level instead of trying to do the minimum subset of it. There was no measurable change in compile time on stdc++.h. This should also resolve 109506 without yet another tweak. PR c++/106890 PR c++/109666 gcc/cp/ChangeLog: * name-lookup.c (maybe_push_to_top_level) (maybe_pop_from_top_level): Split out... * pt.c (instantiate_body): ...from here. * init.c (maybe_instantiate_nsdmi_init): Use them. * name-lookup.h: Declare them.. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/nsdmi-array2.C: New test. * g++.dg/cpp0x/nsdmi-template25.C: New test. --- diff --git a/gcc/cp/init.c b/gcc/cp/init.c index f694c9a5776e..08b26ba9a178 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -597,15 +597,9 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) bool pushed = false; tree ctx = DECL_CONTEXT (member); - processing_template_decl_sentinel ptds (/*reset*/false); + bool push_to_top = maybe_push_to_top_level (member); if (!currently_open_class (ctx)) { - if (!LOCAL_CLASS_P (ctx)) - push_to_top_level (); - else - /* push_to_top_level would lose the necessary function context, - just reset processing_template_decl. */ - processing_template_decl = 0; push_nested_class (ctx); push_deferring_access_checks (dk_no_deferred); pushed = true; @@ -633,9 +627,8 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) { pop_deferring_access_checks (); pop_nested_class (); - if (!LOCAL_CLASS_P (ctx)) - pop_from_top_level (); } + maybe_pop_from_top_level (push_to_top); input_location = sloc; } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 2901e048b8d2..98b1993e1279 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -8520,6 +8520,43 @@ do_pop_from_top_level (void) free_saved_scope = s; } +/* Like push_to_top_level, but not if D is function-local. Returns whether we + did push to top. */ + +bool +maybe_push_to_top_level (tree d) +{ + /* Push if D isn't function-local, or is a lambda function, for which name + resolution is already done. */ + bool push_to_top + = !(current_function_decl + && !LAMBDA_FUNCTION_P (d) + && decl_function_context (d) == current_function_decl); + + if (push_to_top) + push_to_top_level (); + else + { + gcc_assert (!processing_template_decl); + push_function_context (); + cp_unevaluated_operand = 0; + c_inhibit_evaluation_warnings = 0; + } + + return push_to_top; +} + +/* Return from whatever maybe_push_to_top_level did. */ + +void +maybe_pop_from_top_level (bool push_to_top) +{ + if (push_to_top) + pop_from_top_level (); + else + pop_function_context (); +} + /* Push into the scope of the namespace NS, even if it is deeply nested within another namespace. */ diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index c6d0aa96b559..350a9c05cfe2 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -470,6 +470,8 @@ extern void push_to_top_level (void); extern void pop_from_top_level (void); extern void maybe_save_operator_binding (tree); extern void push_operator_bindings (void); +extern bool maybe_push_to_top_level (tree); +extern void maybe_pop_from_top_level (bool); extern void push_using_decl_bindings (tree, tree); extern void discard_operator_bindings (tree); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c010392418fb..0304eb759e83 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -26006,20 +26006,7 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p) if (current_function_decl) save_omp_privatization_clauses (omp_privatization_save); - bool push_to_top - = !(current_function_decl - && !LAMBDA_FUNCTION_P (d) - && decl_function_context (d) == current_function_decl); - - if (push_to_top) - push_to_top_level (); - else - { - gcc_assert (!processing_template_decl); - push_function_context (); - cp_unevaluated_operand = 0; - c_inhibit_evaluation_warnings = 0; - } + bool push_to_top = maybe_push_to_top_level (d); if (VAR_P (d)) { @@ -26132,10 +26119,7 @@ instantiate_body (tree pattern, tree args, tree d, bool nested_p) if (!nested_p) TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (d)) = 0; - if (push_to_top) - pop_from_top_level (); - else - pop_function_context (); + maybe_pop_from_top_level (push_to_top); if (current_function_decl) restore_omp_privatization_clauses (omp_privatization_save); diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-array2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-array2.C new file mode 100644 index 000000000000..5ad60f565108 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-array2.C @@ -0,0 +1,15 @@ +// PR c++/109666 +// { dg-do compile { target c++11 } } + +struct Point { + int value_; +}; +template struct StaticVector { + static StaticVector create() { + StaticVector output; + return output; + } + Point _M_elems[n]{}; + +}; +void f() { StaticVector<3>::create(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C new file mode 100644 index 000000000000..368e745540ef --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C @@ -0,0 +1,18 @@ +// PR c++/106890 +// { dg-do compile { target c++11 } } + +struct A +{ + int p; +}; + +template +struct B : virtual public A +{ + B() { } + B(int) { } + + int k = this->p; +}; + +template struct B;