[libc++] Make list constexpr as part of P3372R3#129799
Conversation
8c3656b to
b535bbe
Compare
|
@llvm/pr-subscribers-libcxx Author: Peng Liu (winner245) ChangesFixes #128659. Patch is 188.07 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/129799.diff 73 Files Affected:
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index dcf9838edd74b..6cc5cef2211a7 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -416,6 +416,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_bitset`` ``202306L``
---------------------------------------------------------- -----------------
+ ``__cpp_lib_constexpr_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/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h
index afe3d1bf8a2de..9626922ca3c2f 100644
--- a/libcxx/include/__memory/pointer_traits.h
+++ b/libcxx/include/__memory/pointer_traits.h
@@ -302,6 +302,14 @@ concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p
#endif
+template <class _PtrTo, class _PtrFrom>
+_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _PtrTo __static_fancy_pointer_cast(const _PtrFrom& __p) {
+ using __ptr_traits = pointer_traits<_PtrTo>;
+ using __element_type = typename __ptr_traits::element_type;
+ return __p ? __ptr_traits::pointer_to(*static_cast<__element_type*>(std::addressof(*__p)))
+ : static_cast<_PtrTo>(nullptr);
+}
+
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
diff --git a/libcxx/include/list b/libcxx/include/list
index 1285174f1c384..e6ecce38dc023 100644
--- a/libcxx/include/list
+++ b/libcxx/include/list
@@ -287,10 +287,14 @@ struct __list_node_pointer_traits {
"_LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB macro to silence this diagnostic.");
# endif
- static _LIBCPP_HIDE_FROM_ABI __base_pointer __unsafe_link_pointer_cast(__base_pointer __p) { return __p; }
+ static _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __base_pointer
+ __unsafe_link_pointer_cast(__base_pointer __p) {
+ return __p;
+ }
- static _LIBCPP_HIDE_FROM_ABI __base_pointer __unsafe_link_pointer_cast(__node_pointer __p) {
- return static_cast<__base_pointer>(static_cast<_VoidPtr>(__p));
+ static _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __base_pointer
+ __unsafe_link_pointer_cast(__node_pointer __p) {
+ return std::__static_fancy_pointer_cast<__base_pointer>(__p);
}
};
@@ -303,14 +307,20 @@ struct __list_node_base {
__base_pointer __prev_;
__base_pointer __next_;
- _LIBCPP_HIDE_FROM_ABI __list_node_base() : __prev_(__self()), __next_(__self()) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_node_base() : __prev_(__self()), __next_(__self()) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26
_LIBCPP_HIDE_FROM_ABI explicit __list_node_base(__base_pointer __prev, __base_pointer __next)
: __prev_(__prev), __next_(__next) {}
- _LIBCPP_HIDE_FROM_ABI __base_pointer __self() { return pointer_traits<__base_pointer>::pointer_to(*this); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __base_pointer __self() {
+ return pointer_traits<__base_pointer>::pointer_to(*this);
+ }
- _LIBCPP_HIDE_FROM_ABI __node_pointer __as_node() { return static_cast<__node_pointer>(__self()); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __node_pointer __as_node() {
+ return pointer_traits<__node_pointer>::pointer_to(
+ *static_cast<typename pointer_traits<__node_pointer>::element_type*>(this));
+ }
};
template <class _Tp, class _VoidPtr>
@@ -325,7 +335,7 @@ 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:
@@ -338,10 +348,14 @@ public:
typedef __list_node_base<_Tp, _VoidPtr> __base;
typedef typename __base::__base_pointer __base_pointer;
- _LIBCPP_HIDE_FROM_ABI explicit __list_node(__base_pointer __prev, __base_pointer __next) : __base(__prev, __next) {}
- _LIBCPP_HIDE_FROM_ABI ~__list_node() {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __list_node(__base_pointer __prev, __base_pointer __next)
+ : __base(__prev, __next) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI ~__list_node() {}
- _LIBCPP_HIDE_FROM_ABI __base_pointer __as_link() { return __base::__self(); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __base_pointer __as_link() {
+ return pointer_traits<__base_pointer>::pointer_to(
+ *static_cast<typename pointer_traits<__base_pointer>::element_type*>(std::addressof(*this)));
+ }
};
template <class _Tp, class _Alloc = allocator<_Tp> >
@@ -358,7 +372,8 @@ class _LIBCPP_TEMPLATE_VIS __list_iterator {
__base_pointer __ptr_;
- _LIBCPP_HIDE_FROM_ABI explicit __list_iterator(__base_pointer __p) _NOEXCEPT : __ptr_(__p) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __list_iterator(__base_pointer __p) _NOEXCEPT
+ : __ptr_(__p) {}
template <class, class>
friend class list;
@@ -374,37 +389,41 @@ public:
typedef __rebind_pointer_t<_VoidPtr, value_type> pointer;
typedef typename pointer_traits<pointer>::difference_type difference_type;
- _LIBCPP_HIDE_FROM_ABI __list_iterator() _NOEXCEPT : __ptr_(nullptr) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_iterator() _NOEXCEPT : __ptr_(nullptr) {}
- _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __ptr_->__as_node()->__get_value(); }
- _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
+ return __ptr_->__as_node()->__get_value();
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
return pointer_traits<pointer>::pointer_to(__ptr_->__as_node()->__get_value());
}
- _LIBCPP_HIDE_FROM_ABI __list_iterator& operator++() {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_iterator& operator++() {
__ptr_ = __ptr_->__next_;
return *this;
}
- _LIBCPP_HIDE_FROM_ABI __list_iterator operator++(int) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_iterator operator++(int) {
__list_iterator __t(*this);
++(*this);
return __t;
}
- _LIBCPP_HIDE_FROM_ABI __list_iterator& operator--() {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_iterator& operator--() {
__ptr_ = __ptr_->__prev_;
return *this;
}
- _LIBCPP_HIDE_FROM_ABI __list_iterator operator--(int) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_iterator operator--(int) {
__list_iterator __t(*this);
--(*this);
return __t;
}
- friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __list_iterator& __x, const __list_iterator& __y) {
+ friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool
+ operator==(const __list_iterator& __x, const __list_iterator& __y) {
return __x.__ptr_ == __y.__ptr_;
}
- friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __list_iterator& __x, const __list_iterator& __y) {
+ friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool
+ operator!=(const __list_iterator& __x, const __list_iterator& __y) {
return !(__x == __y);
}
};
@@ -416,7 +435,8 @@ class _LIBCPP_TEMPLATE_VIS __list_const_iterator {
__base_pointer __ptr_;
- _LIBCPP_HIDE_FROM_ABI explicit __list_const_iterator(__base_pointer __p) _NOEXCEPT : __ptr_(__p) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI explicit __list_const_iterator(__base_pointer __p) _NOEXCEPT
+ : __ptr_(__p) {}
template <class, class>
friend class list;
@@ -430,39 +450,43 @@ public:
typedef __rebind_pointer_t<_VoidPtr, const value_type> pointer;
typedef typename pointer_traits<pointer>::difference_type difference_type;
- _LIBCPP_HIDE_FROM_ABI __list_const_iterator() _NOEXCEPT : __ptr_(nullptr) {}
- _LIBCPP_HIDE_FROM_ABI __list_const_iterator(const __list_iterator<_Tp, _VoidPtr>& __p) _NOEXCEPT
- : __ptr_(__p.__ptr_) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_const_iterator() _NOEXCEPT : __ptr_(nullptr) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI
+ __list_const_iterator(const __list_iterator<_Tp, _VoidPtr>& __p) _NOEXCEPT : __ptr_(__p.__ptr_) {}
- _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __ptr_->__as_node()->__get_value(); }
- _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
+ return __ptr_->__as_node()->__get_value();
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
return pointer_traits<pointer>::pointer_to(__ptr_->__as_node()->__get_value());
}
- _LIBCPP_HIDE_FROM_ABI __list_const_iterator& operator++() {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_const_iterator& operator++() {
__ptr_ = __ptr_->__next_;
return *this;
}
- _LIBCPP_HIDE_FROM_ABI __list_const_iterator operator++(int) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_const_iterator operator++(int) {
__list_const_iterator __t(*this);
++(*this);
return __t;
}
- _LIBCPP_HIDE_FROM_ABI __list_const_iterator& operator--() {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_const_iterator& operator--() {
__ptr_ = __ptr_->__prev_;
return *this;
}
- _LIBCPP_HIDE_FROM_ABI __list_const_iterator operator--(int) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_const_iterator operator--(int) {
__list_const_iterator __t(*this);
--(*this);
return __t;
}
- friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __list_const_iterator& __x, const __list_const_iterator& __y) {
+ friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool
+ operator==(const __list_const_iterator& __x, const __list_const_iterator& __y) {
return __x.__ptr_ == __y.__ptr_;
}
- friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __list_const_iterator& __x, const __list_const_iterator& __y) {
+ friend _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool
+ operator!=(const __list_const_iterator& __x, const __list_const_iterator& __y) {
return !(__x == __y);
}
};
@@ -503,43 +527,49 @@ protected:
__node_base __end_;
_LIBCPP_COMPRESSED_PAIR(size_type, __size_, __node_allocator, __node_alloc_);
- _LIBCPP_HIDE_FROM_ABI __base_pointer __end_as_link() const _NOEXCEPT {
- return __node_pointer_traits::__unsafe_link_pointer_cast(const_cast<__node_base&>(__end_).__self());
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __base_pointer __end_as_link() const _NOEXCEPT {
+ return pointer_traits<__base_pointer>::pointer_to(const_cast<__node_base&>(__end_));
}
- _LIBCPP_HIDE_FROM_ABI size_type __node_alloc_max_size() const _NOEXCEPT {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI size_type __node_alloc_max_size() const _NOEXCEPT {
return __node_alloc_traits::max_size(__node_alloc_);
}
- _LIBCPP_HIDE_FROM_ABI static void __unlink_nodes(__base_pointer __f, __base_pointer __l) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI static void
+ __unlink_nodes(__base_pointer __f, __base_pointer __l) _NOEXCEPT;
- _LIBCPP_HIDE_FROM_ABI __list_imp() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value);
- _LIBCPP_HIDE_FROM_ABI __list_imp(const allocator_type& __a);
- _LIBCPP_HIDE_FROM_ABI __list_imp(const __node_allocator& __a);
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_imp()
+ _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value);
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_imp(const allocator_type& __a);
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_imp(const __node_allocator& __a);
# ifndef _LIBCPP_CXX03_LANG
- _LIBCPP_HIDE_FROM_ABI __list_imp(__node_allocator&& __a) _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __list_imp(__node_allocator&& __a) _NOEXCEPT;
# endif
- _LIBCPP_HIDE_FROM_ABI ~__list_imp();
- _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
- _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __size_ == 0; }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI ~__list_imp();
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI bool empty() const _NOEXCEPT { return __size_ == 0; }
- _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__end_.__next_); }
- _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT { return const_iterator(__end_.__next_); }
- _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return iterator(__end_as_link()); }
- _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return const_iterator(__end_as_link()); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT { return iterator(__end_.__next_); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT {
+ return const_iterator(__end_.__next_);
+ }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT { return iterator(__end_as_link()); }
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT {
+ return const_iterator(__end_as_link());
+ }
- _LIBCPP_HIDE_FROM_ABI void swap(__list_imp& __c)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void swap(__list_imp& __c)
# if _LIBCPP_STD_VER >= 14
_NOEXCEPT;
# else
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<allocator_type>);
# endif
- _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp& __c) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp& __c) {
__copy_assign_alloc(
__c, integral_constant<bool, __node_alloc_traits::propagate_on_container_copy_assignment::value>());
}
- _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp& __c)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp& __c)
_NOEXCEPT_(!__node_alloc_traits::propagate_on_container_move_assignment::value ||
is_nothrow_move_assignable<__node_allocator>::value) {
__move_assign_alloc(
@@ -547,7 +577,8 @@ protected:
}
template <class... _Args>
- _LIBCPP_HIDE_FROM_ABI __node_pointer __create_node(__base_pointer __prev, __base_pointer __next, _Args&&... __args) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI __node_pointer
+ __create_node(__base_pointer __prev, __base_pointer __next, _Args&&... __args) {
__allocation_guard<__node_allocator> __guard(__node_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.
@@ -563,7 +594,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_alloc_traits::destroy(__node_alloc_, std::addressof(__node->__get_value()));
@@ -572,54 +603,57 @@ protected:
}
private:
- _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp& __c, true_type) {
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp& __c, true_type) {
if (__node_alloc_ != __c.__node_alloc_)
clear();
__node_alloc_ = __c.__node_alloc_;
}
- _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp&, false_type) {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __list_imp&, false_type) {}
- _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp& __c, true_type)
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp& __c, true_type)
_NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value) {
__node_alloc_ = std::move(__c.__node_alloc_);
}
- _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp&, false_type) _NOEXCEPT {}
+ _LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__list_imp&, false_type) _NOEXCEPT {}
};
// Unlink nodes [__f, __l]
template <class _Tp, class _Alloc>
-inline void __list_imp<_Tp, _Alloc>::__unlink_nodes(__base_pointer __f, __base_pointer __l) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX26 inline void
+__list_imp<_Tp, _Alloc>::__unlink_nodes(__base_pointer __f, __base_pointer __l) _NOEXCEPT {
__f->__prev_->__next_ = __l->__next_;
__l->__next_->__prev_ = __f->__prev_;
}
template <class _Tp, class _Alloc>
-inline __list_imp<_Tp, _Alloc>::__list_imp() _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value)
+_LIBCPP_CONSTEXPR_SINCE_CXX26 inline __list_imp<_Tp, _Alloc>::__list_imp()
+ _NOEXCEPT_(is_nothrow_default_constructible<__node_allocator>::value)
: __size_(0) {}
template <class _Tp, class _Alloc>
-...
[truncated]
|
d39dabf to
3e721b8
Compare
3e721b8 to
9694e9c
Compare
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
libcxx/include/list
Outdated
There was a problem hiding this comment.
| *static_cast<typename pointer_traits<__base_pointer>::element_type*>(std::addressof(*this))); | |
| *static_cast<typename pointer_traits<__base_pointer>::element_type*>(this)); |
That should be strictly simpler but equivalent?
There was a problem hiding this comment.
Yes, you are right, std::addressof(*this) == this given that this is a raw pointer (only for fancy pointers can std::addressof(*p) differ from p). I adopted your simplification, and then I realized that the cast expression can be further simplified as follows:
static_cast<typename pointer_traits<__base_pointer>::element_type*>(this) == static_cast<__base*>(this)
So the entire function __as_link() simplifies to return __base::__self(); (the original version we had) because inheritance would automatically cast this to a base this when calling a base member function.
There was a problem hiding this comment.
Once thing I don't fully understand is that once I made the aforementioned simplifications by avoiding the use of std::addressof(*this), i.e.,
simplifying
return pointer_traits<__base_pointer>::pointer_to(
*static_cast<typename pointer_traits<__base_pointer>::element_type*>(std::addressof(*this)));into
return pointer_traits<__base_pointer>::pointer_to(
*static_cast<typename pointer_traits<__base_pointer>::element_type*>(this));I got a consistent failure in stage1 (generic-gcc, gcc-15, g++-15):
# | /__w/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/__memory/allocator.h:118:24: error: deallocation of storage that was not previously allocated
# | 118 | ::operator delete(__p);
# | | ~~~~~~~~~~~~~~~~~^~~~~
This failure only happens with gcc (which I don't quite understand).
To work around this issue, I have to reverted back to using std::addressof(*this).
There was a problem hiding this comment.
Ack. Let's leave addressof for now, but can you please try to minimize this so we can file a bug report to GCC?
It looks like GCC might be tracking this specially during constant evaluation, and they incorrectly think that it can't have been allocated.
libcxx/test/std/containers/sequences/list/list.capacity/resize_size.pass.cpp
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
What's special with those that doesn't work inside constexpr? Is there no way to tweak the tests so they work at compile-time?
There was a problem hiding this comment.
The main challenge I faced to make these tests constexpr is that they both call a function getConstructController, which defines a local static variable.
// getConstructController - Return the global allocator construction controller.
inline ConstructController* getConstructController() {
static ConstructController c;
return &c;
}According to my test (https://godbolt.org/z/c51735h3T), this function call cannot be made constexpr.
There was a problem hiding this comment.
The ideal outcome here might be to pass this static data as an argument to the various "controller" types and create the object as a local variable in the function instead. I don't know if that's feasible though. I think this is reasonable for now.
There was a problem hiding this comment.
I still find it challenging to make these two tests constexpr, because the AllocatorConstructController type must use a singleton pattern (as the test-types, test-allocator and test need to share the same controller), meaning that the controller object must be a static variable. Whether it is a local static (https://godbolt.org/z/8eYxoj9or) or class static (https://godbolt.org/z/xnzh693WK) variable, I found it not possible to achieve a constexpr implementation.
There was a problem hiding this comment.
In order to check this in constant evaluation, I think we need to create a controller type that holds the state as member subobjects, and explicitly create and refer to such a controller object. A singleton is unlikely to be usable in constexpr tests.
There was a problem hiding this comment.
The main challenge I face here is that I found it not easy to avoid a singleton patten because we need to make sure that the same unique controller object (AllocatorConstructionController) must be used by multiple different types, including the test-allocator (ContainerTestAllocator), the test-types (CopyInsertable'), and the tests (e.g., ExpectConstructGuard`). In other words, a unique controller object must be shared. If we hold the controller as a member subobject inside any type, it is hard to ensure uniqueness of the controller object used by other types.
libcxx/test/std/containers/sequences/list/list.cons/size_type.pass.cpp
Outdated
Show resolved
Hide resolved
libcxx/test/std/containers/sequences/list/list.modifiers/append_range.pass.cpp
Outdated
Show resolved
Hide resolved
libcxx/test/std/containers/sequences/list/list.modifiers/push_back_rvalue.pass.cpp
Outdated
Show resolved
Hide resolved
2dfa51a to
64e31c6
Compare
ldionne
left a comment
There was a problem hiding this comment.
This LGTM modulo the remaining comments and rebasing onto main.
There was a problem hiding this comment.
The ideal outcome here might be to pass this static data as an argument to the various "controller" types and create the object as a local variable in the function instead. I don't know if that's feasible though. I think this is reasonable for now.
libcxx/test/std/containers/sequences/list/list.modifiers/prepend_range.pass.cpp
Outdated
Show resolved
Hide resolved
daaee70 to
082460e
Compare
082460e to
46164d8
Compare
This patch makes
std::listconstexpr as part of P3372R3.Fixes #128659.