On 2/7/25 9:19 AM, Nathaniel Shead wrote:
On Fri, Feb 07, 2025 at 08:05:54AM -0500, Jason Merrill wrote:
On 1/31/25 8:44 AM, Nathaniel Shead wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

My fix for this issue in r15-7147 turns out to not be quite sufficient;
static member templates apparently go down a different code path and
need their own handling.

        PR c++/107741

gcc/cp/ChangeLog:

        * decl2.cc (start_initialized_static_member): Push the
        TEMPLATE_DECL when appropriate.
        * parser.cc (cp_parser_init_declarator): Start the member decl
        early for static members so that lambda scope is set.
        (cp_parser_template_declaration_after_parameters): Don't
        register static members here.

gcc/testsuite/ChangeLog:

        * g++.dg/abi/lambda-ctx2-19.C: Add tests for template members.
        * g++.dg/abi/lambda-ctx2-19vs20.C: Likewise.
        * g++.dg/abi/lambda-ctx2-20.C: Likewise.
        * g++.dg/abi/lambda-ctx2.h: Likewise.
        * g++.dg/cpp0x/static-member-init-1.C: Likewise.

Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
---
   gcc/cp/decl2.cc                               | 15 ++++++++--
   gcc/cp/parser.cc                              | 30 +++++++++++++++----
   gcc/testsuite/g++.dg/abi/lambda-ctx2-19.C     |  3 ++
   gcc/testsuite/g++.dg/abi/lambda-ctx2-19vs20.C |  3 ++
   gcc/testsuite/g++.dg/abi/lambda-ctx2-20.C     |  3 ++
   gcc/testsuite/g++.dg/abi/lambda-ctx2.h        | 16 ++++++++++
   .../g++.dg/cpp0x/static-member-init-1.C       |  5 ++++
   7 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 9e61afd359f..994a459c79c 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -1295,6 +1295,8 @@ start_initialized_static_member (const cp_declarator 
*declarator,
     gcc_checking_assert (VAR_P (value));
     DECL_CONTEXT (value) = current_class_type;
+  DECL_INITIALIZED_IN_CLASS_P (value) = true;
+
     if (processing_template_decl)
       {
         value = push_template_decl (value);
@@ -1305,8 +1307,17 @@ start_initialized_static_member (const cp_declarator 
*declarator,
     if (attrlist)
       cplus_decl_attributes (&value, attrlist, 0);
-  finish_member_declaration (value);
-  DECL_INITIALIZED_IN_CLASS_P (value) = true;
+  /* When defining a template we need to register the TEMPLATE_DECL.  */
+  tree maybe_template = value;
+  if (template_parm_scope_p ())
+    {
+      if (!DECL_TEMPLATE_SPECIALIZATION (value))
+       maybe_template = DECL_TI_TEMPLATE (value);
+      else
+       maybe_template = NULL_TREE;
+    }
+  if (maybe_template)
+    finish_member_declaration (maybe_template);

Sigh, this all seems increasingly fragile.  Perhaps it would have been
preferable to break up grokfield for all members rather than just
initialized variables.  Or at least for all static data members.  Now is not
the time for that, of course.


Maybe, yeah; I might look into seeing what can be untangled here for
GCC 16.

     return value;
   }
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 7ddb7f119a4..af1c3774f74 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -24179,8 +24179,17 @@ cp_parser_init_declarator (cp_parser* parser,
             here we only handle the latter two.  */
          bool has_lambda_scope = false;
+         if (member_p && decl_specifiers->storage_class == sc_static)
+           {
+             gcc_checking_assert (!decl);
+             tree all_attrs = attr_chainon (attributes, prefix_attributes);
+             decl = start_initialized_static_member (declarator,
+                                                     decl_specifiers,
+                                                     all_attrs);
+           }

Could we do this sooner, near the start_decl call?  And adjust the comment
there that says we wait until after the initializer for members...


Done.

          if (decl != error_mark_node
-             && !member_p
+             && (!member_p || decl)

I think this line can just be "decl" now?


Done.

              && (processing_template_decl || DECL_NAMESPACE_SCOPE_P (decl)))
            has_lambda_scope = true;
@@ -33739,7 +33752,12 @@ cp_parser_template_declaration_after_parameters 
(cp_parser* parser,
       }
     /* Register member declarations.  */
-  if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl))
+  if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl)
+      /* But this is not needed for initialised static members, that were
+        registered early to be able to be used in their own definition.  */
+      && !(variable_template_p (decl)
+          && DECL_CLASS_SCOPE_P (decl)
+          && DECL_INITIALIZED_IN_CLASS_P (DECL_TEMPLATE_RESULT (decl))))

This should be a predicate.

Jason


Done.

So far tested just on dg.exp, OK for trunk if full bootstrap + regtest
succeeds?

@@ -33739,7 +33757,10 @@ cp_parser_template_declaration_after_parameters 
(cp_parser* parser,
      }
/* Register member declarations. */
-  if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl))
+  if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl)
+      /* But this is not needed for initialised static members, that were
+        registered early to be able to be used in their own definition.  */

Let's clarify "early" to "in start_initialized_static_member". OK with that tweak.

Jason

Reply via email to