--- gcc/c-family/c-cppbuiltin.cc.jj	2024-07-02 22:06:21.343875948 +0200
+++ gcc/c-family/c-cppbuiltin.cc	2024-07-03 10:18:00.311324004 +0200
@@ -1091,7 +1091,7 @@ c_cpp_builtins (cpp_reader *pfile)
       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");
--- gcc/testsuite/g++.dg/cpp2a/construct_at.h.jj	2024-07-02 22:06:22.138865784 +0200
+++ gcc/testsuite/g++.dg/cpp2a/construct_at.h	2024-07-03 10:18:00.312323991 +0200
@@ -58,5 +58,18 @@ namespace std
   { 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; }
--- gcc/testsuite/g++.dg/cpp26/constexpr-new1.C.jj	2024-07-03 10:18:00.312323991 +0200
+++ gcc/testsuite/g++.dg/cpp26/constexpr-new1.C	2024-07-03 10:18:00.312323991 +0200
@@ -0,0 +1,66 @@
+// 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 ());
--- gcc/testsuite/g++.dg/cpp26/constexpr-new2.C.jj	2024-07-03 10:57:14.936113640 +0200
+++ gcc/testsuite/g++.dg/cpp26/constexpr-new2.C	2024-07-03 10:58:34.268063259 +0200
@@ -0,0 +1,73 @@
+// 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 ());
--- gcc/testsuite/g++.dg/cpp26/constexpr-new3.C.jj	2024-07-03 11:03:44.848951067 +0200
+++ gcc/testsuite/g++.dg/cpp26/constexpr-new3.C	2024-07-03 11:20:19.850776541 +0200
@@ -0,0 +1,47 @@
+// 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 ();
--- gcc/testsuite/g++.dg/cpp26/feat-cxx26.C.jj	2024-07-02 22:06:22.081866513 +0200
+++ gcc/testsuite/g++.dg/cpp26/feat-cxx26.C	2024-07-03 10:18:00.312323991 +0200
@@ -134,8 +134,8 @@
 
 #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
--- libstdc++-v3/libsupc++/new.jj	2024-01-03 12:07:51.070049086 +0100
+++ libstdc++-v3/libsupc++/new	2024-07-03 10:36:17.728769550 +0200
@@ -43,6 +43,7 @@
 #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)
@@ -175,10 +176,18 @@ void operator delete[](void*, std::size_
 #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; }
 
 // Default placement versions of operator delete.
--- libstdc++-v3/include/bits/version.def.jj	2024-07-01 11:28:23.642225952 +0200
+++ libstdc++-v3/include/bits/version.def	2024-07-03 10:33:56.996636092 +0200
@@ -1814,6 +1814,15 @@ ftms = {
   };
 };
 
+ftms = {
+  name = constexpr_new;
+  values = {
+    v = 202406;
+    cxxmin = 26;
+    extra_cond = "__cpp_constexpr >= 202406L";
+  };
+};
+
 // Standard test specifications.
 stds[97] = ">= 199711L";
 stds[03] = ">= 199711L";
--- libstdc++-v3/include/bits/version.h.jj	2024-07-01 11:28:23.643225939 +0200
+++ libstdc++-v3/include/bits/version.h	2024-07-03 10:34:28.487052774 +0200
@@ -2023,4 +2023,14 @@
 #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
