aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2023-05-01 10:57:20 -0400
committerJason Merrill <jason@redhat.com>2023-05-01 16:55:07 -0400
commit07c52d1eec9671af92b7ce977b469f13a87887ad (patch)
tree285dc6de4e8d715b2fb25139eff2f289a30cbf00
parentd89b152436a14cae3715af06cd52ed2d0eaafb8e (diff)
downloadgcc-07c52d1eec9671af92b7ce977b469f13a87887ad.zip
gcc-07c52d1eec9671af92b7ce977b469f13a87887ad.tar.gz
gcc-07c52d1eec9671af92b7ce977b469f13a87887ad.tar.bz2
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++/109666 gcc/cp/ChangeLog: * name-lookup.cc (maybe_push_to_top_level) (maybe_pop_from_top_level): Split out... * pt.cc (instantiate_body): ...from here. * init.cc (maybe_instantiate_nsdmi_init): Use them. * name-lookup.h: Declare them.. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/nsdmi-array2.C: New test.
-rw-r--r--gcc/cp/init.cc25
-rw-r--r--gcc/cp/name-lookup.cc37
-rw-r--r--gcc/cp/name-lookup.h2
-rw-r--r--gcc/cp/pt.cc20
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/nsdmi-array2.C15
5 files changed, 58 insertions, 41 deletions
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 1dd24e3..0b35e10 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -597,32 +597,14 @@ maybe_instantiate_nsdmi_init (tree member, tsubst_flags_t complain)
bool pushed = false;
tree ctx = type_context_for_name_lookup (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;
}
- /* If we didn't push_to_top_level, still step out of constructor
- scope so build_base_path doesn't try to use its __in_chrg. */
- tree cfd = current_function_decl;
- auto cbl = current_binding_level;
- if (at_function_scope_p ())
- {
- current_function_decl
- = decl_function_context (current_function_decl);
- while (current_binding_level->kind != sk_class)
- current_binding_level = current_binding_level->level_chain;
- }
-
inject_this_parameter (ctx, TYPE_UNQUALIFIED);
start_lambda_scope (member);
@@ -639,15 +621,12 @@ maybe_instantiate_nsdmi_init (tree member, tsubst_flags_t complain)
if (init != error_mark_node)
DECL_INITIAL (member) = init;
- current_function_decl = cfd;
- current_binding_level = cbl;
if (pushed)
{
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.cc b/gcc/cp/name-lookup.cc
index 477cddd..7c61bc3 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8236,6 +8236,43 @@ 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 c234cd4..b3e7085 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -466,6 +466,8 @@ extern void push_nested_namespace (tree);
extern void pop_nested_namespace (tree);
extern void push_to_top_level (void);
extern void pop_from_top_level (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);
/* Lower level interface for modules. */
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 6df16fe..3f1cf13 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -26815,20 +26815,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);
mark_template_arguments_used (pattern, args);
@@ -26942,10 +26929,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 0000000..5ad60f5
--- /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 <int n> struct StaticVector {
+ static StaticVector create() {
+ StaticVector output;
+ return output;
+ }
+ Point _M_elems[n]{};
+
+};
+void f() { StaticVector<3>::create(); }