https://gcc.gnu.org/g:445203466749b8bdd17590fe7dd37d72d8b570c0

commit r13-9354-g445203466749b8bdd17590fe7dd37d72d8b570c0
Author: Marek Polacek <pola...@redhat.com>
Date:   Mon Jan 13 15:09:14 2025 -0500

    c++: re-enable NSDMI CONSTRUCTOR folding [PR118355]
    
    In c++/102990 we had a problem where massage_init_elt got {},
    digest_nsdmi_init turned that {} into { .value = (int) 1.0e+0 },
    and we crashed in the call to fold_non_dependent_init because
    a FIX_TRUNC_EXPR/FLOAT_EXPR got into tsubst*.  So we avoided
    calling fold_non_dependent_init for a CONSTRUCTOR.
    
    But that broke the following test, where we no longer fold the
    CONST_DECL in
      { .type = ZERO }
    to
      { .type = 0 }
    and then process_init_constructor_array does:
    
                if (next != error_mark_node
                    && (initializer_constant_valid_p (next, TREE_TYPE (next))
                        != null_pointer_node))
                  {
                    /* Use VEC_INIT_EXPR for non-constant initialization of
                       trailing elements with no explicit initializers.  */
                    picflags |= PICFLAG_VEC_INIT;
    
    because { .type = ZERO } isn't initializer_constant_valid_p.  Then we
    create a VEC_INIT_EXPR and say we can't convert the argument.
    
    So we have to fold the elements of the CONSTRUCTOR.  We just can't
    instantiate the elements in a template.
    
    This also fixes c++/118047.
    
            PR c++/118047
            PR c++/118355
    
    gcc/cp/ChangeLog:
    
            * typeck2.cc (massage_init_elt): Call fold_non_dependent_init
            unless for a CONSTRUCTOR in a template.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/nsdmi-list10.C: New test.
            * g++.dg/cpp0x/nsdmi-list9.C: New test.
    
    Reviewed-by: Jason Merrill <ja...@redhat.com>
    (cherry picked from commit e939005c496dfd4058fa57b6860bfadcabe4a111)

Diff:
---
 gcc/cp/typeck2.cc                         |  8 +++----
 gcc/testsuite/g++.dg/cpp0x/nsdmi-list10.C | 35 +++++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/nsdmi-list9.C  | 34 ++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc
index 27263f503f18..e499bf0f20ce 100644
--- a/gcc/cp/typeck2.cc
+++ b/gcc/cp/typeck2.cc
@@ -1528,10 +1528,10 @@ massage_init_elt (tree type, tree init, int nested, int 
flags,
     new_flags |= LOOKUP_AGGREGATE_PAREN_INIT;
   init = digest_init_r (type, init, nested ? 2 : 1, new_flags, complain);
   /* When we defer constant folding within a statement, we may want to
-     defer this folding as well.  Don't call this on CONSTRUCTORs because
-     their elements have already been folded, and we must avoid folding
-     the result of get_nsdmi.  */
-  if (TREE_CODE (init) != CONSTRUCTOR)
+     defer this folding as well.  Don't call this on CONSTRUCTORs in
+     a template because their elements have already been folded, and
+     we must avoid folding the result of get_nsdmi.  */
+  if (!(processing_template_decl && TREE_CODE (init) == CONSTRUCTOR))
     {
       tree t = fold_non_dependent_init (init, complain);
       if (TREE_CONSTANT (t))
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list10.C 
b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list10.C
new file mode 100644
index 000000000000..36b74749cbf6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list10.C
@@ -0,0 +1,35 @@
+// PR c++/118047
+// { dg-do compile { target c++11 } }
+
+typedef decltype(sizeof(char)) size_t;
+
+namespace std {
+template <typename T>
+struct initializer_list {
+  const T *_M_array;
+  size_t _M_len;
+  constexpr size_t size() const { return _M_len; }
+};
+}
+
+enum E {
+    One
+};
+
+struct A {
+    E e = One;
+};
+
+struct B {
+    A as[1] {};
+};
+
+struct V
+{
+  constexpr V(const std::initializer_list<B> &a) : size(a.size()){}
+  int size;
+};
+
+constexpr V a{{}};
+
+static_assert(a.size == 1, "");
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list9.C 
b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list9.C
new file mode 100644
index 000000000000..ae69ba0810dc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list9.C
@@ -0,0 +1,34 @@
+// PR c++/118355
+// { dg-do compile { target c++11 } }
+
+enum MY_ENUM
+{
+  ZERO,
+};
+
+struct FOO
+{
+  MY_ENUM type = ZERO;
+};
+
+struct ARR
+{
+  FOO array[1] = {};
+};
+
+template<typename>
+struct ARR2
+{
+  FOO array[1] = {};
+};
+
+void
+g ()
+{
+
+  ARR arr;
+  arr = {};
+
+  ARR2<int> arr2;
+  arr2 = {};
+}

Reply via email to