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);
 
   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);
+           }
+
          if (decl != error_mark_node
-             && !member_p
+             && (!member_p || decl)
              && (processing_template_decl || DECL_NAMESPACE_SCOPE_P (decl)))
            has_lambda_scope = true;
 
@@ -24230,10 +24239,14 @@ cp_parser_init_declarator (cp_parser* parser,
          pop_scope (pushed_scope);
          pushed_scope = NULL_TREE;
        }
-      decl = grokfield (declarator, decl_specifiers,
-                       initializer, !is_non_constant_init,
-                       /*asmspec=*/NULL_TREE,
-                       attr_chainon (attributes, prefix_attributes));
+      if (decl)
+       finish_initialized_static_member (decl, initializer,
+                                         /*asmspec=*/NULL_TREE);
+      else
+       decl = grokfield (declarator, decl_specifiers,
+                         initializer, !is_non_constant_init,
+                         /*asmspec=*/NULL_TREE,
+                         attr_chainon (attributes, prefix_attributes));
       if (decl && TREE_CODE (decl) == FUNCTION_DECL)
        cp_parser_save_default_args (parser, decl);
       cp_finalize_omp_declare_simd (parser, decl);
@@ -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))))
     finish_member_declaration (decl);
   /* If DECL is a function template, we must return to parse it later.
      (Even though there is no definition, there might be default
diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx2-19.C 
b/gcc/testsuite/g++.dg/abi/lambda-ctx2-19.C
index 35d394da8c5..afbbf7a86ef 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-ctx2-19.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-ctx2-19.C
@@ -8,3 +8,6 @@
 // { dg-final { scan-assembler {_ZNK1BIiEUlvE2_clEv:} } }
 // { dg-final { scan-assembler {_ZNK1BIiEUlvE3_clEv:} } }
 // { dg-final { scan-assembler {_ZNK1CIiE1xMUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1DUlvE7_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1EIiEUlvE8_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1EIiEUlvE9_clEv:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx2-19vs20.C 
b/gcc/testsuite/g++.dg/abi/lambda-ctx2-19vs20.C
index d4662291e0c..a7f8306233f 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-ctx2-19vs20.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-ctx2-19vs20.C
@@ -6,3 +6,6 @@
 // { dg-regexp {[^\n]*lambda-ctx2.h:[:0-9]* warning: the mangled name of 
.A::<lambda>.[^\n]*\n} }
 // { dg-regexp {[^\n]*lambda-ctx2.h:[:0-9]* warning: the mangled name of 
.B<int>::<lambda>.[^\n]*\n} }
 // { dg-regexp {[^\n]*lambda-ctx2.h:[:0-9]* warning: the mangled name of 
.B<int>::<lambda>.[^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-ctx2.h:[:0-9]* warning: the mangled name of 
.D::<lambda>.[^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-ctx2.h:[:0-9]* warning: the mangled name of 
.E<int>::<lambda>.[^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-ctx2.h:[:0-9]* warning: the mangled name of 
.E<int>::<lambda>.[^\n]*\n} }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx2-20.C 
b/gcc/testsuite/g++.dg/abi/lambda-ctx2-20.C
index 764f6061876..e61c266e833 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-ctx2-20.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-ctx2-20.C
@@ -8,3 +8,6 @@
 // { dg-final { scan-assembler {_ZNK1BIiE1xMUlvE_clEv:} } }
 // { dg-final { scan-assembler {_ZNK1BIiE1xMUlvE0_clEv:} } }
 // { dg-final { scan-assembler {_ZNK1CIiE1xMUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1D1xIiEUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1EIiE1xIiEUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1EIiE1xIiEUlvE0_clEv:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx2.h 
b/gcc/testsuite/g++.dg/abi/lambda-ctx2.h
index e359254db90..d6fa546f9cc 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-ctx2.h
+++ b/gcc/testsuite/g++.dg/abi/lambda-ctx2.h
@@ -25,3 +25,19 @@ int f() {
   A::x();
   return B<int>::x;
 }
+
+struct D {
+  template <typename>
+  static constexpr auto x = []{ return 5; };
+};
+
+template <typename>
+struct E {
+  template <typename>
+  static inline auto x = (side_effect(), []{ return 6; }(), []{ return 7; }());
+};
+
+int g() {
+  D::x<int>();
+  return E<int>::x<int>;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/static-member-init-1.C 
b/gcc/testsuite/g++.dg/cpp0x/static-member-init-1.C
index e64e77faade..c79aafffbf5 100644
--- a/gcc/testsuite/g++.dg/cpp0x/static-member-init-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/static-member-init-1.C
@@ -1,5 +1,10 @@
 // { dg-do compile { target c++11 } }
+// { dg-options "-pedantic" }
 
 struct S {
     static constexpr const void* x = &x;
+
+    template <typename> static inline const void* y = &y<int>;
+    // { dg-warning "variable templates only available with" "" { target 
c++11_down } .-1 }
+    // { dg-warning "inline variables are only available with" "" { target 
c++14_down } .-2 }
 };
-- 
2.47.0

Reply via email to