Skip to content

Commit 7808541

Browse files
[libc++] P2747R2: constexpr placement new (library part) (#105768)
This patch implements https://wg21.link/P2747R2. The library changes affect direct `operator new` and `operator new[]` calls even when the core language changes are absent. The changes are not available for MS ABI because the `operator new` and `operator new[]` are from VCRuntime's `<vcruntime_new.h>`. A feature request was submitted for that [1]. As a drive-by change, the patch reformatted the whole `new.pass.cpp` and `new_array.pass.cpp` tests. Closes #105427 [1]: https://developercommunity.visualstudio.com/t/constexpr-for-placement-operator-newope/10730304.
1 parent 0e8208e commit 7808541

File tree

12 files changed

+90
-38
lines changed

12 files changed

+90
-38
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ Status
406406
---------------------------------------------------------- -----------------
407407
``__cpp_lib_bitset`` ``202306L``
408408
---------------------------------------------------------- -----------------
409-
``__cpp_lib_constexpr_new`` *unimplemented*
409+
``__cpp_lib_constexpr_new`` ``202406L``
410410
---------------------------------------------------------- -----------------
411411
``__cpp_lib_constrained_equality`` *unimplemented*
412412
---------------------------------------------------------- -----------------

libcxx/docs/ReleaseNotes/20.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ What's New in Libc++ 20.0.0?
3838
Implemented Papers
3939
------------------
4040

41+
- P2747R2: ``constexpr`` placement new (`Github <https://github.com/llvm/llvm-project/issues/105427>`__)
4142
- P2609R3: Relaxing Ranges Just A Smidge (`Github <https://github.com/llvm/llvm-project/issues/105253>`__)
4243
- P2985R0: A type trait for detecting virtual base classes (`Github <https://github.com/llvm/llvm-project/issues/105432>`__)
4344

libcxx/docs/Status/Cxx2cPapers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"`P2642R6 <https://wg21.link/P2642R6>`__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","","",""
6464
"`P3029R1 <https://wg21.link/P3029R1>`__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19.0",""
6565
"","","","","",""
66-
"`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","","",""
66+
"`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","|Complete|","20.0",""
6767
"`P2997R1 <https://wg21.link/P2997R1>`__","Removing the common reference requirement from the indirectly invocable concepts","2024-06 (St. Louis)","|Complete| [#note-P2997R1]_","19.0",""
6868
"`P2389R2 <https://wg21.link/P2389R2>`__","``dextents`` Index Type Parameter","2024-06 (St. Louis)","|Complete|","19.0",""
6969
"`P3168R2 <https://wg21.link/P3168R2>`__","Give ``std::optional`` Range Support","2024-06 (St. Louis)","","","|ranges|"

libcxx/include/__config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,12 @@ typedef __char32_t char32_t;
788788
# define _LIBCPP_CONSTEXPR_SINCE_CXX23
789789
# endif
790790

791+
# if _LIBCPP_STD_VER >= 26
792+
# define _LIBCPP_CONSTEXPR_SINCE_CXX26 constexpr
793+
# else
794+
# define _LIBCPP_CONSTEXPR_SINCE_CXX26
795+
# endif
796+
791797
# ifndef _LIBCPP_WEAK
792798
# define _LIBCPP_WEAK __attribute__((__weak__))
793799
# endif

libcxx/include/new

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ void operator delete[](void* ptr, const std::nothrow_t&) noexcept; // repla
7979
void operator delete[](void* ptr, std::align_val_t alignment,
8080
const std::nothrow_t&) noexcept; // replaceable, C++17
8181
82-
void* operator new (std::size_t size, void* ptr) noexcept; // nodiscard in C++20
83-
void* operator new[](std::size_t size, void* ptr) noexcept; // nodiscard in C++20
82+
void* operator new (std::size_t size, void* ptr) noexcept; // nodiscard in C++20, constexpr since C++26
83+
void* operator new[](std::size_t size, void* ptr) noexcept; // nodiscard in C++20, constexpr since C++26
8484
void operator delete (void* ptr, void*) noexcept;
8585
void operator delete[](void* ptr, void*) noexcept;
8686
@@ -242,8 +242,14 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::size_t __sz,
242242
# endif
243243
# endif
244244

245-
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI void* operator new(std::size_t, void* __p) _NOEXCEPT { return __p; }
246-
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI void* operator new[](std::size_t, void* __p) _NOEXCEPT { return __p; }
245+
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void*
246+
operator new(std::size_t, void* __p) _NOEXCEPT {
247+
return __p;
248+
}
249+
_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void*
250+
operator new[](std::size_t, void* __p) _NOEXCEPT {
251+
return __p;
252+
}
247253
inline _LIBCPP_HIDE_FROM_ABI void operator delete(void*, void*) _NOEXCEPT {}
248254
inline _LIBCPP_HIDE_FROM_ABI void operator delete[](void*, void*) _NOEXCEPT {}
249255

libcxx/include/version

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,9 @@ __cpp_lib_void_t 201411L <type_traits>
513513
# undef __cpp_lib_bind_front
514514
# define __cpp_lib_bind_front 202306L
515515
# define __cpp_lib_bitset 202306L
516-
// # define __cpp_lib_constexpr_new 202406L
516+
# if !defined(_LIBCPP_ABI_VCRUNTIME)
517+
# define __cpp_lib_constexpr_new 202406L
518+
# endif
517519
// # define __cpp_lib_constrained_equality 202403L
518520
// # define __cpp_lib_copyable_function 202306L
519521
// # define __cpp_lib_debugging 202311L

libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new.pass.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,30 @@
1515

1616
int A_constructed = 0;
1717

18-
struct A
19-
{
20-
A() {++A_constructed;}
21-
~A() {--A_constructed;}
18+
struct A {
19+
A() { ++A_constructed; }
20+
~A() { --A_constructed; }
2221
};
2322

24-
int main(int, char**)
25-
{
26-
char buf[sizeof(A)];
23+
TEST_CONSTEXPR_OPERATOR_NEW void test_direct_call() {
24+
assert(::operator new(sizeof(int), &A_constructed) == &A_constructed);
2725

28-
A* ap = new(buf) A;
29-
assert((char*)ap == buf);
30-
assert(A_constructed == 1);
26+
char ch = '*';
27+
assert(::operator new(1, &ch) == &ch);
28+
assert(ch == '*');
29+
}
30+
31+
#ifdef __cpp_lib_constexpr_new
32+
static_assert((test_direct_call(), true));
33+
#endif
34+
35+
int main(int, char**) {
36+
char buf[sizeof(A)];
37+
38+
A* ap = new (buf) A;
39+
assert((char*)ap == buf);
40+
assert(A_constructed == 1);
3141

42+
test_direct_call();
3243
return 0;
3344
}

libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new_array.pass.cpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,34 @@
1515

1616
int A_constructed = 0;
1717

18-
struct A
19-
{
20-
A() {++A_constructed;}
21-
~A() {--A_constructed;}
18+
struct A {
19+
A() { ++A_constructed; }
20+
~A() { --A_constructed; }
2221
};
2322

24-
int main(int, char**)
25-
{
26-
const std::size_t Size = 3;
27-
// placement new might require additional space.
28-
const std::size_t ExtraSize = 64;
29-
char buf[Size*sizeof(A) + ExtraSize];
23+
TEST_CONSTEXPR_OPERATOR_NEW void test_direct_call() {
24+
assert(::operator new[](sizeof(int), &A_constructed) == &A_constructed);
3025

31-
A* ap = new(buf) A[Size];
32-
assert((char*)ap >= buf);
33-
assert((char*)ap < (buf + ExtraSize));
34-
assert(A_constructed == Size);
26+
char ch = '*';
27+
assert(::operator new[](1, &ch) == &ch);
28+
assert(ch == '*');
29+
}
30+
31+
#ifdef __cpp_lib_constexpr_new
32+
static_assert((test_direct_call(), true));
33+
#endif
34+
35+
int main(int, char**) {
36+
const std::size_t Size = 3;
37+
// placement new might require additional space.
38+
const std::size_t ExtraSize = 64;
39+
char buf[Size * sizeof(A) + ExtraSize];
40+
41+
A* ap = new (buf) A[Size];
42+
assert((char*)ap >= buf);
43+
assert((char*)ap < (buf + ExtraSize));
44+
assert(A_constructed == Size);
3545

46+
test_direct_call();
3647
return 0;
3748
}

libcxx/test/std/language.support/support.limits/support.limits.general/new.version.compile.pass.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,16 +171,16 @@
171171

172172
#elif TEST_STD_VER > 23
173173

174-
# if !defined(_LIBCPP_VERSION)
174+
# if !defined(_LIBCPP_ABI_VCRUNTIME)
175175
# ifndef __cpp_lib_constexpr_new
176176
# error "__cpp_lib_constexpr_new should be defined in c++26"
177177
# endif
178178
# if __cpp_lib_constexpr_new != 202406L
179179
# error "__cpp_lib_constexpr_new should have the value 202406L in c++26"
180180
# endif
181-
# else // _LIBCPP_VERSION
181+
# else
182182
# ifdef __cpp_lib_constexpr_new
183-
# error "__cpp_lib_constexpr_new should not be defined because it is unimplemented in libc++!"
183+
# error "__cpp_lib_constexpr_new should not be defined when the requirement '!defined(_LIBCPP_ABI_VCRUNTIME)' is not met!"
184184
# endif
185185
# endif
186186

libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6555,16 +6555,16 @@
65556555
# error "__cpp_lib_constexpr_memory should have the value 202202L in c++26"
65566556
# endif
65576557

6558-
# if !defined(_LIBCPP_VERSION)
6558+
# if !defined(_LIBCPP_ABI_VCRUNTIME)
65596559
# ifndef __cpp_lib_constexpr_new
65606560
# error "__cpp_lib_constexpr_new should be defined in c++26"
65616561
# endif
65626562
# if __cpp_lib_constexpr_new != 202406L
65636563
# error "__cpp_lib_constexpr_new should have the value 202406L in c++26"
65646564
# endif
6565-
# else // _LIBCPP_VERSION
6565+
# else
65666566
# ifdef __cpp_lib_constexpr_new
6567-
# error "__cpp_lib_constexpr_new should not be defined because it is unimplemented in libc++!"
6567+
# error "__cpp_lib_constexpr_new should not be defined when the requirement '!defined(_LIBCPP_ABI_VCRUNTIME)' is not met!"
65686568
# endif
65696569
# endif
65706570

libcxx/test/support/test_macros.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,12 @@
184184
# define TEST_CONSTEXPR_CXX23
185185
#endif
186186

187+
#if TEST_STD_VER >= 26
188+
# define TEST_CONSTEXPR_CXX26 constexpr
189+
#else
190+
# define TEST_CONSTEXPR_CXX26
191+
#endif
192+
187193
#define TEST_ALIGNAS_TYPE(...) TEST_ALIGNAS(TEST_ALIGNOF(__VA_ARGS__))
188194

189195
#if !TEST_HAS_FEATURE(cxx_rtti) && !defined(__cpp_rtti) \
@@ -497,4 +503,12 @@ inline Tp const& DoNotOptimize(Tp const& value) {
497503
# define TEST_HAS_EXPLICIT_THIS_PARAMETER
498504
#endif
499505

506+
// Placement `operator new`/`operator new[]` are not yet constexpr in C++26
507+
// when using MS ABI, because they are from <vcruntime_new.h>.
508+
#if defined(__cpp_lib_constexpr_new) && __cpp_lib_constexpr_new >= 202406L
509+
# define TEST_CONSTEXPR_OPERATOR_NEW constexpr
510+
#else
511+
# define TEST_CONSTEXPR_OPERATOR_NEW
512+
#endif
513+
500514
#endif // SUPPORT_TEST_MACROS_HPP

libcxx/utils/generate_feature_test_macro_components.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,8 @@ def add_version_header(tc):
363363
"name": "__cpp_lib_constexpr_new",
364364
"values": {"c++26": 202406}, # P2747R2 constexpr placement new
365365
"headers": ["new"],
366-
"unimplemented": True,
366+
"test_suite_guard": "!defined(_LIBCPP_ABI_VCRUNTIME)",
367+
"libcxx_guard": "!defined(_LIBCPP_ABI_VCRUNTIME)",
367368
},
368369
{
369370
"name": "__cpp_lib_constexpr_numeric",

0 commit comments

Comments
 (0)