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