libstdc++: Remove overzealous static_asserts from std::span
authorPatrick Palka <ppalka@redhat.com>
Tue, 22 Sep 2020 00:53:17 +0000 (20:53 -0400)
committerPatrick Palka <ppalka@redhat.com>
Tue, 22 Sep 2020 03:21:34 +0000 (23:21 -0400)
For a span with statically empty extent, we currently model the
preconditions of front(), back(), and operator[] as if they are
mandates, by using a static_assert to verify that extent != 0.  This
causes us to reject valid programs that would instantiate these member
functions and at runtime never call them.

Since they are already followed by more general runtime asserts, this
patch just removes these static_asserts altogether,

libstdc++-v3/ChangeLog:

* include/std/span (span::front): Remove static_assert.
(span::back): Likewise.
(span::operator[]): Likewise.
* testsuite/23_containers/span/back_neg.cc: Rewrite to verify
that we check the preconditions of back() only when it's called.
* testsuite/23_containers/span/front_neg.cc: Likewise for
front().
* testsuite/23_containers/span/index_op_neg.cc: Likewise for
operator[].

libstdc++-v3/include/std/span
libstdc++-v3/testsuite/23_containers/span/back_neg.cc
libstdc++-v3/testsuite/23_containers/span/front_neg.cc
libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc

index f658adb04cf04259035cc95fe17ffbcdea0fbf45..1cdc0589ddb1e5a97742155ea1d86f6b7456cb0a 100644 (file)
@@ -264,7 +264,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr reference
       front() const noexcept
       {
-       static_assert(extent != 0);
        __glibcxx_assert(!empty());
        return *this->_M_ptr;
       }
@@ -272,7 +271,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr reference
       back() const noexcept
       {
-       static_assert(extent != 0);
        __glibcxx_assert(!empty());
        return *(this->_M_ptr + (size() - 1));
       }
@@ -280,7 +278,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr reference
       operator[](size_type __idx) const noexcept
       {
-       static_assert(extent != 0);
        __glibcxx_assert(__idx < size());
        return *(this->_M_ptr + __idx);
       }
index c451ed10df87f0d78f3e418977ba27adeac7bd91..f777edfa20c5b30d27f2670c037f7b3b6f597fe3 100644 (file)
 
 #include <span>
 
-void
-test01()
+constexpr bool
+test01(bool b)
 {
   std::span<int, 0> s;
-  s.back(); // { dg-error "here" }
+  if (b || !s.empty())
+    s.back();
+  return true;
 }
-// { dg-error "static assertion failed" "" { target *-*-* } 0 }
+
+static_assert(test01(false));
+static_assert(test01(true)); // { dg-error "non-constant" }
+// { dg-error "assert" "" { target *-*-* } 0 }
+// { dg-prune-output "in 'constexpr' expansion" }
index 38f87aa2cd5125c20264da13a43d884beb8998a6..14e5bc1e10096ade46ed0f563fe79edc171961fa 100644 (file)
 
 #include <span>
 
-void
-test01()
+constexpr bool
+test01(bool b)
 {
   std::span<int, 0> s;
-  s.front(); // { dg-error "here" }
+  if (b || !s.empty())
+    s.front();
+  return true;
 }
-// { dg-error "static assertion failed" "" { target *-*-* } 0 }
+
+static_assert(test01(false));
+static_assert(test01(true)); // { dg-error "non-constant" }
+// { dg-error "assert" "" { target *-*-* } 0 }
+// { dg-prune-output "in 'constexpr' expansion" }
index 1e8b2d8724eb127a77017286cb045cc1923025ec..6a3bb8834b432f0c0ae16de5daf98063187c8b81 100644 (file)
 
 #include <span>
 
-void
-test01()
+constexpr bool
+test01(bool b)
 {
   std::span<int, 0> s;
-  s[99]; // { dg-error "here" }
+  if (b || !s.empty())
+    s[99];
+  return true;
 }
-// { dg-error "static assertion failed" "" { target *-*-* } 0 }
+
+static_assert(test01(false));
+static_assert(test01(true)); // { dg-error "non-constant" }
+// { dg-error "assert" "" { target *-*-* } 0 }
+// { dg-prune-output "in 'constexpr' expansion" }