From 36de4e94e9f73af60e5c8f96673fb5aaac8fb083 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Sun, 17 Sep 2023 22:51:18 +0800 Subject: [PATCH 01/12] Add test coverage for non-trivial pointers --- .../test.cpp | 181 ++++++++++++++++-- 1 file changed, 168 insertions(+), 13 deletions(-) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index d697fc595a..86aa35fa89 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -34,6 +34,155 @@ _CONSTEXPR20 void assert_is_permutation(const Container& cont, initializer_list< assert(is_permutation(cont.begin(), cont.end(), il.begin(), il.end())); } +class test_leak { + char* ptr; + +public: + test_leak(const test_leak&) = delete; + test_leak& operator=(const test_leak&) = delete; + + _CONSTEXPR20 test_leak() noexcept /* terminates */ : ptr(allocator{}.allocate(1)) {} + _CONSTEXPR20 ~test_leak() { + allocator{}.deallocate(ptr, 1); + } +}; + +template +class nontrivial_pointer : private test_leak { +public: + T* ptr; + _CONSTEXPR20 nontrivial_pointer() noexcept : ptr(nullptr) {} + _CONSTEXPR20 explicit nontrivial_pointer(T* ptr_) noexcept : ptr(ptr_) {} + _CONSTEXPR20 /*implicit*/ nontrivial_pointer(nullptr_t) noexcept : ptr(nullptr) {} + + _CONSTEXPR20 nontrivial_pointer(const nontrivial_pointer& other) noexcept : ptr(other.ptr) {} + template , int> = 0> + _CONSTEXPR20 nontrivial_pointer(const nontrivial_pointer& other) noexcept : ptr(other.ptr) {} + _CONSTEXPR20 nontrivial_pointer& operator=(const nontrivial_pointer& other) noexcept { + ptr = other.ptr; + return *this; + } + + _CONSTEXPR20 ~nontrivial_pointer() = default; + + _CONSTEXPR20 explicit operator bool() const noexcept { + return static_cast(ptr); + } + _CONSTEXPR20 add_lvalue_reference_t operator*() const noexcept { + return *ptr; + } + _CONSTEXPR20 T* operator->() const noexcept { + return ptr; + } + template , int> = 0> + _CONSTEXPR20 add_lvalue_reference_t operator[](I off) const noexcept { + return ptr[off]; + } + + _CONSTEXPR20 nontrivial_pointer& operator++() noexcept { + ++ptr; + return *this; + } + _CONSTEXPR20 nontrivial_pointer operator++(int) noexcept { + return nontrivial_pointer(ptr++); + } + _CONSTEXPR20 nontrivial_pointer& operator--() noexcept { + --ptr; + return *this; + } + _CONSTEXPR20 nontrivial_pointer operator--(int) noexcept { + return nontrivial_pointer(ptr--); + } + template , int> = 0> + _CONSTEXPR20 nontrivial_pointer& operator+=(I diff) noexcept { + ptr += diff; + return *this; + } + template , int> = 0> + _CONSTEXPR20 nontrivial_pointer& operator-=(I diff) noexcept { + ptr -= diff; + return *this; + } + + template , int> = 0> + _CONSTEXPR20 friend nontrivial_pointer operator+(nontrivial_pointer ptr, I diff) noexcept { + return ptr += diff; + } + template , int> = 0> + _CONSTEXPR20 friend nontrivial_pointer operator+(I diff, nontrivial_pointer ptr) noexcept { + return ptr += diff; + } + _CONSTEXPR20 friend ptrdiff_t operator-(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr - rhs.ptr; + } + template , int> = 0> + _CONSTEXPR20 friend nontrivial_pointer operator-(nontrivial_pointer ptr, I diff) noexcept { + return ptr -= diff; + } + + _CONSTEXPR20 friend bool operator==(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr == rhs.ptr; + } + _CONSTEXPR20 friend bool operator==(nontrivial_pointer ptr, nullptr_t) noexcept { + return !static_cast(ptr.ptr); + } + _CONSTEXPR20 friend bool operator==(nullptr_t, nontrivial_pointer ptr) noexcept { + return !static_cast(ptr.ptr); + } + _CONSTEXPR20 friend bool operator!=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr != rhs.ptr; + } + _CONSTEXPR20 friend bool operator!=(nontrivial_pointer ptr, nullptr_t) noexcept { + return static_cast(ptr.ptr); + } + _CONSTEXPR20 friend bool operator!=(nullptr_t, nontrivial_pointer ptr) noexcept { + return static_cast(ptr.ptr); + } + _CONSTEXPR20 friend bool operator<(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr < rhs.ptr; + } + _CONSTEXPR20 friend bool operator<=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr <= rhs.ptr; + } + _CONSTEXPR20 friend bool operator>(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr > rhs.ptr; + } + _CONSTEXPR20 friend bool operator>=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + return lhs.ptr >= rhs.ptr; + } +}; + +template > +struct impl_pointer_to { + static constexpr nontrivial_pointer pointer_to(T& r) noexcept { + return nontrivial_pointer(addressof(r)); + } +}; + +template +struct impl_pointer_to { + // no pointer_to for void +}; + +template +struct std::pointer_traits> : public impl_pointer_to { + using pointer = nontrivial_pointer; + using element_type = T; + using difference_type = ptrdiff_t; + + template + using rebind = nontrivial_pointer; +}; + +template +struct std::iterator_traits> { + using iterator_category = random_access_iterator_tag; + using difference_type = ptrdiff_t; + using value_type = remove_const_t; + using reference = add_lvalue_reference_t; + using pointer = nontrivial_pointer; +}; + template class MyAlloc { private: @@ -49,6 +198,7 @@ class MyAlloc { } using value_type = T; + using pointer = nontrivial_pointer; using propagate_on_container_copy_assignment = POCCA; using propagate_on_container_move_assignment = POCMA; @@ -70,12 +220,12 @@ class MyAlloc { return equal_id() != other.equal_id(); } - [[nodiscard]] constexpr T* allocate(const size_t numElements) { - return allocator{}.allocate(numElements + equal_id()) + equal_id(); + [[nodiscard]] constexpr pointer allocate(const size_t numElements) { + return pointer(allocator{}.allocate(numElements + equal_id()) + equal_id()); } - constexpr void deallocate(T* const first, const size_t numElements) noexcept { - allocator{}.deallocate(first - equal_id(), numElements + equal_id()); + constexpr void deallocate(pointer const first, const size_t numElements) noexcept { + allocator{}.deallocate(_Unfancy(first - equal_id()), numElements + equal_id()); } }; @@ -559,7 +709,7 @@ void test_flist() { // NOTE: Having 4 elements of type char32_t bypasses the Small String Optimization. -void test_string_copy_ctor() { +_CONSTEXPR20 void test_string_copy_ctor() { basic_string, StationaryAlloc> src( {5, 10, 20, 30}, StationaryAlloc(11)); auto src_it = src.begin(); @@ -583,7 +733,7 @@ void test_string_copy_ctor() { assert(dst.get_allocator().id() == 11); } -void test_string_copy_alloc_ctor(const size_t id1, const size_t id2) { +_CONSTEXPR20 void test_string_copy_alloc_ctor(const size_t id1, const size_t id2) { basic_string, StationaryAlloc> src( {5, 10, 20, 30}, StationaryAlloc(id1)); auto src_it = src.begin(); @@ -608,7 +758,7 @@ void test_string_copy_alloc_ctor(const size_t id1, const size_t id2) { } template -void test_string_copy_assign(const size_t id1, const size_t id2, const size_t id3) { +_CONSTEXPR20 void test_string_copy_assign(const size_t id1, const size_t id2, const size_t id3) { basic_string, Alloc> src({5, 10, 20, 30}, Alloc(id1)); basic_string, Alloc> dst({0, 0, 0, 0}, Alloc(id2)); @@ -636,7 +786,7 @@ void test_string_copy_assign(const size_t id1, const size_t id2, const size_t id assert(dst.get_allocator().id() == id3); } -void test_string_copy_assign_pocca_sso() { +_CONSTEXPR20 void test_string_copy_assign_pocca_sso() { // GH-3862 fixed a bug where the POCCA codepath in basic_string's copy assignment operator mishandled // the scenario where the string on the right hand side has a large capacity but a small size - so while // the RHS has dynamically allocated memory, the LHS should activate the Small String Optimization. @@ -661,7 +811,7 @@ void test_string_copy_assign_pocca_sso() { assert(right == "yyyyyyy"); } -void test_string_move_ctor() { +_CONSTEXPR20 void test_string_move_ctor() { basic_string, StationaryAlloc> src( {5, 10, 20, 30}, StationaryAlloc(11)); auto it1 = src.begin(); @@ -690,7 +840,7 @@ void test_string_move_ctor() { assert(dst.get_allocator().id() == 11); } -void test_string_move_alloc_ctor(const size_t id1, const size_t id2) { +_CONSTEXPR20 void test_string_move_alloc_ctor(const size_t id1, const size_t id2) { basic_string, StationaryAlloc> src( {5, 10, 20, 30}, StationaryAlloc(id1)); auto it1 = src.begin(); @@ -721,7 +871,7 @@ void test_string_move_alloc_ctor(const size_t id1, const size_t id2) { } template -void test_string_move_assign(const size_t id1, const size_t id2, const size_t id3) { +_CONSTEXPR20 void test_string_move_assign(const size_t id1, const size_t id2, const size_t id3) { basic_string, Alloc> src({5, 10, 20, 30}, Alloc(id1)); basic_string, Alloc> dst({0, 0, 0, 0}, Alloc(id2)); @@ -755,7 +905,7 @@ void test_string_move_assign(const size_t id1, const size_t id2, const size_t id } template -void test_string_swap(const size_t id1, const size_t id2) { +_CONSTEXPR20 void test_string_swap(const size_t id1, const size_t id2) { basic_string, Alloc> src({5, 10, 20, 30}, Alloc(id1)); basic_string, Alloc> dst({6, 40, 50, 60}, Alloc(id2)); @@ -784,7 +934,7 @@ void test_string_swap(const size_t id1, const size_t id2) { assert(dst.get_allocator().id() == id1); } -void test_string() { +_CONSTEXPR20 bool test_string() { test_string_copy_ctor(); test_string_copy_alloc_ctor(11, 11); // equal allocators @@ -814,6 +964,8 @@ void test_string() { test_string_swap>(11, 11); // POCS, equal allocators test_string_swap>(11, 22); // POCS, non-equal allocators test_string_swap>(11, 22); // POCS, always-equal allocators + + return true; } @@ -1680,8 +1832,11 @@ int main() { test_sequence(); test_sequence(); test_sequence(); + #if _HAS_CXX20 static_assert(test_sequence()); + + static_assert(test_string()); #endif // _HAS_CXX20 test_flist(); From af25008f5f8d9e1bda68f8e451b15308c92c7c48 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Mon, 18 Sep 2023 13:43:43 +0800 Subject: [PATCH 02/12] Fix `basic_string::operator=(const&)` --- stl/inc/xstring | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index ae566f24af..12db1eaada 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -3166,12 +3166,13 @@ public: size_type _New_capacity = _Calculate_growth(_Right_size, _Small_string_capacity, _Right.max_size()); auto _Right_al_non_const = _Right_al; const pointer _New_ptr = _Allocate_for_capacity(_Right_al_non_const, _New_capacity); // throws - _Traits::copy(_Unfancy(_New_ptr), _Right_ptr, _Right_size + 1); + _Tidy_deallocate(); - _Mypair._Myval2._Bx._Ptr = _New_ptr; - _Mypair._Myval2._Mysize = _Right_size; - _Mypair._Myval2._Myres = _New_capacity; + _Construct_in_place(_Mypair._Myval2._Bx._Ptr, _New_ptr); + _Mypair._Myval2._Mysize = _Right_size; + _Mypair._Myval2._Myres = _New_capacity; + _ASAN_STRING_CREATE(*this); } else { _Tidy_deallocate(); _Traits::copy(_Mypair._Myval2._Bx._Buf, _Right_ptr, _Right_size + 1); From 02b66e977bfefda79ebd3e5a89b66a8f553d1fd7 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Mon, 18 Sep 2023 13:52:47 +0800 Subject: [PATCH 03/12] Fix `basic_string::_Take_contents` --- stl/inc/xstring | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index 12db1eaada..46991c2aef 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -3052,8 +3052,9 @@ private: if (_Right_data._Large_mode_engaged()) { // steal buffer _Construct_in_place(_My_data._Bx._Ptr, _Right_data._Bx._Ptr); - _Right_data._Bx._Ptr = nullptr; _Swap_proxy_and_iterators(_Right); + + _Destroy_in_place(_Right_data._Bx._Ptr); } else { // copy small string buffer _My_data._Activate_SSO_buffer(); _Traits::copy(_My_data._Bx._Buf, _Right_data._Bx._Buf, _Right_data._Mysize + 1); From 3cb5d00391d319086559cd74776cb9eae42b4d69 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Mon, 18 Sep 2023 15:09:05 +0800 Subject: [PATCH 04/12] [WIP] `failure was caused by allocated storage not being deallocated` ? What happens to `vector(vector&&)` ? --- tests/std/tests/VSO_0000000_allocator_propagation/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index 86aa35fa89..26ccc48881 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -457,7 +457,7 @@ _CONSTEXPR20 bool test_sequence() { test_sequence_copy_assign>(11, 22, 11); // POCCA, non-equal allocators test_sequence_copy_assign>(11, 22, 11); // POCCA, always-equal allocators - test_sequence_move_ctor(); + // test_sequence_move_ctor(); test_sequence_move_alloc_ctor(11, 11); // equal allocators test_sequence_move_alloc_ctor(11, 22); // non-equal allocators From add808dfab68aea90abd0d404861fed3edd3ab96 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:13:47 +0800 Subject: [PATCH 05/12] Update `operator bool()` Co-authored-by: Casey Carter --- tests/std/tests/VSO_0000000_allocator_propagation/test.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index 26ccc48881..6a20b9fa8c 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -66,7 +66,11 @@ class nontrivial_pointer : private test_leak { _CONSTEXPR20 ~nontrivial_pointer() = default; _CONSTEXPR20 explicit operator bool() const noexcept { +#ifdef __EDG__ // TRANSITION, VSO-1888157 return static_cast(ptr); +#else // ^^^ workaround / no workaround vvv + return ptr != nullptr; +#endif // ^^^ no workaround ^^^ } _CONSTEXPR20 add_lvalue_reference_t operator*() const noexcept { return *ptr; From 15e676232feca3b9ef93bff94c59a2e967993e03 Mon Sep 17 00:00:00 2001 From: achabense <60953653+achabense@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:33:42 +0800 Subject: [PATCH 06/12] cleanups --- .../VSO_0000000_allocator_propagation/test.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index 6a20b9fa8c..c34ba18b3e 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -35,15 +35,15 @@ _CONSTEXPR20 void assert_is_permutation(const Container& cont, initializer_list< } class test_leak { - char* ptr; + char* res; public: test_leak(const test_leak&) = delete; test_leak& operator=(const test_leak&) = delete; - _CONSTEXPR20 test_leak() noexcept /* terminates */ : ptr(allocator{}.allocate(1)) {} + _CONSTEXPR20 test_leak() noexcept /* terminates */ : res(allocator{}.allocate(1)) {} _CONSTEXPR20 ~test_leak() { - allocator{}.deallocate(ptr, 1); + allocator{}.deallocate(res, 1); } }; @@ -128,19 +128,19 @@ class nontrivial_pointer : private test_leak { return lhs.ptr == rhs.ptr; } _CONSTEXPR20 friend bool operator==(nontrivial_pointer ptr, nullptr_t) noexcept { - return !static_cast(ptr.ptr); + return !ptr; } _CONSTEXPR20 friend bool operator==(nullptr_t, nontrivial_pointer ptr) noexcept { - return !static_cast(ptr.ptr); + return !ptr; } _CONSTEXPR20 friend bool operator!=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { return lhs.ptr != rhs.ptr; } _CONSTEXPR20 friend bool operator!=(nontrivial_pointer ptr, nullptr_t) noexcept { - return static_cast(ptr.ptr); + return static_cast(ptr); } _CONSTEXPR20 friend bool operator!=(nullptr_t, nontrivial_pointer ptr) noexcept { - return static_cast(ptr.ptr); + return static_cast(ptr); } _CONSTEXPR20 friend bool operator<(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { return lhs.ptr < rhs.ptr; From d724676d89610519cf294d13f7d1f4ceb6773f4e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Sep 2023 13:17:02 -0700 Subject: [PATCH 07/12] Add `private:`. --- tests/std/tests/VSO_0000000_allocator_propagation/test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index c34ba18b3e..7889511823 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -35,6 +35,7 @@ _CONSTEXPR20 void assert_is_permutation(const Container& cont, initializer_list< } class test_leak { +private: char* res; public: From 7f3ba483d718ea3f14782fc924f2cba6bc11ddb5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Sep 2023 13:17:53 -0700 Subject: [PATCH 08/12] `_CONSTEXPR20 friend` => `friend _CONSTEXPR20` --- .../test.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index 7889511823..e280469109 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -110,49 +110,49 @@ class nontrivial_pointer : private test_leak { } template , int> = 0> - _CONSTEXPR20 friend nontrivial_pointer operator+(nontrivial_pointer ptr, I diff) noexcept { + friend _CONSTEXPR20 nontrivial_pointer operator+(nontrivial_pointer ptr, I diff) noexcept { return ptr += diff; } template , int> = 0> - _CONSTEXPR20 friend nontrivial_pointer operator+(I diff, nontrivial_pointer ptr) noexcept { + friend _CONSTEXPR20 nontrivial_pointer operator+(I diff, nontrivial_pointer ptr) noexcept { return ptr += diff; } - _CONSTEXPR20 friend ptrdiff_t operator-(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + friend _CONSTEXPR20 ptrdiff_t operator-(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { return lhs.ptr - rhs.ptr; } template , int> = 0> - _CONSTEXPR20 friend nontrivial_pointer operator-(nontrivial_pointer ptr, I diff) noexcept { + friend _CONSTEXPR20 nontrivial_pointer operator-(nontrivial_pointer ptr, I diff) noexcept { return ptr -= diff; } - _CONSTEXPR20 friend bool operator==(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + friend _CONSTEXPR20 bool operator==(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { return lhs.ptr == rhs.ptr; } - _CONSTEXPR20 friend bool operator==(nontrivial_pointer ptr, nullptr_t) noexcept { + friend _CONSTEXPR20 bool operator==(nontrivial_pointer ptr, nullptr_t) noexcept { return !ptr; } - _CONSTEXPR20 friend bool operator==(nullptr_t, nontrivial_pointer ptr) noexcept { + friend _CONSTEXPR20 bool operator==(nullptr_t, nontrivial_pointer ptr) noexcept { return !ptr; } - _CONSTEXPR20 friend bool operator!=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + friend _CONSTEXPR20 bool operator!=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { return lhs.ptr != rhs.ptr; } - _CONSTEXPR20 friend bool operator!=(nontrivial_pointer ptr, nullptr_t) noexcept { + friend _CONSTEXPR20 bool operator!=(nontrivial_pointer ptr, nullptr_t) noexcept { return static_cast(ptr); } - _CONSTEXPR20 friend bool operator!=(nullptr_t, nontrivial_pointer ptr) noexcept { + friend _CONSTEXPR20 bool operator!=(nullptr_t, nontrivial_pointer ptr) noexcept { return static_cast(ptr); } - _CONSTEXPR20 friend bool operator<(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + friend _CONSTEXPR20 bool operator<(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { return lhs.ptr < rhs.ptr; } - _CONSTEXPR20 friend bool operator<=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + friend _CONSTEXPR20 bool operator<=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { return lhs.ptr <= rhs.ptr; } - _CONSTEXPR20 friend bool operator>(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + friend _CONSTEXPR20 bool operator>(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { return lhs.ptr > rhs.ptr; } - _CONSTEXPR20 friend bool operator>=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { + friend _CONSTEXPR20 bool operator>=(nontrivial_pointer lhs, nontrivial_pointer rhs) noexcept { return lhs.ptr >= rhs.ptr; } }; From 33dce61e56611c1804ec799f7a2ae3d1d20d3b85 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Sep 2023 13:19:28 -0700 Subject: [PATCH 09/12] Use the primary template for when `is_void_v` is `true`. --- .../tests/VSO_0000000_allocator_propagation/test.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index e280469109..06cdd77f84 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -159,14 +159,14 @@ class nontrivial_pointer : private test_leak { template > struct impl_pointer_to { - static constexpr nontrivial_pointer pointer_to(T& r) noexcept { - return nontrivial_pointer(addressof(r)); - } + // no pointer_to for void }; template -struct impl_pointer_to { - // no pointer_to for void +struct impl_pointer_to { + static constexpr nontrivial_pointer pointer_to(T& r) noexcept { + return nontrivial_pointer(addressof(r)); + } }; template From 9daeca5012397a4abbdb35281305e974f3e24030 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Sep 2023 13:20:07 -0700 Subject: [PATCH 10/12] `struct` defaults to `public` inheritance. --- tests/std/tests/VSO_0000000_allocator_propagation/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index 06cdd77f84..2c0f2cfbd5 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -170,7 +170,7 @@ struct impl_pointer_to { }; template -struct std::pointer_traits> : public impl_pointer_to { +struct std::pointer_traits> : impl_pointer_to { using pointer = nontrivial_pointer; using element_type = T; using difference_type = ptrdiff_t; From 4a51b97010fc544456621c9f193156363a099c46 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 19 Sep 2023 13:25:32 -0700 Subject: [PATCH 11/12] Work around VSO-1888462. --- tests/std/tests/VSO_0000000_allocator_propagation/test.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index 2c0f2cfbd5..b3c25689dd 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -462,7 +462,9 @@ _CONSTEXPR20 bool test_sequence() { test_sequence_copy_assign>(11, 22, 11); // POCCA, non-equal allocators test_sequence_copy_assign>(11, 22, 11); // POCCA, always-equal allocators - // test_sequence_move_ctor(); +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1888462 + test_sequence_move_ctor(); +#endif // ^^^ no workaround ^^^ test_sequence_move_alloc_ctor(11, 11); // equal allocators test_sequence_move_alloc_ctor(11, 22); // non-equal allocators From a6795f497621b8031429f6eb6a76e841ba4e6b21 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 20 Sep 2023 16:45:43 -0700 Subject: [PATCH 12/12] Restrict the MSVC workaround to C++20 compile-time. --- .../std/tests/VSO_0000000_allocator_propagation/test.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp index b3c25689dd..9585dca3ea 100644 --- a/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp +++ b/tests/std/tests/VSO_0000000_allocator_propagation/test.cpp @@ -462,9 +462,12 @@ _CONSTEXPR20 bool test_sequence() { test_sequence_copy_assign>(11, 22, 11); // POCCA, non-equal allocators test_sequence_copy_assign>(11, 22, 11); // POCCA, always-equal allocators -#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1888462 - test_sequence_move_ctor(); -#endif // ^^^ no workaround ^^^ +#if _HAS_CXX20 && !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-1888462 + if (!is_constant_evaluated()) +#endif // ^^^ workaround ^^^ + { + test_sequence_move_ctor(); + } test_sequence_move_alloc_ctor(11, 11); // equal allocators test_sequence_move_alloc_ctor(11, 22); // non-equal allocators