if (cxx_dialect > cxx23)
{
/* Set feature test macros for C++26. */
- cpp_define (pfile, "__cpp_constexpr=202306L");
+ cpp_define (pfile, "__cpp_constexpr=202406L");
cpp_define (pfile, "__cpp_static_assert=202306L");
cpp_define (pfile, "__cpp_placeholder_variables=202306L");
cpp_define (pfile, "__cpp_structured_bindings=202403L");
--- /dev/null
+// C++26 P2747R2 - constexpr placement new
+// { dg-do compile { target c++26 } }
+
+#include "../cpp2a/construct_at.h"
+
+struct S {
+ constexpr S () : a (42), b (43) {}
+ constexpr S (int c, int d) : a (c), b (d) {}
+ int a, b;
+};
+struct T {
+ int a, b;
+};
+
+constexpr bool
+foo ()
+{
+ std::allocator<int> a;
+ auto b = a.allocate (3);
+ ::new (b) int ();
+ ::new (b + 1) int (1);
+ ::new (b + 2) int {2};
+ if (b[0] != 0 || b[1] != 1 || b[2] != 2)
+ return false;
+ a.deallocate (b, 3);
+ std::allocator<S> c;
+ auto d = c.allocate (4);
+ ::new (d) S;
+ ::new (d + 1) S ();
+ ::new (d + 2) S (7, 8);
+ ::new (d + 3) S { 9, 10 };
+ if (d[0].a != 42 || d[0].b != 43
+ || d[1].a != 42 || d[1].b != 43
+ || d[2].a != 7 || d[2].b != 8
+ || d[3].a != 9 || d[3].b != 10)
+ return false;
+ d[0].~S ();
+ d[1].~S ();
+ d[2].~S ();
+ d[3].~S ();
+ c.deallocate (d, 4);
+ std::allocator<T> e;
+ auto f = e.allocate (3);
+ ::new (f) T ();
+ ::new (f + 1) T (7, 8);
+ ::new (f + 2) T { .a = 9, .b = 10 };
+ if (f[0].a != 0 || f[0].b != 0
+ || f[1].a != 7 || f[1].b != 8
+ || f[2].a != 9 || f[2].b != 10)
+ return false;
+ f[0].~T ();
+ f[1].~T ();
+ f[2].~T ();
+ e.deallocate (f, 3);
+ auto g = a.allocate (3);
+ new (g) int[] {1, 2, 3};
+ if (g[0] != 1 || g[1] != 2 || g[2] != 3)
+ return false;
+ new (g) int[] {4, 5};
+ if (g[0] != 4 || g[1] != 5)
+ return false;
+ a.deallocate (g, 3);
+ return true;
+}
+
+static_assert (foo ());
--- /dev/null
+// C++26 P2747R2 - constexpr placement new
+// { dg-do compile { target c++26 } }
+
+#include <memory>
+#include <new>
+
+#ifndef __cpp_lib_constexpr_new
+# error "__cpp_lib_constexpr_new"
+#elif __cpp_lib_constexpr_new < 202406L
+# error "__cpp_lib_constexpr_new < 202406"
+#endif
+
+struct S {
+ constexpr S () : a (42), b (43) {}
+ constexpr S (int c, int d) : a (c), b (d) {}
+ int a, b;
+};
+struct T {
+ int a, b;
+};
+
+constexpr bool
+foo ()
+{
+ std::allocator<int> a;
+ auto b = a.allocate (3);
+ ::new (b) int ();
+ ::new (b + 1) int (1);
+ ::new (b + 2) int {2};
+ if (b[0] != 0 || b[1] != 1 || b[2] != 2)
+ return false;
+ a.deallocate (b, 3);
+ std::allocator<S> c;
+ auto d = c.allocate (4);
+ ::new (d) S;
+ ::new (d + 1) S ();
+ ::new (d + 2) S (7, 8);
+ ::new (d + 3) S { 9, 10 };
+ if (d[0].a != 42 || d[0].b != 43
+ || d[1].a != 42 || d[1].b != 43
+ || d[2].a != 7 || d[2].b != 8
+ || d[3].a != 9 || d[3].b != 10)
+ return false;
+ d[0].~S ();
+ d[1].~S ();
+ d[2].~S ();
+ d[3].~S ();
+ c.deallocate (d, 4);
+ std::allocator<T> e;
+ auto f = e.allocate (3);
+ ::new (f) T ();
+ ::new (f + 1) T (7, 8);
+ ::new (f + 2) T { .a = 9, .b = 10 };
+ if (f[0].a != 0 || f[0].b != 0
+ || f[1].a != 7 || f[1].b != 8
+ || f[2].a != 9 || f[2].b != 10)
+ return false;
+ f[0].~T ();
+ f[1].~T ();
+ f[2].~T ();
+ e.deallocate (f, 3);
+ auto g = a.allocate (3);
+ new (g) int[] {1, 2, 3};
+ if (g[0] != 1 || g[1] != 2 || g[2] != 3)
+ return false;
+ new (g) int[] {4, 5};
+ if (g[0] != 4 || g[1] != 5)
+ return false;
+ a.deallocate (g, 3);
+ return true;
+}
+
+static_assert (foo ());
--- /dev/null
+// C++26 P2747R2 - constexpr placement new
+// { dg-do compile { target c++26 } }
+
+#include "../cpp2a/construct_at.h"
+
+struct S {
+ constexpr S () : a (42), b (43) {}
+ constexpr S (int c, int d) : a (c), b (d) {}
+ int a, b;
+};
+struct T {
+ int a, b;
+};
+
+constexpr bool
+foo ()
+{
+ std::allocator<int> a;
+ auto b = a.allocate (3);
+ new (b + 1) int[] {2, 3}; // { dg-error "" "" { xfail *-*-* } }
+ a.deallocate (b, 3);
+ return true;
+}
+
+constexpr bool
+bar ()
+{
+ std::allocator<int> a;
+ auto b = a.allocate (3);
+ new (b) int[] {1, 2, 3, 4}; // { dg-error "array subscript value '3' is outside the bounds of array 'heap ' of type 'int \\\[3\\\]'" }
+ a.deallocate (b, 3);
+ return true;
+}
+
+constexpr bool
+baz ()
+{
+ std::allocator<int> a;
+ auto b = a.allocate (2);
+ new (b) long (42); // { dg-error "accessing value of 'heap ' through a 'long int' glvalue in a constant expression" }
+ a.deallocate (b, 2);
+ return true;
+}
+
+constexpr bool a = foo ();
+constexpr bool b = bar ();
+constexpr bool c = baz ();
#ifndef __cpp_constexpr
# error "__cpp_constexpr"
-#elif __cpp_constexpr != 202306L
-# error "__cpp_constexpr != 202306L"
+#elif __cpp_constexpr != 202406L
+# error "__cpp_constexpr != 202406L"
#endif
#ifndef __cpp_decltype_auto
{ l->~T (); }
}
-inline void *operator new (std::size_t, void *p) noexcept
+#if __cpp_constexpr >= 202406L
+constexpr
+#else
+inline
+#endif
+void *operator new (std::size_t, void *p) noexcept
+{ return p; }
+
+#if __cpp_constexpr >= 202406L
+constexpr
+#else
+inline
+#endif
+void *operator new[] (std::size_t, void *p) noexcept
{ return p; }
};
};
+ftms = {
+ name = constexpr_new;
+ values = {
+ v = 202406;
+ cxxmin = 26;
+ extra_cond = "__cpp_constexpr >= 202406L";
+ };
+};
+
// Standard test specifications.
stds[97] = ">= 199711L";
stds[03] = ">= 199711L";
#endif /* !defined(__cpp_lib_ranges_concat) && defined(__glibcxx_want_ranges_concat) */
#undef __glibcxx_want_ranges_concat
+#if !defined(__cpp_lib_constexpr_new)
+# if (__cplusplus > 202302L) && (__cpp_constexpr >= 202406L)
+# define __glibcxx_constexpr_new 202406L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_new)
+# define __cpp_lib_constexpr_new 202406L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_constexpr_new) && defined(__glibcxx_want_constexpr_new) */
+#undef __glibcxx_want_constexpr_new
+
#undef __glibcxx_want_all
#define __glibcxx_want_launder
#define __glibcxx_want_hardware_interference_size
#define __glibcxx_want_destroying_delete
+#define __glibcxx_want_constexpr_new
#include <bits/version.h>
#pragma GCC visibility push(default)
#endif // __cpp_sized_deallocation
#endif // __cpp_aligned_new
+#if __cpp_lib_constexpr_new >= 202406L
+# define _GLIBCXX_PLACEMENT_CONSTEXPR constexpr
+#else
+# define _GLIBCXX_PLACEMENT_CONSTEXPR inline
+#endif
+
// Default placement versions of operator new.
-_GLIBCXX_NODISCARD inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
+_GLIBCXX_NODISCARD _GLIBCXX_PLACEMENT_CONSTEXPR
+void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }
-_GLIBCXX_NODISCARD inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
+_GLIBCXX_NODISCARD _GLIBCXX_PLACEMENT_CONSTEXPR
+void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
{ return __p; }
+#undef _GLIBCXX_PLACEMENT_CONSTEXPR
+
// Default placement versions of operator delete.
inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { }
inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }