https://gcc.gnu.org/g:bbc9c0423ca754e8e6ff80e08948ff52986337a0

commit r15-2435-gbbc9c0423ca754e8e6ff80e08948ff52986337a0
Author: Marek Polacek <pola...@redhat.com>
Date:   Wed Jul 17 15:44:26 2024 -0400

    c++: array new with value-initialization, again [PR115645]
    
    Unfortunately, my r15-1946 fix broke the attached testcase; the
    constexpr evaluation reported an error about not being able to
    evaluate the code emitted by build_vec_init.  Jason figured out
    it's because we were wrongly setting try_const to false, where
    in fact it should have been true.  Value-initialization of scalars
    is constexpr, so we should check that alongside of
    type_has_constexpr_default_constructor.
    
            PR c++/115645
    
    gcc/cp/ChangeLog:
    
            * init.cc (build_vec_init): When initializing a scalar type, try to
            create a constant initializer.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp2a/constexpr-new23.C: New test.

Diff:
---
 gcc/cp/init.cc                               |  5 +++-
 gcc/testsuite/g++.dg/cpp2a/constexpr-new23.C | 38 ++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index e9561c146d7b..de82152bd1d3 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -4724,7 +4724,10 @@ build_vec_init (tree base, tree maxindex, tree init,
                    && TREE_CONSTANT (maxindex)
                    && (init ? TREE_CODE (init) == CONSTRUCTOR
                        : (type_has_constexpr_default_constructor
-                          (inner_elt_type)))
+                          (inner_elt_type)
+                          /* Value-initialization of scalars is constexpr.  */
+                          || (explicit_value_init_p
+                              && SCALAR_TYPE_P (inner_elt_type))))
                    && (literal_type_p (inner_elt_type)
                        || TYPE_HAS_CONSTEXPR_CTOR (inner_elt_type)));
   vec<constructor_elt, va_gc> *const_vec = NULL;
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new23.C 
b/gcc/testsuite/g++.dg/cpp2a/constexpr-new23.C
new file mode 100644
index 000000000000..1abbef18fae3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new23.C
@@ -0,0 +1,38 @@
+// PR c++/115645
+// { dg-do compile { target c++20 } }
+
+using size_t = decltype(sizeof(0));
+
+void* operator new(size_t, void* p) { return p; }
+void* operator new[](size_t, void* p) { return p; }
+
+#define VERIFY(C) if (!(C)) throw
+
+namespace std {
+  template<typename T>
+    constexpr T* construct_at(T* p)
+    {
+      if constexpr (__is_array(T))
+        return ::new((void*)p) T[1]();
+      else
+        return ::new((void*)p) T();
+    }
+}
+
+constexpr void
+test_array()
+{
+  int arr[1] { 99 };
+  std::construct_at(&arr);
+  VERIFY( arr[0] == 0 );
+
+  union U {
+    long long x = -1;
+    int arr[4];
+  } u;
+
+  auto p = std::construct_at(&u.arr);
+  VERIFY( (*p)[0] == 0 );
+}
+
+static_assert( [] { test_array(); return true; }() );

Reply via email to