[libcxx] r324182 - [libc++] Fix PR35491 - std::array of zero-size doesn't work with non-default constructible types.
Hans Wennborg via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 5 07:19:43 PST 2018
This broke the Chromium build, see
https://bugs.chromium.org/p/chromium/issues/detail?id=809050#c2
I see there were a lot of changes landed around the same time, so I'm
not sure what to revert here exactly.
On Sun, Feb 4, 2018 at 2:03 AM, Eric Fiselier via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
> Author: ericwf
> Date: Sat Feb 3 17:03:08 2018
> New Revision: 324182
>
> URL: http://llvm.org/viewvc/llvm-project?rev=324182&view=rev
> Log:
> [libc++] Fix PR35491 - std::array of zero-size doesn't work with non-default constructible types.
>
> Summary:
> This patch fixes llvm.org/PR35491 and LWG2157 (https://cplusplus.github.io/LWG/issue2157)
>
> The fix attempts to maintain ABI compatibility by replacing the array with a instance of `aligned_storage`.
>
> Reviewers: mclow.lists, EricWF
>
> Reviewed By: EricWF
>
> Subscribers: lichray, cfe-commits
>
> Differential Revision: https://reviews.llvm.org/D41223
>
> Modified:
> libcxx/trunk/include/array
> libcxx/trunk/test/std/containers/sequences/array/array.cons/default.pass.cpp
> libcxx/trunk/test/std/containers/sequences/array/array.data/data.pass.cpp
> libcxx/trunk/test/std/containers/sequences/array/array.data/data_const.pass.cpp
> libcxx/trunk/test/std/containers/sequences/array/begin.pass.cpp
>
> Modified: libcxx/trunk/include/array
> URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/array?rev=324182&r1=324181&r2=324182&view=diff
> ==============================================================================
> --- libcxx/trunk/include/array (original)
> +++ libcxx/trunk/include/array Sat Feb 3 17:03:08 2018
> @@ -118,6 +118,55 @@ template <size_t I, class T, size_t N> c
> _LIBCPP_BEGIN_NAMESPACE_STD
>
> template <class _Tp, size_t _Size>
> +struct __array_traits {
> + typedef _Tp _StorageT[_Size];
> +
> + _LIBCPP_INLINE_VISIBILITY
> + static _LIBCPP_CONSTEXPR_AFTER_CXX14 _Tp* __data(_StorageT& __store) {
> + return __store;
> + }
> +
> + _LIBCPP_INLINE_VISIBILITY
> + static _LIBCPP_CONSTEXPR_AFTER_CXX14 _Tp const* __data(const _StorageT& __store) {
> + return __store;
> + }
> +
> + _LIBCPP_INLINE_VISIBILITY
> + static void __swap(_StorageT& __lhs, _StorageT& __rhs) {
> + std::swap_ranges(__lhs, __lhs + _Size, __rhs);
> + }
> +
> + _LIBCPP_INLINE_VISIBILITY
> + static void __fill(_StorageT& __arr, _Tp const& __val) {
> + _VSTD::fill_n(__arr, _Size, __val);
> + }
> +};
> +
> +template <class _Tp>
> +struct __array_traits<_Tp, 0> {
> + typedef typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type _StorageT;
> +
> + _LIBCPP_INLINE_VISIBILITY
> + static _Tp* __data(_StorageT& __store) {
> + _StorageT *__ptr = std::addressof(__store);
> + return reinterpret_cast<_Tp*>(__ptr);
> + }
> +
> + _LIBCPP_INLINE_VISIBILITY
> + static const _Tp* __data(const _StorageT& __store) {
> + const _StorageT *__ptr = std::addressof(__store);
> + return reinterpret_cast<const _Tp*>(__ptr);
> + }
> +
> + _LIBCPP_INLINE_VISIBILITY
> + static void __swap(_StorageT&, _StorageT&) {}
> +
> + _LIBCPP_INLINE_VISIBILITY
> + static void __fill(_StorageT&, _Tp const&) {
> + }
> +};
> +
> +template <class _Tp, size_t _Size>
> struct _LIBCPP_TEMPLATE_VIS array
> {
> // types:
> @@ -134,31 +183,26 @@ struct _LIBCPP_TEMPLATE_VIS array
> typedef std::reverse_iterator<iterator> reverse_iterator;
> typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
>
> - value_type __elems_[_Size > 0 ? _Size : 1];
> + typedef __array_traits<_Tp, _Size> _Traits;
> + typename _Traits::_StorageT __elems_;
>
> // No explicit construct/copy/destroy for aggregate type
> _LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u)
> - {_VSTD::fill_n(__elems_, _Size, __u);}
> - _LIBCPP_INLINE_VISIBILITY
> - void swap(array& __a) _NOEXCEPT_(_Size == 0 || __is_nothrow_swappable<_Tp>::value)
> - { __swap_dispatch((std::integral_constant<bool, _Size == 0>()), __a); }
> + {_Traits::__fill(__elems_, __u);}
>
> _LIBCPP_INLINE_VISIBILITY
> - void __swap_dispatch(std::true_type, array&) {}
> -
> - _LIBCPP_INLINE_VISIBILITY
> - void __swap_dispatch(std::false_type, array& __a)
> - { _VSTD::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);}
> + void swap(array& __a) _NOEXCEPT_(_Size == 0 || __is_nothrow_swappable<_Tp>::value)
> + { _Traits::__swap(__elems_, __a.__elems_); }
>
> // iterators:
> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
> - iterator begin() _NOEXCEPT {return iterator(__elems_);}
> + iterator begin() _NOEXCEPT {return iterator(data());}
> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
> - const_iterator begin() const _NOEXCEPT {return const_iterator(__elems_);}
> + const_iterator begin() const _NOEXCEPT {return const_iterator(data());}
> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
> - iterator end() _NOEXCEPT {return iterator(__elems_ + _Size);}
> + iterator end() _NOEXCEPT {return iterator(data() + _Size);}
> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
> - const_iterator end() const _NOEXCEPT {return const_iterator(__elems_ + _Size);}
> + const_iterator end() const _NOEXCEPT {return const_iterator(data() + _Size);}
>
> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
> reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
> @@ -201,9 +245,9 @@ struct _LIBCPP_TEMPLATE_VIS array
> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference back() const {return __elems_[_Size > 0 ? _Size-1 : 0];}
>
> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
> - value_type* data() _NOEXCEPT {return __elems_;}
> + value_type* data() _NOEXCEPT {return _Traits::__data(__elems_);}
> _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
> - const value_type* data() const _NOEXCEPT {return __elems_;}
> + const value_type* data() const _NOEXCEPT {return _Traits::__data(__elems_);}
> };
>
> template <class _Tp, size_t _Size>
>
> Modified: libcxx/trunk/test/std/containers/sequences/array/array.cons/default.pass.cpp
> URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/array/array.cons/default.pass.cpp?rev=324182&r1=324181&r2=324182&view=diff
> ==============================================================================
> --- libcxx/trunk/test/std/containers/sequences/array/array.cons/default.pass.cpp (original)
> +++ libcxx/trunk/test/std/containers/sequences/array/array.cons/default.pass.cpp Sat Feb 3 17:03:08 2018
> @@ -14,6 +14,14 @@
> #include <array>
> #include <cassert>
>
> +// std::array is explicitly allowed to be initialized with A a = { init-list };.
> +// Disable the missing braces warning for this reason.
> +#include "disable_missing_braces_warning.h"
> +
> +struct NoDefault {
> + NoDefault(int) {}
> +};
> +
> int main()
> {
> {
> @@ -28,4 +36,13 @@ int main()
> C c;
> assert(c.size() == 0);
> }
> + {
> + typedef std::array<NoDefault, 0> C;
> + C c;
> + assert(c.size() == 0);
> + C c1 = {};
> + assert(c1.size() == 0);
> + C c2 = {{}};
> + assert(c2.size() == 0);
> + }
> }
>
> Modified: libcxx/trunk/test/std/containers/sequences/array/array.data/data.pass.cpp
> URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/array/array.data/data.pass.cpp?rev=324182&r1=324181&r2=324182&view=diff
> ==============================================================================
> --- libcxx/trunk/test/std/containers/sequences/array/array.data/data.pass.cpp (original)
> +++ libcxx/trunk/test/std/containers/sequences/array/array.data/data.pass.cpp Sat Feb 3 17:03:08 2018
> @@ -36,4 +36,14 @@ int main()
> T* p = c.data();
> (void)p; // to placate scan-build
> }
> + {
> + struct NoDefault {
> + NoDefault(int) {}
> + };
> + typedef NoDefault T;
> + typedef std::array<T, 0> C;
> + C c = {};
> + T* p = c.data();
> + assert(p != nullptr);
> + }
> }
>
> Modified: libcxx/trunk/test/std/containers/sequences/array/array.data/data_const.pass.cpp
> URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/array/array.data/data_const.pass.cpp?rev=324182&r1=324181&r2=324182&view=diff
> ==============================================================================
> --- libcxx/trunk/test/std/containers/sequences/array/array.data/data_const.pass.cpp (original)
> +++ libcxx/trunk/test/std/containers/sequences/array/array.data/data_const.pass.cpp Sat Feb 3 17:03:08 2018
> @@ -38,6 +38,16 @@ int main()
> const T* p = c.data();
> (void)p; // to placate scan-build
> }
> + {
> + struct NoDefault {
> + NoDefault(int) {}
> + };
> + typedef NoDefault T;
> + typedef std::array<T, 0> C;
> + const C c = {};
> + const T* p = c.data();
> + assert(p != nullptr);
> + }
> #if TEST_STD_VER > 14
> {
> typedef std::array<int, 5> C;
>
> Modified: libcxx/trunk/test/std/containers/sequences/array/begin.pass.cpp
> URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/containers/sequences/array/begin.pass.cpp?rev=324182&r1=324181&r2=324182&view=diff
> ==============================================================================
> --- libcxx/trunk/test/std/containers/sequences/array/begin.pass.cpp (original)
> +++ libcxx/trunk/test/std/containers/sequences/array/begin.pass.cpp Sat Feb 3 17:03:08 2018
> @@ -31,4 +31,13 @@ int main()
> *i = 5.5;
> assert(c[0] == 5.5);
> }
> + {
> + struct NoDefault {
> + NoDefault(int) {}
> + };
> + typedef NoDefault T;
> + typedef std::array<T, 0> C;
> + C c = {};
> + assert(c.begin() == c.end());
> + }
> }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list