jdoerrie created this revision.
jdoerrie added reviewers: mclow.lists, ldionne.
Herald added a reviewer: EricWF.
Herald added subscribers: libcxx-commits, dexonsmith, christof.

[libc++] Disallow dynamic -> static span conversions

This change disallows dynamic to static span conversions. This complies
with the standard, which lists the following constaint in
views.span#span.cons-20.1 [1]:

  Extent == dynamic_extent || Extent == OtherExtent

Thus this should fail if Extent != dynamic_extent && Extent !=
OtherExtent, which is the case when trying to construct a static span
from a dynamic span.

[1] https://eel.is/c++draft/views.span#span.cons-20.1


Repository:
  rCXX libc++

https://reviews.llvm.org/D69520

Files:
  libcxx/include/span
  libcxx/test/std/containers/views/span.cons/span.fail.cpp
  libcxx/test/std/containers/views/span.cons/span.pass.cpp

Index: libcxx/test/std/containers/views/span.cons/span.pass.cpp
===================================================================
--- libcxx/test/std/containers/views/span.cons/span.pass.cpp
+++ libcxx/test/std/containers/views/span.cons/span.pass.cpp
@@ -62,48 +62,41 @@
         std::span<const volatile int> s4{ vsp0};    // a span<const volatile int> pointing at volatile int.
         assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
     }
-
-//  dynamic -> static
-    {
-        std::span<const          int, 0> s1{  sp};  // a span<const          int> pointing at int.
-        std::span<      volatile int, 0> s2{  sp};  // a span<      volatile int> pointing at int.
-        std::span<const volatile int, 0> s3{  sp};  // a span<const volatile int> pointing at int.
-        std::span<const volatile int, 0> s4{ vsp};  // a span<const volatile int> pointing at volatile int.
-        assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
-    }
 }
 
 
 template <typename T>
 constexpr bool testConstexprSpan()
 {
-    std::span<T>    s0{};
-    std::span<T, 0> s1(s0); // dynamic -> static
-    std::span<T>    s2(s1); // static -> dynamic
-    ASSERT_NOEXCEPT(std::span<T>   {s0});
-    ASSERT_NOEXCEPT(std::span<T, 0>{s1});
-    ASSERT_NOEXCEPT(std::span<T>   {s1});
-    ASSERT_NOEXCEPT(std::span<T, 0>{s0});
-
-    return
-        s1.data() == nullptr && s1.size() == 0
-    &&  s2.data() == nullptr && s2.size() == 0;
+  std::span<T> s0d{};
+  std::span<T, 0> s0s{};
+  std::span<T> s1(s0d);    // dynamic -> dynamic
+  std::span<T, 0> s2(s0s); // static -> static
+  std::span<T> s3(s2);     // static -> dynamic
+  ASSERT_NOEXCEPT(std::span<T>{s0d});
+  ASSERT_NOEXCEPT(std::span<T, 0>{s0s});
+  ASSERT_NOEXCEPT(std::span<T>{s0s});
+
+  return s1.data() == nullptr && s1.size() == 0 && s2.data() == nullptr &&
+         s2.size() == 0 && s3.data() == nullptr && s3.size() == 0;
 }
 
 
 template <typename T>
 void testRuntimeSpan()
 {
-    std::span<T>    s0{};
-    std::span<T, 0> s1(s0); // dynamic -> static
-    std::span<T>    s2(s1); // static -> dynamic
-    ASSERT_NOEXCEPT(std::span<T>   {s0});
-    ASSERT_NOEXCEPT(std::span<T, 0>{s1});
-    ASSERT_NOEXCEPT(std::span<T>   {s1});
-    ASSERT_NOEXCEPT(std::span<T, 0>{s0});
-
-    assert(s1.data() == nullptr && s1.size() == 0);
-    assert(s2.data() == nullptr && s2.size() == 0);
+  std::span<T> s0d{};
+  std::span<T, 0> s0s{};
+  std::span<T> s1(s0d);    // dynamic -> dynamic
+  std::span<T, 0> s2(s0s); // static -> static
+  std::span<T> s3(s2);     // static -> dynamic
+  ASSERT_NOEXCEPT(std::span<T>{s0d});
+  ASSERT_NOEXCEPT(std::span<T, 0>{s0s});
+  ASSERT_NOEXCEPT(std::span<T>{s0s});
+
+  assert(s1.data() == nullptr && s1.size() == 0);
+  assert(s2.data() == nullptr && s2.size() == 0);
+  assert(s3.data() == nullptr && s3.size() == 0);
 }
 
 
@@ -113,10 +106,12 @@
     static_assert(std::is_convertible_v<Src(*)[], Dest(*)[]>, "Bad input types to 'testConversionSpan");
     std::span<Src>    s0d{};
     std::span<Src>    s0s{};
-    std::span<Dest, 0> s1(s0d); // dynamic -> static
-    std::span<Dest>    s2(s0s); // static -> dynamic
-        s1.data() == nullptr && s1.size() == 0
-    &&  s2.data() == nullptr && s2.size() == 0;
+    std::span<Dest> s1(s0d);    // dynamic -> dynamic
+    std::span<Dest, 0> s2(s0s); // static -> static
+    std::span<Dest> s3(s0d);    // static -> dynamic
+    s1.data() == nullptr&& s1.size() == 0 &&
+        s2.data() == nullptr&& s2.size() == 0 &&
+        s3.data() == nullptr&& s3.size() == 0;
 }
 
 struct A{};
Index: libcxx/test/std/containers/views/span.cons/span.fail.cpp
===================================================================
--- libcxx/test/std/containers/views/span.cons/span.fail.cpp
+++ libcxx/test/std/containers/views/span.cons/span.fail.cpp
@@ -74,19 +74,6 @@
     std::span<      volatile int> s6{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
     std::span<      volatile int> s7{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
     }
-
-//  Try to remove const and/or volatile (static -> static)
-    {
-    std::span<               int, 0> s1{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
-    std::span<               int, 0> s2{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
-    std::span<               int, 0> s3{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
-
-    std::span<const          int, 0> s4{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}}
-    std::span<const          int, 0> s5{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}}
-
-    std::span<      volatile int, 0> s6{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}}
-    std::span<      volatile int, 0> s7{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}}
-    }
 }
 
 int main(int, char**)
Index: libcxx/include/span
===================================================================
--- libcxx/include/span
+++ libcxx/include/span
@@ -232,15 +232,6 @@
                           nullptr_t> = nullptr)
         : __data{__other.data()} {}
 
-    template <class _OtherElementType>
-    _LIBCPP_INLINE_VISIBILITY
-        constexpr span(const span<_OtherElementType, dynamic_extent>& __other,
-                       enable_if_t<
-                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
-                          nullptr_t> = nullptr) noexcept
-        : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); }
-
-
 //  ~span() noexcept = default;
 
     template <size_t _Count>
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to