public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-113] libstdc++: Simplify std::array accessors [PR104719]
@ 2022-05-04 15:34 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2022-05-04 15:34 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:ef8d5ac08b5e60f35c52087d88c0235c8ce6b65b

commit r13-113-gef8d5ac08b5e60f35c52087d88c0235c8ce6b65b
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Mar 25 10:28:28 2022 +0000

    libstdc++: Simplify std::array accessors [PR104719]
    
    This removes the __array_traits::_S_ref and __array_traits::_S_ptr
    accessors, which only exist to make the special case of std::array<T, 0>
    syntactically well-formed.
    
    By changing the empty type used as the std::array<T, 0>::_M_elems data
    member to support operator[] and conversion to a pointer, we can write
    code using the natural syntax. The indirection through _S_ref and
    _S_ptr is removed for the common case, and a function call is only used
    for the special case of zero-size arrays.
    
    The invalid member access for zero-sized arrays is changed to use
    __builtin_trap() instead of a null dereference. This guarantees a
    runtime error if it ever gets called, instead of undefined behaviour
    that is likely to get optimized out as unreachable.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/104719
            * include/std/array (__array_traits::_S_ref): Remove.
            (__array_traits::_S_ptr): Remove.
            (__array_traits<T, 0>::_Type): Define operator[] and operator T*
            to provide an array-like API.
            (array::_AT_Type): Remove public typeef.
            (array::operator[], array::at, array::front, array::back): Use
            index operator to access _M_elems instead of _S_ref.
            (array::data): Use implicit conversion from _M_elems to pointer.
            (swap(array&, array&)): Use __enable_if_t helper.
            (get<I>): Use index operator to access _M_elems.
            * testsuite/23_containers/array/tuple_interface/get_neg.cc:
            Adjust dg-error line numbers.

Diff:
---
 libstdc++-v3/include/std/array                     | 80 ++++++++++------------
 .../23_containers/array/tuple_interface/get_neg.cc |  6 +-
 2 files changed, 38 insertions(+), 48 deletions(-)

