From 26fdeabb21601b507daa5d8abcbd7be6d63cd67a Mon Sep 17 00:00:00 2001 From: Hamid Reza Arzaghi Date: Thu, 1 Oct 2020 01:26:39 +0330 Subject: [PATCH 1/5] improve vector move ctor --- stl/inc/vector | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 0fe4e0079ab..2b1bca1879a 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -372,7 +372,10 @@ public: using reference = value_type&; using const_reference = const value_type&; - _Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {} + _Vector_val() noexcept : _Myfirst{}, _Mylast{}, _Myend{} {} + + _Vector_val(pointer _First, pointer _Last, pointer _End) noexcept + : _Myfirst{_First}, _Mylast{_Last}, _Myend{_End} {} void _Swap_val(_Vector_val& _Right) noexcept { this->_Swap_proxy_and_iterators(_Right); @@ -578,9 +581,15 @@ private: } public: - vector(vector&& _Right) noexcept : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal())) { + vector(vector&& _Right) noexcept + : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal()), _Right._Mypair._Myval2._Myfirst, + _Right._Mypair._Myval2._Mylast, _Right._Mypair._Myval2._Myend) { _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); - _Move_construct(_Right, true_type{}); + _Mypair._Myval2._Swap_proxy_and_iterators(_Right._Mypair._Myval2); + + _Right._Mypair._Myval2._Myfirst = pointer(); + _Right._Mypair._Myval2._Mylast = pointer(); + _Right._Mypair._Myval2._Myend = pointer(); } vector(vector&& _Right, const _Alloc& _Al) noexcept(_Alty_traits::is_always_equal::value) // strengthened From 169ca6857eb60d9a3ce286f79abd7d3f34b5cc51 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 1 Oct 2020 19:27:33 -0700 Subject: [PATCH 2/5] Use parentheses for potentially-fancy pointers. --- stl/inc/vector | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 2b1bca1879a..1c6e878ef4e 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -372,10 +372,10 @@ public: using reference = value_type&; using const_reference = const value_type&; - _Vector_val() noexcept : _Myfirst{}, _Mylast{}, _Myend{} {} + _Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {} _Vector_val(pointer _First, pointer _Last, pointer _End) noexcept - : _Myfirst{_First}, _Mylast{_Last}, _Myend{_End} {} + : _Myfirst(_First), _Mylast(_Last), _Myend(_End) {} void _Swap_val(_Vector_val& _Right) noexcept { this->_Swap_proxy_and_iterators(_Right); From b61c5fea522cdb9561398e9ec6695651b6db0d4d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 1 Oct 2020 19:44:54 -0700 Subject: [PATCH 3/5] Change pointer() to nullptr for Cpp17NullablePointers. unique_ptr still calls reset(pointer()) to select a specific overload. --- stl/inc/memory | 6 +++--- stl/inc/vector | 24 ++++++++++++------------ stl/inc/xhash | 8 ++++---- stl/inc/xstring | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index dcfded85434..eafeefd38b9 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -3281,10 +3281,10 @@ public: } pointer release() noexcept { - return _STD exchange(_Mypair._Myval2, pointer()); + return _STD exchange(_Mypair._Myval2, nullptr); } - void reset(pointer _Ptr = pointer()) noexcept { + void reset(pointer _Ptr = nullptr) noexcept { pointer _Old = _STD exchange(_Mypair._Myval2, _Ptr); if (_Old) { _Mypair._Get_first()(_Old); @@ -3413,7 +3413,7 @@ public: } pointer release() noexcept { - return _STD exchange(_Mypair._Myval2, pointer()); + return _STD exchange(_Mypair._Myval2, nullptr); } template > diff --git a/stl/inc/vector b/stl/inc/vector index 1c6e878ef4e..d52d4077601 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -390,9 +390,9 @@ public: _Mylast = _Right._Mylast; _Myend = _Right._Myend; - _Right._Myfirst = pointer(); - _Right._Mylast = pointer(); - _Right._Myend = pointer(); + _Right._Myfirst = nullptr; + _Right._Mylast = nullptr; + _Right._Myend = nullptr; } pointer _Myfirst; // pointer to beginning of array @@ -587,9 +587,9 @@ public: _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); _Mypair._Myval2._Swap_proxy_and_iterators(_Right._Mypair._Myval2); - _Right._Mypair._Myval2._Myfirst = pointer(); - _Right._Mypair._Myval2._Mylast = pointer(); - _Right._Mypair._Myval2._Myend = pointer(); + _Right._Mypair._Myval2._Myfirst = nullptr; + _Right._Mypair._Myval2._Mylast = nullptr; + _Right._Mypair._Myval2._Myend = nullptr; } vector(vector&& _Right, const _Alloc& _Al) noexcept(_Alty_traits::is_always_equal::value) // strengthened @@ -1301,9 +1301,9 @@ private: _Destroy(_Myfirst, _Mylast); _Getal().deallocate(_Myfirst, static_cast(_Myend - _Myfirst)); - _Myfirst = pointer(); - _Mylast = pointer(); - _Myend = pointer(); + _Myfirst = nullptr; + _Mylast = nullptr; + _Myend = nullptr; } _Buy_raw(_Newcapacity); @@ -1704,9 +1704,9 @@ private: _Destroy(_Myfirst, _Mylast); _Getal().deallocate(_Myfirst, static_cast(_Myend - _Myfirst)); - _Myfirst = pointer(); - _Mylast = pointer(); - _Myend = pointer(); + _Myfirst = nullptr; + _Mylast = nullptr; + _Myend = nullptr; } } diff --git a/stl/inc/xhash b/stl/inc/xhash index 761b5d385c3..39eeba36edd 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -319,9 +319,9 @@ struct _Hash_vec { void _Tidy() noexcept { _Destroy_range(_Mypair._Myval2._Myfirst, _Mypair._Myval2._Mylast); _Mypair._Get_first().deallocate(_Mypair._Myval2._Myfirst, size()); - _Mypair._Myval2._Myfirst = pointer(); - _Mypair._Myval2._Mylast = pointer(); - _Mypair._Myval2._Myend = pointer(); + _Mypair._Myval2._Myfirst = nullptr; + _Mypair._Myval2._Mylast = nullptr; + _Mypair._Myval2._Myend = nullptr; } ~_Hash_vec() { @@ -472,7 +472,7 @@ private: _Min_buckets_construct_ptr(const _Min_buckets_construct_ptr&) = delete; _NODISCARD pointer _Release(_Unchecked_iterator _Newend) noexcept { _STD uninitialized_fill(_Base, _Base + _Min_buckets * 2, _Newend); - return _STD exchange(_Base, pointer()); + return _STD exchange(_Base, nullptr); } ~_Min_buckets_construct_ptr() { if (_Base) { diff --git a/stl/inc/xstring b/stl/inc/xstring index a1ac9f75908..e3fcec57484 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -2713,7 +2713,7 @@ private: auto& _Right_data = _Right._Mypair._Myval2; if (_Right_data._Large_string_engaged()) { // steal buffer _Construct_in_place(_My_data._Bx._Ptr, _Right_data._Bx._Ptr); - _Right_data._Bx._Ptr = pointer(); + _Right_data._Bx._Ptr = nullptr; _Swap_proxy_and_iterators(_Right); } else { // copy small string buffer _Traits::copy(_My_data._Bx._Buf, _Right_data._Bx._Buf, _Right_data._Mysize + 1); From 44cf7a441d90d2bbcf09f8d65e65684826763812 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 1 Oct 2020 20:26:29 -0700 Subject: [PATCH 4/5] Use _STD exchange() to improve codegen slightly. --- stl/inc/vector | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index d52d4077601..5a08f9d8f9f 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -582,14 +582,12 @@ private: public: vector(vector&& _Right) noexcept - : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal()), _Right._Mypair._Myval2._Myfirst, - _Right._Mypair._Myval2._Mylast, _Right._Mypair._Myval2._Myend) { + : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal()), + _STD exchange(_Right._Mypair._Myval2._Myfirst, nullptr), + _STD exchange(_Right._Mypair._Myval2._Mylast, nullptr), + _STD exchange(_Right._Mypair._Myval2._Myend, nullptr)) { _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); _Mypair._Myval2._Swap_proxy_and_iterators(_Right._Mypair._Myval2); - - _Right._Mypair._Myval2._Myfirst = nullptr; - _Right._Mypair._Myval2._Mylast = nullptr; - _Right._Mypair._Myval2._Myend = nullptr; } vector(vector&& _Right, const _Alloc& _Al) noexcept(_Alty_traits::is_always_equal::value) // strengthened From 922ad2aa8373323413b6fcb1d60cac8ee64cea84 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 1 Oct 2020 22:06:35 -0700 Subject: [PATCH 5/5] Fix fancy_pointer to meet the Cpp17NullablePointer requirements. --- .../Dev10_722102_shared_ptr_nullptr/test.cpp | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/Dev10_722102_shared_ptr_nullptr/test.cpp b/tests/std/tests/Dev10_722102_shared_ptr_nullptr/test.cpp index 0c753db3ddd..75eca42e39d 100644 --- a/tests/std/tests/Dev10_722102_shared_ptr_nullptr/test.cpp +++ b/tests/std/tests/Dev10_722102_shared_ptr_nullptr/test.cpp @@ -4,12 +4,12 @@ // Dev10-722102 "STL: Get nullptr overloads" // DevDiv-520681 "Faulty implementation of shared_ptr(nullptr_t) constructor" -#include +#include +#include +#include #include #include #include -#include -#include #include #include @@ -159,11 +159,43 @@ namespace unique_ptr_ { template struct fancy_pointer { - T* ptr_; + T* ptr_{nullptr}; fancy_pointer() = default; + explicit fancy_pointer(secret_tag, T* ptr) : ptr_{ptr} {} + fancy_pointer(nullptr_t) {} + + fancy_pointer& operator=(nullptr_t) { + ptr_ = nullptr; + return *this; + } + + friend bool operator==(const fancy_pointer& left, const fancy_pointer& right) { + return left.ptr_ == right.ptr_; + } + + friend bool operator!=(const fancy_pointer& left, const fancy_pointer& right) { + return left.ptr_ != right.ptr_; + } + + friend bool operator==(const fancy_pointer& left, nullptr_t) { + return left.ptr_ == nullptr; + } + + friend bool operator!=(const fancy_pointer& left, nullptr_t) { + return left.ptr_ != nullptr; + } + + friend bool operator==(nullptr_t, const fancy_pointer& right) { + return nullptr == right.ptr_; + } + + friend bool operator!=(nullptr_t, const fancy_pointer& right) { + return nullptr != right.ptr_; + } + operator T*() const { return ptr_; }