[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