Skip to content

Commit eba7eb7

Browse files
[libc++] P2747R2: constexpr placement new (library part)
Paper link: https://wg21.link/P2747R2 The library changes affect direct `operator new` and `operator new[]` calls even when the core language changes are absent. The approach of Clang for "actual" placement new in constant evaluation doesn't depend on the library changes. The changes are not available for MS ABI because the `operator new` and `operator new[]` are from VCRuntime's `<vcruntime_new.h>`. Drive-by: formatting the whole `new.pass.cpp` and `new_array.pass.cpp`.
1 parent 1193f7d commit eba7eb7

File tree

12 files changed

+88
-37
lines changed

12 files changed

+88
-37
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ Status
404404
---------------------------------------------------------- -----------------
405405
``__cpp_lib_bitset`` ``202306L``
406406
---------------------------------------------------------- -----------------
407-
``__cpp_lib_constexpr_new`` *unimplemented*
407+
``__cpp_lib_constexpr_new`` ``202406L``
408408
---------------------------------------------------------- -----------------
409409
``__cpp_lib_constrained_equality`` *unimplemented*
410410
---------------------------------------------------------- -----------------

libcxx/docs/ReleaseNotes/20.rst

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

41-
- TODO
41+
- P2747R2 - ``constexpr`` placement new (`Github <https://github.com/llvm/llvm-project/issues/105427>`__)
4242

4343

4444
Improvements and New Features

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: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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
@@ -510,7 +510,9 @@ __cpp_lib_void_t 201411L <type_traits>
510510
# undef __cpp_lib_bind_front
511511
# define __cpp_lib_bind_front 202306L
512512
# define __cpp_lib_bitset 202306L
513-
// # define __cpp_lib_constexpr_new 202406L
513+
# if !defined(_LIBCPP_ABI_VCRUNTIME)
514+
# define __cpp_lib_constexpr_new 202406L
515+
# endif
514516
// # define __cpp_lib_constrained_equality 202403L
515517
// # define __cpp_lib_copyable_function 202306L
516518
// # 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
@@ -6554,16 +6554,16 @@
65546554
# error "__cpp_lib_constexpr_memory should have the value 202202L in c++26"
65556555
# endif
65566556

6557-
# if !defined(_LIBCPP_VERSION)
6557+
# if !defined(_LIBCPP_ABI_VCRUNTIME)
65586558
# ifndef __cpp_lib_constexpr_new
65596559
# error "__cpp_lib_constexpr_new should be defined in c++26"
65606560
# endif
65616561
# if __cpp_lib_constexpr_new != 202406L
65626562
# error "__cpp_lib_constexpr_new should have the value 202406L in c++26"
65636563
# endif
6564-
# else // _LIBCPP_VERSION
6564+
# else
65656565
# ifdef __cpp_lib_constexpr_new
6566-
# error "__cpp_lib_constexpr_new should not be defined because it is unimplemented in libc++!"
6566+
# error "__cpp_lib_constexpr_new should not be defined when the requirement '!defined(_LIBCPP_ABI_VCRUNTIME)' is not met!"
65676567
# endif
65686568
# endif
65696569

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)