From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id AB3DF3857C7F for ; Sat, 28 Aug 2021 13:38:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org AB3DF3857C7F Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-255-Us4nB19DNEKXKC6dLHnypw-1; Sat, 28 Aug 2021 09:38:18 -0400 X-MC-Unique: Us4nB19DNEKXKC6dLHnypw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7FAC287122E; Sat, 28 Aug 2021 13:38:17 +0000 (UTC) Received: from localhost (unknown [10.33.36.5]) by smtp.corp.redhat.com (Postfix) with ESMTP id 079CF100EBAD; Sat, 28 Aug 2021 13:38:16 +0000 (UTC) Date: Sat, 28 Aug 2021 14:38:15 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Fix std::allocator for versioned namespace Message-ID: MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: multipart/mixed; boundary="PbHQirnVMjvrZEls" Content-Disposition: inline X-Spam-Status: No, score=-14.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 28 Aug 2021 13:38:23 -0000 --PbHQirnVMjvrZEls Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Removing the allocator specialization for the versioned namespace breaks _Extptr_allocator because the allocator specialization was still declared in , making it an incomplete type. It wrong to remove that specialization anyway, because it is still needed pre-C++20. This removes the #if ! _GLIBCXX_INLINE_VERSION check, so that allocator is still explicitly specialized for the versioned namespace, consistent with the normal unversioned namespace mode. To make _Extptr_allocator usable as a ProtoAllocator, this change adds a default constructor and converting constructor. That is consistent with std::allocator since C++20 (and harmless to do for earlier standards). I'm also explicitly specializing allocator_traits> so that it doesn't need to use allocator::construct and destroy. Doing that allows those members to be removed, further simplifying allocator. That new explicit specialization can delete the allocate, deallocate and max_size members, which are always ill-formed for allocator. Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: * include/bits/alloc_traits.h (allocator_traits): Add explicit specialization for allocator. Improve doxygen comments. * include/bits/allocator.h (allocator): Restore for the versioned namespace. (allocator::construct, allocator::destroy): Remove. * include/ext/extptr_allocator.h (_Extptr_allocator): Add default constructor and converting constructor. Tested powerpc64le-linux. Committed to trunk. --PbHQirnVMjvrZEls Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="patch.txt" commit 754fca77e82a59d85c735a5aff49ee2b1ec4c6df Author: Jonathan Wakely Date: Sat Aug 28 11:05:58 2021 libstdc++: Fix std::allocator for versioned namespace Removing the allocator specialization for the versioned namespace breaks _Extptr_allocator because the allocator specialization was still declared in , making it an incomplete type. It wrong to remove that specialization anyway, because it is still needed pre-C++20. This removes the #if ! _GLIBCXX_INLINE_VERSION check, so that allocator is still explicitly specialized for the versioned namespace, consistent with the normal unversioned namespace mode. To make _Extptr_allocator usable as a ProtoAllocator, this change adds a default constructor and converting constructor. That is consistent with std::allocator since C++20 (and harmless to do for earlier standards). I'm also explicitly specializing allocator_traits> so that it doesn't need to use allocator::construct and destroy. Doing that allows those members to be removed, further simplifying allocator. That new explicit specialization can delete the allocate, deallocate and max_size members, which are always ill-formed for allocator. Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: * include/bits/alloc_traits.h (allocator_traits): Add explicit specialization for allocator. Improve doxygen comments. * include/bits/allocator.h (allocator): Restore for the versioned namespace. (allocator::construct, allocator::destroy): Remove. * include/ext/extptr_allocator.h (_Extptr_allocator): Add default constructor and converting constructor. diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h index 34412583064..05b584f742f 100644 --- a/libstdc++-v3/include/bits/alloc_traits.h +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -559,6 +559,110 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __rhs; } }; + /// Explicit specialization for std::allocator. + template<> + struct allocator_traits> + { + /// The allocator type + using allocator_type = allocator; + + /// The allocated type + using value_type = void; + + /// The allocator's pointer type. + using pointer = void*; + + /// The allocator's const pointer type. + using const_pointer = const void*; + + /// The allocator's void pointer type. + using void_pointer = void*; + + /// The allocator's const void pointer type. + using const_void_pointer = const void*; + + /// The allocator's difference type + using difference_type = std::ptrdiff_t; + + /// The allocator's size type + using size_type = std::size_t; + + /// How the allocator is propagated on copy assignment + using propagate_on_container_copy_assignment = false_type; + + /// How the allocator is propagated on move assignment + using propagate_on_container_move_assignment = true_type; + + /// How the allocator is propagated on swap + using propagate_on_container_swap = false_type; + + /// Whether all instances of the allocator type compare equal. + using is_always_equal = true_type; + + template + using rebind_alloc = allocator<_Up>; + + template + using rebind_traits = allocator_traits>; + + /// allocate is ill-formed for allocator + static void* + allocate(allocator_type&, size_type, const void* = nullptr) = delete; + + /// deallocate is ill-formed for allocator + static void + deallocate(allocator_type&, void*, size_type) = delete; + + /** + * @brief Construct an object of type `_Up` + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for + * an object of type `_Up`. + * @param __args Constructor arguments. + * + * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` + * in C++11, C++14 and C++17. Changed in C++20 to call + * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. + */ + template + static _GLIBCXX20_CONSTEXPR void + construct(allocator_type&, _Up* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { +#if __cplusplus <= 201703L + ::new((void *)__p) _Up(std::forward<_Args>(__args)...); +#else + std::construct_at(__p, std::forward<_Args>(__args)...); +#endif + } + + /** + * @brief Destroy an object of type `_Up` + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Invokes the destructor for `*__p`. + */ + template + static _GLIBCXX20_CONSTEXPR void + destroy(allocator_type&, _Up* __p) + noexcept(is_nothrow_destructible<_Up>::value) + { std::_Destroy(__p); } + + /// max_size is ill-formed for allocator + static size_type + max_size(const allocator_type&) = delete; + + /** + * @brief Obtain an allocator to use when copying a container. + * @param __rhs An allocator. + * @return `__rhs` + */ + static _GLIBCXX20_CONSTEXPR allocator_type + select_on_container_copy_construction(const allocator_type& __rhs) + { return __rhs; } + }; + #if __cplusplus < 201703L template inline void diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h index 396872ffae5..a6883c6758a 100644 --- a/libstdc++-v3/include/bits/allocator.h +++ b/libstdc++-v3/include/bits/allocator.h @@ -61,12 +61,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ // Since C++20 the primary template should be used for allocator, - // but then it would have a non-trivial default ctor and dtor, which - // would be an ABI change. So C++20 still uses the allocator explicit - // specialization, with the historical ABI properties, but with the same - // members that are present in the primary template. + // but then it would have a non-trivial default ctor and dtor for C++20, + // but trivial for C++98-17, which would be an ABI incompatibiliy between + // different standard dialects. So C++20 still uses the allocator + // explicit specialization, with the historical ABI properties, but with + // the same members that are present in the primary template. -#if ! _GLIBCXX_INLINE_VERSION /// allocator specialization. template<> class allocator @@ -77,7 +77,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef ptrdiff_t difference_type; #if __cplusplus <= 201703L - // These were removed for C++20. + // These were removed for C++20, allocator_traits does the right thing. typedef void* pointer; typedef const void* const_pointer; @@ -96,7 +96,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = true_type; #if __cplusplus >= 202002L + // As noted above, these members are present for C++20 to provide the + // same API as the primary template, but still trivial as in pre-C++20. allocator() = default; + ~allocator() = default; template constexpr @@ -105,28 +108,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // No allocate member because it's ill-formed by LWG 3307. // No deallocate member because it would be undefined to call it // with any pointer which wasn't obtained from allocate. - -#else // ! C++20 - private: - // This uses construct and destroy in C++11/14/17 modes. - friend allocator_traits>; - - template - void - construct(_Up* __p, _Args&&... __args) - noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) - { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } - - template - void - destroy(_Up* __p) - noexcept(std::is_nothrow_destructible<_Up>::value) - { __p->~_Up(); } -#endif // C++17 +#endif // C++20 #endif // C++11 - }; -#endif // ! _GLIBCXX_INLINE_VERSION /** * @brief The @a standard allocator, as per C++03 [20.4.1]. @@ -212,7 +196,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return; } #endif - __allocator_base<_Tp>::deallocate(__p, __n); + __allocator_base<_Tp>::deallocate(__p, __n); } #endif // C++20 diff --git a/libstdc++-v3/include/ext/extptr_allocator.h b/libstdc++-v3/include/ext/extptr_allocator.h index 7d8aaac7cee..2dfc73ec605 100644 --- a/libstdc++-v3/include/ext/extptr_allocator.h +++ b/libstdc++-v3/include/ext/extptr_allocator.h @@ -176,6 +176,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Pointer_adapter<_Relative_pointer_impl > const_pointer; + _ExtPtr_allocator() { } + + template + _ExtPtr_allocator(const _ExtPtr_allocator<_Up>&) { } + template struct rebind { typedef _ExtPtr_allocator<_Up> other; }; --PbHQirnVMjvrZEls--