]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: array DMI and member fn [PR109666]
authorJason Merrill <jason@redhat.com>
Mon, 1 May 2023 14:57:20 +0000 (10:57 -0400)
committerJason Merrill <jason@redhat.com>
Mon, 11 Sep 2023 09:23:48 +0000 (05:23 -0400)
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.

gcc/cp/init.c
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/nsdmi-array2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C [new file with mode: 0644]

index f694c9a5776eb510e3272cb43c09bbb3ef31088a..08b26ba9a17855897e83bb0ed03ca359aef94760 100644 (file)
@@ -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;
        }
index 2901e048b8d2e4af4903b6dde5546fbf350888c0..98b1993e12797b2f25d28f9424c5188926bd602e 100644 (file)
@@ -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.  */
 
index c6d0aa96b559f228174dd0881d7be7561aef3c7b..350a9c05cfe25d9fd2e95625d8f409ed6920c1d4 100644 (file)
@@ -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);
 
index c010392418fb63fed4d2faea16dcefc10eed4b63..0304eb759e830cf06788fbf7b0a46620ad5894ea 100644 (file)
@@ -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 (file)
index 0000000..5ad60f5
--- /dev/null
@@ -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(); }
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template25.C
new file mode 100644 (file)
index 0000000..368e745
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/106890
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  int p;
+};
+
+template<typename T>
+struct B : virtual public A
+{
+  B() { }
+  B(int) { }
+
+  int k = this->p;
+};
+
+template struct B<int>;