diff mbox series

[1/2] libstdc++: Make std::construct_at support arrays (LWG 3436)

Message ID 20241002200503.3359969-1-jwakely@redhat.com
State New
Headers show
Series [1/2] libstdc++: Make std::construct_at support arrays (LWG 3436) | expand

Commit Message

Jonathan Wakely Oct. 2, 2024, 7:37 p.m. UTC
Is the g++ test change OK?

Tested x86_64-linux.

-- >8 --

The issue was approved at the recent St. Louis meeting, requiring
support for bounded arrays, but only without arguments to initialize the
array elements.

libstdc++-v3/ChangeLog:

	* include/bits/stl_construct.h (construct_at): Support array
	types (LWG 3436).
	* testsuite/20_util/specialized_algorithms/construct_at/array.cc:
	New test.
	* testsuite/20_util/specialized_algorithms/construct_at/array_neg.cc:
	New test.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/initlist-opt1.C: Adjust for different diagnostics
	from std::construct_at by adding -fconcepts-diagnostics-depth=2.
---
 gcc/testsuite/g++.dg/cpp0x/initlist-opt1.C    |  1 +
 libstdc++-v3/include/bits/stl_construct.h     | 20 +++++++--
 .../construct_at/array.cc                     | 41 +++++++++++++++++++
 .../construct_at/array_neg.cc                 | 19 +++++++++
 4 files changed, 78 insertions(+), 3 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/20_util/specialized_algorithms/construct_at/array.cc
 create mode 100644 libstdc++-v3/testsuite/20_util/specialized_algorithms/construct_at/array_neg.cc
diff mbox series

Patch

diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt1.C
index 391b7c47d50..38c4f00cec0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist-opt1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt1.C
@@ -1,5 +1,6 @@ 
 // PR c++/110102
 // { dg-do compile { target c++11 } }
+// { dg-additional-options "-fconcepts-diagnostics-depth=2" { target c++20 } }
 // { dg-skip-if "requires hosted libstdc++ for list" { ! hostedlib } }
 
 // { dg-error "deleted|construct_at" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h
index dc08fb7ea33..146ea14e99a 100644
--- a/libstdc++-v3/include/bits/stl_construct.h
+++ b/libstdc++-v3/include/bits/stl_construct.h
@@ -90,11 +90,25 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __cpp_constexpr_dynamic_alloc // >= C++20
   template<typename _Tp, typename... _Args>
-    constexpr auto
+    requires (!is_unbounded_array_v<_Tp>)
+      && requires { ::new((void*)0) _Tp(std::declval<_Args>()...); }
+    constexpr _Tp*
     construct_at(_Tp* __location, _Args&&... __args)
     noexcept(noexcept(::new((void*)0) _Tp(std::declval<_Args>()...)))
-    -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...))
-    { return ::new((void*)__location) _Tp(std::forward<_Args>(__args)...); }
+    {
+      void* __loc = const_cast<remove_cv_t<_Tp>*>(__location);
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 3436. std::construct_at should support arrays
+      if constexpr (is_array_v<_Tp>)
+	{
+	  static_assert(sizeof...(_Args) == 0, "std::construct_at for array "
+		       "types must not use any arguments to initialize the "
+		       "array");
+	  return ::new(__loc) _Tp[1]();
+	}
+      else
+	return ::new(__loc) _Tp(std::forward<_Args>(__args)...);
+    }
 #endif // C++20
 #endif// C++17
 
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/construct_at/array.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/construct_at/array.cc
new file mode 100644
index 00000000000..c3683462835
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/construct_at/array.cc
@@ -0,0 +1,41 @@ 
+// { dg-do compile { target c++20 } }
+
+// LWG 3436. std::construct_at should support arrays
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+constexpr void
+test_array()
+{
+  int arr[1] { 99 };
+  std::construct_at(&arr);
+  VERIFY( arr[0] == 0 );
+
+  union U {
+    long long x;
+    int arr[4];
+  } u;
+  u.x = -1;
+
+  auto p = std::construct_at(&u.arr);
+  VERIFY( (*p)[0] == 0 );
+  VERIFY( (*p)[1] == 0 );
+  VERIFY( (*p)[2] == 0 );
+  VERIFY( (*p)[3] == 0 );
+
+  struct NonTrivial {
+    constexpr NonTrivial() : i(99) { }
+    int i;
+  };
+
+  union U2 {
+    char c = 'a';
+    NonTrivial arr[2];
+  } u2;
+
+  auto p2 = std::construct_at(&u2.arr);
+  VERIFY( (*p2)[0].i == 99 );
+}
+
+static_assert( [] { test_array(); return true; }() );
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/construct_at/array_neg.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/construct_at/array_neg.cc
new file mode 100644
index 00000000000..deb86930d1a
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/construct_at/array_neg.cc
@@ -0,0 +1,19 @@ 
+// { dg-do compile { target c++20 } }
+
+// LWG 3436. std::construct_at should support arrays
+
+#include <memory>
+
+void
+test_array_args()
+{
+  int arr[2];
+  std::construct_at(&arr, 1, 2); // { dg-error "here" }
+  // { dg-error "must not use any arguments" "" { target *-*-* } 0 }
+}
+
+void
+test_unbounded_array(int (*p)[])
+{
+  std::construct_at(p); // { dg-error "no matching function" }
+}