[gcc r10-8934] libstdc++: Remove overzealous static_asserts from std::span

Patrick Palka ppalka@gcc.gnu.org
Wed Oct 21 18:05:13 GMT 2020


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

commit r10-8934-geab76310e665a7d06e8ff9e8c8da44ddc5adc586
Author: Patrick Palka <ppalka@redhat.com>
Date:   Mon Sep 21 20:53:17 2020 -0400

    libstdc++: Remove overzealous static_asserts from std::span
    
    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[].
    
    (cherry picked from commit 37edf28c24b7bd198c27d266af9aefad417635fd)

Diff:
---
 libstdc++-v3/include/std/span                            |  3 ---
 libstdc++-v3/testsuite/23_containers/span/back_neg.cc    | 16 ++++++++++++----
 libstdc++-v3/testsuite/23_containers/span/front_neg.cc   | 16 ++++++++++++----
 .../testsuite/23_containers/span/index_op_neg.cc         | 16 ++++++++++++----
 4 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
index f658adb04cf..1cdc0589ddb 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -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);
       }
diff --git a/libstdc++-v3/testsuite/23_containers/span/back_neg.cc b/libstdc++-v3/testsuite/23_containers/span/back_neg.cc
index c451ed10df8..54d049d0d7e 100644
--- a/libstdc++-v3/testsuite/23_containers/span/back_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/span/back_neg.cc
@@ -18,12 +18,20 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do compile { target c++2a } }
 
+#undef _GLIBCXX_ASSERTIONS
+#define _GLIBCXX_ASSERTIONS
 #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" }
diff --git a/libstdc++-v3/testsuite/23_containers/span/front_neg.cc b/libstdc++-v3/testsuite/23_containers/span/front_neg.cc
index 38f87aa2cd5..9a6b3e2f97f 100644
--- a/libstdc++-v3/testsuite/23_containers/span/front_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/span/front_neg.cc
@@ -18,12 +18,20 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do compile { target c++2a } }
 
+#undef _GLIBCXX_ASSERTIONS
+#define _GLIBCXX_ASSERTIONS
 #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" }
diff --git a/libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc b/libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc
index 1e8b2d8724e..c88477438de 100644
--- a/libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc
@@ -18,12 +18,20 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do compile { target c++2a } }
 
+#undef _GLIBCXX_ASSERTIONS
+#define _GLIBCXX_ASSERTIONS
 #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" }


More information about the Libstdc++-cvs mailing list