-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++] P2747R2: constexpr
placement new (library part)
#105768
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-libcxx Author: A. Jiang (frederick-vs-ja) ChangesPaper link: https://wg21.link/P2747R2 The library changes affect direct Drive-by: Formatting the whole Closes #105427. Full diff: https://github.com/llvm/llvm-project/pull/105768.diff 12 Files Affected:
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index a1506e115fe70f..8a429ddd476010 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -404,7 +404,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_bitset`` ``202306L``
---------------------------------------------------------- -----------------
- ``__cpp_lib_constexpr_new`` *unimplemented*
+ ``__cpp_lib_constexpr_new`` ``202406L``
---------------------------------------------------------- -----------------
``__cpp_lib_constrained_equality`` *unimplemented*
---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index fe9f4c1973cdb4..d048ab32d1f130 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -38,7 +38,7 @@ What's New in Libc++ 20.0.0?
Implemented Papers
------------------
-- TODO
+- P2747R2 - ``constexpr`` placement new
Improvements and New Features
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index dd62bcc2555ffc..bfb5e34da458d4 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -63,7 +63,7 @@
"`P2642R6 <https://wg21.link/P2642R6>`__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","","",""
"`P3029R1 <https://wg21.link/P3029R1>`__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19.0",""
"","","","","",""
-"`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","","",""
+"`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","|Complete|","20.0",""
"`P2997R1 <https://wg21.link/P2997R1>`__","Removing the common reference requirement from the indirectly invocable concepts","2024-06 (St. Louis)","|Complete| [#note-P2997R1]_","19.0",""
"`P2389R2 <https://wg21.link/P2389R2>`__","``dextents`` Index Type Parameter","2024-06 (St. Louis)","|Complete|","19.0",""
"`P3168R2 <https://wg21.link/P3168R2>`__","Give ``std::optional`` Range Support","2024-06 (St. Louis)","","","|ranges|"
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 392053a64a8dc1..9dd8d46b48d28f 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -788,6 +788,12 @@ typedef __char32_t char32_t;
# define _LIBCPP_CONSTEXPR_SINCE_CXX23
# endif
+# if _LIBCPP_STD_VER >= 26
+# define _LIBCPP_CONSTEXPR_SINCE_CXX26 constexpr
+# else
+# define _LIBCPP_CONSTEXPR_SINCE_CXX26
+# endif
+
# ifndef _LIBCPP_WEAK
# define _LIBCPP_WEAK __attribute__((__weak__))
# endif
diff --git a/libcxx/include/new b/libcxx/include/new
index 214dbc398530bb..dc48cf44a3e7a2 100644
--- a/libcxx/include/new
+++ b/libcxx/include/new
@@ -242,8 +242,14 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS void operator delete[](void* __p, std::size_t __sz,
# endif
# endif
-_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI void* operator new(std::size_t, void* __p) _NOEXCEPT { return __p; }
-_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI void* operator new[](std::size_t, void* __p) _NOEXCEPT { return __p; }
+_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void*
+operator new(std::size_t, void* __p) _NOEXCEPT {
+ return __p;
+}
+_LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void*
+operator new[](std::size_t, void* __p) _NOEXCEPT {
+ return __p;
+}
inline _LIBCPP_HIDE_FROM_ABI void operator delete(void*, void*) _NOEXCEPT {}
inline _LIBCPP_HIDE_FROM_ABI void operator delete[](void*, void*) _NOEXCEPT {}
diff --git a/libcxx/include/version b/libcxx/include/version
index fe64343eafbc9c..aeddda625fc960 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -510,7 +510,7 @@ __cpp_lib_void_t 201411L <type_traits>
# undef __cpp_lib_bind_front
# define __cpp_lib_bind_front 202306L
# define __cpp_lib_bitset 202306L
-// # define __cpp_lib_constexpr_new 202406L
+# define __cpp_lib_constexpr_new 202406L
// # define __cpp_lib_constrained_equality 202403L
// # define __cpp_lib_copyable_function 202306L
// # define __cpp_lib_debugging 202311L
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new.pass.cpp
index b857b397fc83e4..3e48a3634533a5 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new.pass.cpp
@@ -15,19 +15,30 @@
int A_constructed = 0;
-struct A
-{
- A() {++A_constructed;}
- ~A() {--A_constructed;}
+struct A {
+ A() { ++A_constructed; }
+ ~A() { --A_constructed; }
};
-int main(int, char**)
-{
- char buf[sizeof(A)];
+TEST_CONSTEXPR_CXX26 void test_direct_call() {
+ assert(::operator new(sizeof(int), &A_constructed) == &A_constructed);
- A* ap = new(buf) A;
- assert((char*)ap == buf);
- assert(A_constructed == 1);
+ char ch = '*';
+ assert(::operator new(1, &ch) == &ch);
+ assert(ch == '*');
+}
+
+#if TEST_STD_VER >= 26
+static_assert((test_direct_call(), true));
+#endif
+
+int main(int, char**) {
+ char buf[sizeof(A)];
+
+ A* ap = new (buf) A;
+ assert((char*)ap == buf);
+ assert(A_constructed == 1);
+ test_direct_call();
return 0;
}
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new_array.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new_array.pass.cpp
index 99a5442b6fb1f8..d318e338185c7e 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new_array.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.placement/new_array.pass.cpp
@@ -15,23 +15,34 @@
int A_constructed = 0;
-struct A
-{
- A() {++A_constructed;}
- ~A() {--A_constructed;}
+struct A {
+ A() { ++A_constructed; }
+ ~A() { --A_constructed; }
};
-int main(int, char**)
-{
- const std::size_t Size = 3;
- // placement new might require additional space.
- const std::size_t ExtraSize = 64;
- char buf[Size*sizeof(A) + ExtraSize];
+TEST_CONSTEXPR_CXX26 void test_direct_call() {
+ assert(::operator new[](sizeof(int), &A_constructed) == &A_constructed);
- A* ap = new(buf) A[Size];
- assert((char*)ap >= buf);
- assert((char*)ap < (buf + ExtraSize));
- assert(A_constructed == Size);
+ char ch = '*';
+ assert(::operator new[](1, &ch) == &ch);
+ assert(ch == '*');
+}
+
+#if TEST_STD_VER >= 26
+static_assert((test_direct_call(), true));
+#endif
+
+int main(int, char**) {
+ const std::size_t Size = 3;
+ // placement new might require additional space.
+ const std::size_t ExtraSize = 64;
+ char buf[Size * sizeof(A) + ExtraSize];
+
+ A* ap = new (buf) A[Size];
+ assert((char*)ap >= buf);
+ assert((char*)ap < (buf + ExtraSize));
+ assert(A_constructed == Size);
+ test_direct_call();
return 0;
}
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.compile.pass.cpp
index 17c1bd71eee675..e6308ae36085ca 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.compile.pass.cpp
@@ -171,17 +171,11 @@
#elif TEST_STD_VER > 23
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_constexpr_new
-# error "__cpp_lib_constexpr_new should be defined in c++26"
-# endif
-# if __cpp_lib_constexpr_new != 202406L
-# error "__cpp_lib_constexpr_new should have the value 202406L in c++26"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_constexpr_new
-# error "__cpp_lib_constexpr_new should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_constexpr_new
+# error "__cpp_lib_constexpr_new should be defined in c++26"
+# endif
+# if __cpp_lib_constexpr_new != 202406L
+# error "__cpp_lib_constexpr_new should have the value 202406L in c++26"
# endif
# if TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index b8bad696f1bae0..4ddd35ddff23f1 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -6554,17 +6554,11 @@
# error "__cpp_lib_constexpr_memory should have the value 202202L in c++26"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_constexpr_new
-# error "__cpp_lib_constexpr_new should be defined in c++26"
-# endif
-# if __cpp_lib_constexpr_new != 202406L
-# error "__cpp_lib_constexpr_new should have the value 202406L in c++26"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_constexpr_new
-# error "__cpp_lib_constexpr_new should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_constexpr_new
+# error "__cpp_lib_constexpr_new should be defined in c++26"
+# endif
+# if __cpp_lib_constexpr_new != 202406L
+# error "__cpp_lib_constexpr_new should have the value 202406L in c++26"
# endif
# ifndef __cpp_lib_constexpr_numeric
diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index e96208c85d1d24..b52baaeaf139a9 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -184,6 +184,12 @@
# define TEST_CONSTEXPR_CXX23
#endif
+#if TEST_STD_VER >= 26
+# define TEST_CONSTEXPR_CXX26 constexpr
+#else
+# define TEST_CONSTEXPR_CXX26
+#endif
+
#define TEST_ALIGNAS_TYPE(...) TEST_ALIGNAS(TEST_ALIGNOF(__VA_ARGS__))
#if !TEST_HAS_FEATURE(cxx_rtti) && !defined(__cpp_rtti) \
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index b041b08f02aac5..a4404380851578 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -363,7 +363,6 @@ def add_version_header(tc):
"name": "__cpp_lib_constexpr_new",
"values": {"c++26": 202406}, # P2747R2 constexpr placement new
"headers": ["new"],
- "unimplemented": True,
},
{
"name": "__cpp_lib_constexpr_numeric",
|
@@ -63,7 +63,7 @@ | |||
"`P2642R6 <https://wg21.link/P2642R6>`__","Padded ``mdspan`` layouts","2024-03 (Tokyo)","","","" | |||
"`P3029R1 <https://wg21.link/P3029R1>`__","Better ``mdspan``'s CTAD","2024-03 (Tokyo)","|Complete|","19.0","" | |||
"","","","","","" | |||
"`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","","","" | |||
"`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","|Complete|","20.0","" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add some notes that only the library part is implemented?
Edit: Possibly no, as the compiler changes will be done soon are already complete.
aaf423b
to
55f75d8
Compare
@@ -510,7 +510,9 @@ __cpp_lib_void_t 201411L <type_traits> | |||
# undef __cpp_lib_bind_front | |||
# define __cpp_lib_bind_front 202306L | |||
# define __cpp_lib_bitset 202306L | |||
// # define __cpp_lib_constexpr_new 202406L | |||
# if !defined(_LIBCPP_ABI_VCRUNTIME) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want a check for __cpp_constexpr >= 202406L
here too? constexpr operator new
has been valid since C++23 but isn't usable without compiler support, and users might check defined(__cpp_lib_constexpr_new)
instead of defined(__cpp_lib_constexpr_new) && __cpp_constexpr >= 202406L
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want a check for
__cpp_constexpr >= 202406L
here too?constexpr operator new
has been valid since C++23 but isn't usable without compiler support,
I'm pretty sure that constexpr operator new
in this paper doesn't require any constexpr feature after C++11. So the library changes don't require any change in the compiler.
and users might check
defined(__cpp_lib_constexpr_new)
instead ofdefined(__cpp_lib_constexpr_new) && __cpp_constexpr >= 202406L
I don't think it's meaningful to check __cpp_lib_constexpr_new
. The approach for the core part in #104586 doesn't require library changes.
In other words, under Clang's current approach for constexpr placement new, the core and library changes are independent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your right, I was thinking that operator new
could never be called in a constant expression, which might have been ill-formed NDR before C++23, but I forgot it could just be called directly operator new(1zu, p)
without a new-expression. Which I guess is the only thing this patch adds support for with clang.
Looks like the GCC implementation does check if operator new
is marked constexpr
: https://godbolt.org/z/hYaYYvaKc so this is needed for GCC at least.
55f75d8
to
eba7eb7
Compare
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`.
eba7eb7
to
354a874
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly LGTM but I have a few questions.
Paper link: https://wg21.link/P2747R2
The library changes affect direct
operator new
andoperator new[]
calls even when the core language changes are absent.The changes are not available for MS ABI because the
operator new
andoperator new[]
are from VCRuntime's<vcruntime_new.h>
.Notes for actual placement-new in constant evaluation:
operator new
/operator new[]
in constant evaluation ([Clang] Implement P2747 constexpr placement new #104586).operator new
/operator new[]
to beconstexpr
(gcc-mirror/gcc@afa3a4a).Drive-by: Formatting the whole
new.pass.cpp
andnew_array.pass.cpp
.Closes #105427.