diff --git a/libstdc++-v3/include/std/array b/libstdc++-v3/include/std/array
index e45143fb329..d1daffee425 100644
--- a/libstdc++-v3/include/std/array
+++ b/libstdc++-v3/include/std/array
@@ -49,36 +49,31 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
-  template<typename _Tp, std::size_t _Nm>
+  template<typename _Tp, size_t _Nm>
     struct __array_traits
     {
-      typedef _Tp _Type[_Nm];
-      typedef __is_swappable<_Tp> _Is_swappable;
-      typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable;
-
-      static constexpr _Tp&
-      _S_ref(const _Type& __t, std::size_t __n) noexcept
-      { return const_cast<_Tp&>(__t[__n]); }
-
-      static constexpr _Tp*
-      _S_ptr(const _Type& __t) noexcept
-      { return const_cast<_Tp*>(__t); }
+      using _Type = _Tp[_Nm];
+      using _Is_swappable = __is_swappable<_Tp>;
+      using _Is_nothrow_swappable = __is_nothrow_swappable<_Tp>;
     };
 
  template<typename _Tp>
    struct __array_traits<_Tp, 0>
    {
-     struct _Type { };
-     typedef true_type _Is_swappable;
-     typedef true_type _Is_nothrow_swappable;
-
-     static constexpr _Tp&
-     _S_ref(const _Type&, std::size_t) noexcept
-     { return *static_cast<_Tp*>(nullptr); }
-
-     static constexpr _Tp*
-     _S_ptr(const _Type&) noexcept
-     { return nullptr; }
+     // Empty type used instead of _Tp[0] for std::array<_Tp, 0>.
+     struct _Type
+     {
+       // Indexing is undefined.
+       __attribute__((__always_inline__,__artificial__,__noreturn__))
+       _Tp& operator[](size_t) const noexcept { __builtin_trap(); }
+
+       // Conversion to a pointer produces a null pointer.
+       __attribute__((__always_inline__,__artificial__))
+       operator _Tp*() const noexcept { return nullptr; }
+     };
+
+     using _Is_swappable = true_type;
+     using _Is_nothrow_swappable = true_type;
    };
 
   /**
@@ -111,8 +106,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef std::reverse_iterator<const_iterator>   const_reverse_iterator;
 
       // Support for zero-sized arrays mandatory.
-      typedef __array_traits<_Tp, _Nm> _AT_Type;
-      typename _AT_Type::_Type                         _M_elems;
+      typename __array_traits<_Tp, _Nm>::_Type        _M_elems;
 
       // No explicit construct/copy/destroy for aggregate type.
 
@@ -123,7 +117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       _GLIBCXX20_CONSTEXPR void
       swap(array& __other)
-      noexcept(_AT_Type::_Is_nothrow_swappable::value)
+      noexcept(__array_traits<_Tp, _Nm>::_Is_nothrow_swappable::value)
       { std::swap_ranges(begin(), end(), __other.begin()); }
 
       // Iterators.
@@ -206,7 +200,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       operator[](size_type __n) noexcept
       {
 	__glibcxx_requires_subscript(__n);
-	return _AT_Type::_S_ref(_M_elems, __n);
+	return _M_elems[__n];
       }
 
       [[__nodiscard__]]
@@ -216,7 +210,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus >= 201402L
 	__glibcxx_requires_subscript(__n);
 #endif
-	return _AT_Type::_S_ref(_M_elems, __n);
+	return _M_elems[__n];
       }
 
       _GLIBCXX17_CONSTEXPR reference
@@ -226,7 +220,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
 					    ">= _Nm (which is %zu)"),
 					__n, _Nm);
-	return _AT_Type::_S_ref(_M_elems, __n);
+	return _M_elems[__n];
       }
 
       constexpr const_reference
@@ -234,11 +228,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       {
 	// Result of conditional expression must be an lvalue so use
 	// boolean ? lvalue : (throw-expr, lvalue)
-	return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n)
+	return __n < _Nm ? _M_elems[__n]
 	  : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) "
 					       ">= _Nm (which is %zu)"),
 					   __n, _Nm),
-	     _AT_Type::_S_ref(_M_elems, 0));
+	     _M_elems[__n]);
       }
 
       [[__nodiscard__]]
@@ -246,7 +240,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       front() noexcept
       {
 	__glibcxx_requires_nonempty();
-	return *begin();
+	return _M_elems[0];
       }
 
       [[__nodiscard__]]
@@ -256,7 +250,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus >= 201402L
 	__glibcxx_requires_nonempty();
 #endif
-	return _AT_Type::_S_ref(_M_elems, 0);
+	return _M_elems[0];
       }
 
       [[__nodiscard__]]
@@ -264,7 +258,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       back() noexcept
       {
 	__glibcxx_requires_nonempty();
-	return _Nm ? *(end() - 1) : *end();
+	return _M_elems[_Nm - 1];
       }
 
       [[__nodiscard__]]
@@ -274,19 +268,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus >= 201402L
 	__glibcxx_requires_nonempty();
 #endif
-	return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1)
- 	           : _AT_Type::_S_ref(_M_elems, 0);
+	return _M_elems[_Nm - 1];
       }
 
       [[__gnu__::__const__, __nodiscard__]]
       _GLIBCXX17_CONSTEXPR pointer
       data() noexcept
-      { return _AT_Type::_S_ptr(_M_elems); }
+      { return _M_elems; }
 
       [[__nodiscard__]]
       _GLIBCXX17_CONSTEXPR const_pointer
       data() const noexcept
-      { return _AT_Type::_S_ptr(_M_elems); }
+      { return _M_elems; }
     };
 
 #if __cpp_deduction_guides >= 201606
@@ -371,9 +364,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline
 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
     // Constrained free swap overload, see p0185r1
-    typename enable_if<
-      __array_traits<_Tp, _Nm>::_Is_swappable::value
-    >::type
+    __enable_if_t<__array_traits<_Tp, _Nm>::_Is_swappable::value>
 #else
     void
 #endif
@@ -383,8 +374,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
   template<typename _Tp, std::size_t _Nm>
-    typename enable_if<
-      !__array_traits<_Tp, _Nm>::_Is_swappable::value>::type
+    __enable_if_t<!__array_traits<_Tp, _Nm>::_Is_swappable::value>
     swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete;
 #endif
 
@@ -394,7 +384,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     get(array<_Tp, _Nm>& __arr) noexcept
     {
       static_assert(_Int < _Nm, "array index is within bounds");
-      return __array_traits<_Tp, _Nm>::_S_ref(__arr._M_elems, _Int);
+      return __arr._M_elems[_Int];
     }
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
@@ -412,7 +402,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     get(const array<_Tp, _Nm>& __arr) noexcept
     {
       static_assert(_Int < _Nm, "array index is within bounds");
-      return __array_traits<_Tp, _Nm>::_S_ref(__arr._M_elems, _Int);
+      return __arr._M_elems[_Int];
     }
 
   template<std::size_t _Int, typename _Tp, std::size_t _Nm>
diff --git a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc
index ea1fd9f2f96..b97149474c9 100644
--- a/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/array/tuple_interface/get_neg.cc
@@ -26,6 +26,6 @@ int n1 = std::get<1>(a);
 int n2 = std::get<1>(std::move(a));
 int n3 = std::get<1>(ca);
 
-// { dg-error "static assertion failed" "" { target *-*-* } 396 }
-// { dg-error "static assertion failed" "" { target *-*-* } 405 }
-// { dg-error "static assertion failed" "" { target *-*-* } 414 }
+// { dg-error "static assertion failed" "" { target *-*-* } 386 }
+// { dg-error "static assertion failed" "" { target *-*-* } 395 }
+// { dg-error "static assertion failed" "" { target *-*-* } 404 }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-04 15:34 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-04 15:34 [gcc r13-113] libstdc++: Simplify std::array accessors [PR104719] Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).