From bbc9c0423ca754e8e6ff80e08948ff52986337a0 Mon Sep 17 00:00:00 2001 From: Marek Polacek <polacek@redhat.com> Date: Wed, 17 Jul 2024 15:44:26 -0400 Subject: [PATCH] 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. --- gcc/cp/init.cc | 5 ++- gcc/testsuite/g++.dg/cpp2a/constexpr-new23.C | 38 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/constexpr-new23.C 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; }() ); -- GitLab