[libcxx] r324182 - [libc++] Fix PR35491 - std::array of zero-size doesn't work with non-default constructible types.
Nirav Davé via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 5 12:30:22 PST 2018
https://bugs.llvm.org/show_bug.cgi?id=36241
On Mon, Feb 5, 2018 at 10:20 AM Hans Wennborg via cfe-commits <
cfe-commits at lists.llvm.org> wrote:
> 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
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180205/94a34cbf/attachment-0001.html>
More information about the cfe-commits
mailing list