-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[libc++] Make forward_list constexpr as part of P3372R3 #129435
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
base: main
Are you sure you want to change the base?
Conversation
7e3dd4c
to
e8ec4ce
Compare
✅ With the latest revision this PR passed the Python code formatter. |
dde423e
to
57338e2
Compare
@llvm/pr-subscribers-libcxx Author: Peng Liu (winner245) ChangesFixes #128658. Patch is 165.20 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/129435.diff 76 Files Affected:
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index dcf9838edd74b..5ac25a69ac52e 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -416,6 +416,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_bitset`` ``202306L``
---------------------------------------------------------- -----------------
+ ``__cpp_lib_constexpr_forward_list`` ``202502L``
+ ---------------------------------------------------------- -----------------
``__cpp_lib_constexpr_new`` ``202406L``
---------------------------------------------------------- -----------------
``__cpp_lib_constrained_equality`` *unimplemented*
diff --git a/libcxx/include/__memory/allocation_guard.h b/libcxx/include/__memory/allocation_guard.h
index 66edcd92ed618..2fc485f4ed0ed 100644
--- a/libcxx/include/__memory/allocation_guard.h
+++ b/libcxx/include/__memory/allocation_guard.h
@@ -49,24 +49,26 @@ struct __allocation_guard {
using _Size _LIBCPP_NODEBUG = typename allocator_traits<_Alloc>::size_type;
template <class _AllocT> // we perform the allocator conversion inside the constructor
- _LIBCPP_HIDE_FROM_ABI explicit __allocation_guard(_AllocT __alloc, _Size __n)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __allocation_guard(_AllocT __alloc, _Size __n)
: __alloc_(std::move(__alloc)),
__n_(__n),
__ptr_(allocator_traits<_Alloc>::allocate(__alloc_, __n_)) // initialization order is important
{}
- _LIBCPP_HIDE_FROM_ABI ~__allocation_guard() _NOEXCEPT { __destroy(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI ~__allocation_guard() _NOEXCEPT { __destroy(); }
- _LIBCPP_HIDE_FROM_ABI __allocation_guard(const __allocation_guard&) = delete;
- _LIBCPP_HIDE_FROM_ABI __allocation_guard(__allocation_guard&& __other) _NOEXCEPT
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __allocation_guard(const __allocation_guard&) = delete;
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __allocation_guard(__allocation_guard&& __other) _NOEXCEPT
: __alloc_(std::move(__other.__alloc_)),
__n_(__other.__n_),
__ptr_(__other.__ptr_) {
__other.__ptr_ = nullptr;
}
- _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(const __allocation_guard& __other) = delete;
- _LIBCPP_HIDE_FROM_ABI __allocation_guard& operator=(__allocation_guard&& __other) _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __allocation_guard&
+ operator=(const __allocation_guard& __other) = delete;
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __allocation_guard&
+ operator=(__allocation_guard&& __other) _NOEXCEPT {
if (std::addressof(__other) != this) {
__destroy();
@@ -79,17 +81,17 @@ struct __allocation_guard {
return *this;
}
- _LIBCPP_HIDE_FROM_ABI _Pointer
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI _Pointer
__release_ptr() _NOEXCEPT { // not called __release() because it's a keyword in objective-c++
_Pointer __tmp = __ptr_;
__ptr_ = nullptr;
return __tmp;
}
- _LIBCPP_HIDE_FROM_ABI _Pointer __get() const _NOEXCEPT { return __ptr_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI _Pointer __get() const _NOEXCEPT { return __ptr_; }
private:
- _LIBCPP_HIDE_FROM_ABI void __destroy() _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __destroy() _NOEXCEPT {
if (__ptr_ != nullptr) {
allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __n_);
}
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index 8c688611d5ee2..aca31bc37dc1d 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -295,9 +295,14 @@ struct __forward_node_traits {
"the _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB macro to silence this diagnostic.");
# endif
- _LIBCPP_HIDE_FROM_ABI static __begin_node_pointer __as_iter_node(__begin_node_pointer __p) { return __p; }
- _LIBCPP_HIDE_FROM_ABI static __begin_node_pointer __as_iter_node(__node_pointer __p) {
- return static_cast<__begin_node_pointer>(static_cast<__void_pointer>(__p));
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI static __begin_node_pointer
+ __as_iter_node(__begin_node_pointer __p) {
+ return __p;
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI static __begin_node_pointer __as_iter_node(__node_pointer __p) {
+ // return static_cast<__begin_node_pointer>(static_cast<__void_pointer>(__p));
+ return __p ? pointer_traits<__begin_node_pointer>::pointer_to(*__p) // fancy pointer
+ : static_cast<__begin_node_pointer>(nullptr);
}
};
@@ -308,11 +313,13 @@ struct __forward_begin_node {
pointer __next_;
- _LIBCPP_HIDE_FROM_ABI __forward_begin_node() : __next_(nullptr) {}
- _LIBCPP_HIDE_FROM_ABI explicit __forward_begin_node(pointer __n) : __next_(__n) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_begin_node() : __next_(nullptr) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_begin_node(pointer __n) : __next_(__n) {}
- _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __next_as_begin() const {
- return static_cast<__begin_node_pointer>(__next_);
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __next_as_begin() const {
+ // return static_cast<__begin_node_pointer>(__next_);
+ return __next_ ? pointer_traits<__begin_node_pointer>::pointer_to(*__next_) // fancy pointer
+ : static_cast<__begin_node_pointer>(nullptr);
}
};
@@ -336,18 +343,20 @@ private:
};
public:
- _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; }
# else
private:
_ALIGNAS_TYPE(_Tp) char __buffer_[sizeof(_Tp)];
public:
- _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() {
+ return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_));
+ }
# endif
- _LIBCPP_HIDE_FROM_ABI explicit __forward_list_node(_NodePtr __next) : _Base(__next) {}
- _LIBCPP_HIDE_FROM_ABI ~__forward_list_node() {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_node(_NodePtr __next) : _Base(__next) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI ~__forward_list_node() {}
};
template <class _Tp, class _Alloc = allocator<_Tp> >
@@ -358,25 +367,29 @@ class _LIBCPP_TEMPLATE_VIS __forward_list_const_iterator;
template <class _NodePtr>
class _LIBCPP_TEMPLATE_VIS __forward_list_iterator {
typedef __forward_node_traits<_NodePtr> __traits;
+ typedef typename __traits::__node_type __node_type;
typedef typename __traits::__node_pointer __node_pointer;
typedef typename __traits::__begin_node_pointer __begin_node_pointer;
typedef typename __traits::__void_pointer __void_pointer;
__begin_node_pointer __ptr_;
- _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const {
- return static_cast<__begin_node_pointer>(static_cast<__void_pointer>(__ptr_));
- }
- _LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const {
- return static_cast<__node_pointer>(static_cast<__void_pointer>(__ptr_));
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const { return __ptr_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const {
+ // return static_cast<__node_pointer>(static_cast<__void_pointer>(__ptr_));
+ return __ptr_ ? pointer_traits<__node_pointer>::pointer_to(
+ const_cast<__node_type&>(static_cast<const __node_type&>(*__ptr_))) // fancy pointer
+ : static_cast<__node_pointer>(nullptr);
}
- _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(nullptr_t) _NOEXCEPT : __ptr_(nullptr) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(nullptr_t) _NOEXCEPT
+ : __ptr_(nullptr) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26
_LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(__begin_node_pointer __p) _NOEXCEPT
: __ptr_(__traits::__as_iter_node(__p)) {}
- _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(__node_pointer __p) _NOEXCEPT
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(__node_pointer __p) _NOEXCEPT
: __ptr_(__traits::__as_iter_node(__p)) {}
template <class, class>
@@ -391,27 +404,31 @@ public:
typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
typedef __rebind_pointer_t<__node_pointer, value_type> pointer;
- _LIBCPP_HIDE_FROM_ABI __forward_list_iterator() _NOEXCEPT : __ptr_(nullptr) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_iterator() _NOEXCEPT : __ptr_(nullptr) {}
- _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_unsafe_node_pointer()->__get_value(); }
- _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
+ return __get_unsafe_node_pointer()->__get_value();
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
return pointer_traits<pointer>::pointer_to(__get_unsafe_node_pointer()->__get_value());
}
- _LIBCPP_HIDE_FROM_ABI __forward_list_iterator& operator++() {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_iterator& operator++() {
__ptr_ = __traits::__as_iter_node(__ptr_->__next_);
return *this;
}
- _LIBCPP_HIDE_FROM_ABI __forward_list_iterator operator++(int) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_iterator operator++(int) {
__forward_list_iterator __t(*this);
++(*this);
return __t;
}
- friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __forward_list_iterator& __x, const __forward_list_iterator& __y) {
+ friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool
+ operator==(const __forward_list_iterator& __x, const __forward_list_iterator& __y) {
return __x.__ptr_ == __y.__ptr_;
}
- friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __forward_list_iterator& __x, const __forward_list_iterator& __y) {
+ friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool
+ operator!=(const __forward_list_iterator& __x, const __forward_list_iterator& __y) {
return !(__x == __y);
}
};
@@ -429,18 +446,22 @@ class _LIBCPP_TEMPLATE_VIS __forward_list_const_iterator {
__begin_node_pointer __ptr_;
- _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const {
- return static_cast<__begin_node_pointer>(static_cast<__void_pointer>(__ptr_));
- }
- _LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const {
- return static_cast<__node_pointer>(static_cast<__void_pointer>(__ptr_));
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const { return __ptr_; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const {
+ // return static_cast<__node_pointer>(static_cast<__void_pointer>(__ptr_));
+ return __ptr_ ? pointer_traits<__node_pointer>::pointer_to(
+ const_cast<__node_type&>(static_cast<const __node_type&>(*__ptr_))) // fancy pointer
+ : static_cast<__node_pointer>(nullptr);
}
- _LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(nullptr_t) _NOEXCEPT : __ptr_(nullptr) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(nullptr_t) _NOEXCEPT
+ : __ptr_(nullptr) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26
_LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(__begin_node_pointer __p) _NOEXCEPT
: __ptr_(__traits::__as_iter_node(__p)) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26
_LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(__node_pointer __p) _NOEXCEPT
: __ptr_(__traits::__as_iter_node(__p)) {}
@@ -454,30 +475,32 @@ public:
typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
typedef __rebind_pointer_t<__node_pointer, const value_type> pointer;
- _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator() _NOEXCEPT : __ptr_(nullptr) {}
- _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator(__forward_list_iterator<__node_pointer> __p) _NOEXCEPT
- : __ptr_(__p.__ptr_) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator() _NOEXCEPT : __ptr_(nullptr) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI
+ __forward_list_const_iterator(__forward_list_iterator<__node_pointer> __p) _NOEXCEPT : __ptr_(__p.__ptr_) {}
- _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_unsafe_node_pointer()->__get_value(); }
- _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
+ return __get_unsafe_node_pointer()->__get_value();
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
return pointer_traits<pointer>::pointer_to(__get_unsafe_node_pointer()->__get_value());
}
- _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator& operator++() {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator& operator++() {
__ptr_ = __traits::__as_iter_node(__ptr_->__next_);
return *this;
}
- _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator operator++(int) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_const_iterator operator++(int) {
__forward_list_const_iterator __t(*this);
++(*this);
return __t;
}
- friend _LIBCPP_HIDE_FROM_ABI bool
+ friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool
operator==(const __forward_list_const_iterator& __x, const __forward_list_const_iterator& __y) {
return __x.__ptr_ == __y.__ptr_;
}
- friend _LIBCPP_HIDE_FROM_ABI bool
+ friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool
operator!=(const __forward_list_const_iterator& __x, const __forward_list_const_iterator& __y) {
return !(__x == __y);
}
@@ -501,48 +524,51 @@ protected:
_LIBCPP_COMPRESSED_PAIR(__begin_node, __before_begin_, __node_allocator, __alloc_);
- _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __before_begin() _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __before_begin() _NOEXCEPT {
return pointer_traits<__begin_node_pointer>::pointer_to(__before_begin_);
}
- _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __before_begin() const _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __before_begin() const _NOEXCEPT {
return pointer_traits<__begin_node_pointer>::pointer_to(const_cast<__begin_node&>(__before_begin_));
}
typedef __forward_list_iterator<__node_pointer> iterator;
typedef __forward_list_const_iterator<__node_pointer> const_iterator;
- _LIBCPP_HIDE_FROM_ABI __forward_list_base() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __forward_list_base()
+ _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value)
: __before_begin_(__begin_node()) {}
- _LIBCPP_HIDE_FROM_ABI explicit __forward_list_base(const allocator_type& __a)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_base(const allocator_type& __a)
: __before_begin_(__begin_node()), __alloc_(__node_allocator(__a)) {}
- _LIBCPP_HIDE_FROM_ABI explicit __forward_list_base(const __node_allocator& __a)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __forward_list_base(const __node_allocator& __a)
: __before_begin_(__begin_node()), __alloc_(__a) {}
public:
# ifndef _LIBCPP_CXX03_LANG
- _LIBCPP_HIDE_FROM_ABI
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI
__forward_list_base(__forward_list_base&& __x) noexcept(is_nothrow_move_constructible<__node_allocator>::value);
- _LIBCPP_HIDE_FROM_ABI __forward_list_base(__forward_list_base&& __x, const allocator_type& __a);
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI
+ __forward_list_base(__forward_list_base&& __x, const allocator_type& __a);
# endif // _LIBCPP_CXX03_LANG
__forward_list_base(const __forward_list_base&) = delete;
__forward_list_base& operator=(const __forward_list_base&) = delete;
- _LIBCPP_HIDE_FROM_ABI ~__forward_list_base();
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI ~__forward_list_base();
protected:
- _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __forward_list_base& __x) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __forward_list_base& __x) {
__copy_assign_alloc(__x, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());
}
- _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__forward_list_base& __x)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__forward_list_base& __x)
_NOEXCEPT_(!__node_traits::propagate_on_container_move_assignment::value ||
is_nothrow_move_assignable<__node_allocator>::value) {
__move_assign_alloc(__x, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>());
}
template <class... _Args>
- _LIBCPP_HIDE_FROM_ABI __node_pointer __create_node(__node_pointer __next, _Args&&... __args) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __node_pointer
+ __create_node(__node_pointer __next, _Args&&... __args) {
__allocation_guard<__node_allocator> __guard(__alloc_, 1);
// Begin the lifetime of the node itself. Note that this doesn't begin the lifetime of the value
// held inside the node, since we need to use the allocator's construct() method for that.
@@ -557,7 +583,7 @@ protected:
return __guard.__release_ptr();
}
- _LIBCPP_HIDE_FROM_ABI void __delete_node(__node_pointer __node) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __delete_node(__node_pointer __node) {
// For the same reason as above, we use the allocator's destroy() method for the value_type,
// but not for the node itself.
__node_traits::destroy(__alloc_, std::addressof(__node->__get_value()));
@@ -566,7 +592,7 @@ protected:
}
public:
- _LIBCPP_HIDE_FROM_ABI void swap(__forward_list_base& __x)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void swap(__forward_list_base& __x)
# if _LIBCPP_STD_VER >= 14
_NOEXCEPT;
# else
@@ -574,18 +600,21 @@ public:
# endif
protected:
- _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
private:
- _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __forward_list_base&, false_type) {}
- _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __forward_list_base& __x, true_type) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __forward_list_base&, false_type) {
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void
+ __copy_assign_alloc(const __forward_list_base& __x, true_type) {
if (__alloc_ != __x.__alloc_)
clear();
__alloc_ = __x.__alloc_;
}
- _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__forward_list_base&, false_type) _NOEXCEPT {}
- _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__forward_list_base& __x, true_type)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void
+ __move_assign_alloc(__forward_list_base&, false_type) _NOEXCEPT {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__forward_list_base& __x, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {
__alloc_ = std::move(__x.__alloc_);
}
@@ -594,14 +623,15 @@ private:
# ifndef _LIBCPP_CXX03_LANG
template <class _Tp, class _Alloc>
-inline __forward_...
[truncated]
|
57338e2
to
c6a1c3d
Compare
7307e6f
to
ca3436e
Compare
I've just updated this patch mainly for GCC to correctly handle fancy pointers in constant evaluations. Before this update, the patch passed all stage 1 CIs except for GCC: stage1 (generic-gcc, gcc-14, g++-14). The reason for the failure is that the In Clang, To fix this, I take a somewhat tedious approach, which manually expands |
This is LWG3454 whose proposed resolution is speculatively implemented by libc++ and MSVC STL.
But how did this happen? libc++ is consistently marking that function |
libcxx/include/forward_list
Outdated
_LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI static __begin_node_pointer __as_iter_node(__node_pointer __p) { | ||
# ifdef _LIBCPP_CXX03_LANG | ||
return static_cast<__begin_node_pointer>(__p); | ||
# else | ||
if constexpr (std::is_pointer<__begin_node_pointer>::value) { | ||
return static_cast<__begin_node_pointer>(__p); | ||
} else { | ||
return __p ? __begin_node_pointer::pointer_to(*static_cast<__begin_node*>(std::addressof(*__p))) | ||
: static_cast<__begin_node_pointer>(nullptr); | ||
} | ||
# endif |
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.
I think it would be helpful to introduce __static_fancy_pointer_cast
function template (in <__memory/pointer_traits.h>
or a new internal header). The current changes don't seem correct to me (as libc++ backports C++11 fancy pointer mechanisms to C++03 mode). Let's see whether putting it into free functions would help.
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.
Thank you for the suggestion! Adding a __static_fancy_pointer_cast
function template indeed makes a lot of sense, especially since it could also be beneficial for making <list>
constexpr
. Following your suggestion, I have introduced a __static_fancy_pointer_cast
function template in <__memory/pointer_traits.h>
.
Thanks for your clarification! From what you said, I just realized that the problem I mentioned might not exist. I was debugging the GCC CI failure on my local platform using GCC, and I encountered an error with After a bit more investigation of c6a1c3d, I realized that the GCC CI failure might be most likely due to a missing cast in _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI
static __begin_node_pointer __as_iter_node(__node_pointer __p) {
return __p ? pointer_traits<__begin_node_pointer>::pointer_to(*__p)
: static_cast<__begin_node_pointer>(nullptr);
} For GCC constant evaluation, I need an extra _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI
static __begin_node_pointer __as_iter_node(__node_pointer __p) {
return __p ? pointer_traits<__begin_node_pointer>::pointer_to(*static_cast<__begin_node*>(std::addressof(*__p)))
: static_cast<__begin_node_pointer>(nullptr);
} My latest push already included this cast, which actually fixed my real issue with the GCC CI. So maybe I should switch back to |
03ebbf9
to
60984d6
Compare
libcxx/include/forward_list
Outdated
_LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI static __begin_node_pointer | ||
__as_iter_node(__begin_node_pointer __p) { | ||
return __p; | ||
} | ||
_LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI static __begin_node_pointer __as_iter_node(__node_pointer __p) { | ||
return std::__static_fancy_pointer_cast<__begin_node_pointer>(__p); |
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.
Why did this change? What's incorrect about the old version?
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.
The old version was roughly equivalent to static_cast<Base*>(static_cast<void*>(ptr_to_derived))
(except that it works for fancy pointers), which didn't work in constant evaluation and possibly had UB (Godbolt link).
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.
I'm quite certain this didn't have UB. It's defined behaviour to reinterpret_cast<Base*>(derived)
if Base
is the first object after all. Anyways, I think we'd be better off if we don't try to do the round tripping through a void*
if we can get away with it (which IMO is quite reasonable). That would allow us to collapse the entire __as_iter_node
construct. Could we do that in a separate patch and rebase this on top to simplify this whole thing?
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.
The old version fails in constant evaluation. I fixed it without resorting to the void*
pointer. Given that the redundant __as_iter_node
identity cast has already been fixed for forward_list
, is there anything else that needs to be addressed before this patch is landed? I've just rebased the patch to resolve conflicts due to the removal of __as_iter_node
.
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.
@philnik777 I am not sure if I understood your comment correctly in the first place. Were you suggesting me clean up the unnecessary static_cast
s before this one? If so, I've submitted a separate patch #130310 for that.
60984d6
to
cb8d353
Compare
cb8d353
to
b8c5630
Compare
b8c5630
to
ffa779e
Compare
Fixes #128658.