[libcxx-commits] [libcxx] 3a208c6 - [libc++] Implement P1394r4 for span: range constructor

Joe Loser via libcxx-commits libcxx-commits at lists.llvm.org
Fri Oct 8 14:01:34 PDT 2021


Author: Joe Loser
Date: 2021-10-08T17:00:39-04:00
New Revision: 3a208c68942e9f4d24bd235a6e497852da898cae

URL: https://github.com/llvm/llvm-project/commit/3a208c68942e9f4d24bd235a6e497852da898cae
DIFF: https://github.com/llvm/llvm-project/commit/3a208c68942e9f4d24bd235a6e497852da898cae.diff

LOG: [libc++] Implement P1394r4 for span: range constructor

Implement https://wg21.link/p1394 which allows span to be constructible
from any contiguous forwarding-range that has a compatible element type.

Fixes https://bugs.llvm.org/show_bug.cgi?id=51443

Reviewed By: ldionne, Quuxplusone, #libc

Differential Revision: https://reviews.llvm.org/D110503

Added: 
    libcxx/test/std/containers/views/span.cons/iterator_len.pass.cpp
    libcxx/test/std/containers/views/span.cons/iterator_len.verify.cpp
    libcxx/test/std/containers/views/span.cons/iterator_sentinel.pass.cpp
    libcxx/test/std/containers/views/span.cons/iterator_sentinel.verify.cpp
    libcxx/test/std/containers/views/span.cons/range.pass.cpp

Modified: 
    libcxx/docs/Status/Cxx20Papers.csv
    libcxx/include/span
    libcxx/test/std/containers/views/span.cons/assign.pass.cpp
    libcxx/test/std/containers/views/span.cons/copy.pass.cpp
    libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
    libcxx/test/std/containers/views/span.elem/back.pass.cpp
    libcxx/test/std/containers/views/span.elem/data.pass.cpp
    libcxx/test/std/containers/views/span.elem/front.pass.cpp
    libcxx/test/std/containers/views/span.elem/op_idx.pass.cpp
    libcxx/test/std/containers/views/span.iterators/begin.pass.cpp
    libcxx/test/std/containers/views/span.iterators/end.pass.cpp
    libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp
    libcxx/test/std/containers/views/span.iterators/rend.pass.cpp
    libcxx/test/std/containers/views/span.objectrep/as_bytes.pass.cpp
    libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.fail.cpp
    libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.pass.cpp
    libcxx/test/std/containers/views/span.obs/empty.pass.cpp
    libcxx/test/std/containers/views/span.obs/size.pass.cpp
    libcxx/test/std/containers/views/span.obs/size_bytes.pass.cpp
    libcxx/test/std/containers/views/span.sub/first.fail.cpp
    libcxx/test/std/containers/views/span.sub/first.pass.cpp
    libcxx/test/std/containers/views/span.sub/last.fail.cpp
    libcxx/test/std/containers/views/span.sub/last.pass.cpp
    libcxx/test/std/containers/views/span.sub/subspan.fail.cpp
    libcxx/test/std/containers/views/span.sub/subspan.pass.cpp

Removed: 
    libcxx/test/std/containers/views/span.cons/container.fail.cpp
    libcxx/test/std/containers/views/span.cons/container.pass.cpp
    libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp
    libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp
    libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp
    libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp


################################################################################
diff  --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv
index 7167009bd54c7..152889c853777 100644
--- a/libcxx/docs/Status/Cxx20Papers.csv
+++ b/libcxx/docs/Status/Cxx20Papers.csv
@@ -135,7 +135,7 @@
 "","","","","",""
 "`P0883 <https://wg21.link/P0883>`__","LWG","Fixing Atomic Initialization","Belfast","|Complete| [#note-P0883]_","13.0"
 "`P1391 <https://wg21.link/P1391>`__","LWG","Range constructor for std::string_view","Belfast","|Complete|","14.0"
-"`P1394 <https://wg21.link/P1394>`__","LWG","Range constructor for std::span","Belfast","* *",""
+"`P1394 <https://wg21.link/P1394>`__","LWG","Range constructor for std::span","Belfast","|Complete|","14.0"
 "`P1456 <https://wg21.link/P1456>`__","LWG","Move-only views","Belfast","* *",""
 "`P1622 <https://wg21.link/P1622>`__","LWG","Mandating the Standard Library: Clause 32 - Thread support library","Belfast","* *",""
 "`P1645 <https://wg21.link/P1645>`__","LWG","constexpr for numeric algorithms","Belfast","|Complete|","12.0"

diff  --git a/libcxx/include/span b/libcxx/include/span
index fe247e8938325..2f1a19d42bcdf 100644
--- a/libcxx/include/span
+++ b/libcxx/include/span
@@ -56,18 +56,18 @@ public:
 
     // [span.cons], span constructors, copy, assignment, and destructor
     constexpr span() noexcept;
-    constexpr explicit(Extent != dynamic_extent) span(pointer ptr, size_type count);
-    constexpr explicit(Extent != dynamic_extent) span(pointer firstElem, pointer lastElem);
+    template <class It>
+    constexpr explicit(Extent != dynamic_extent) span(It first, size_type count);
+    template <class It, class End>
+    constexpr explicit(Extent != dynamic_extent) span(It first, End last);
     template <size_t N>
         constexpr span(element_type (&arr)[N]) noexcept;
     template <size_t N>
         constexpr span(array<value_type, N>& arr) noexcept;
     template <size_t N>
         constexpr span(const array<value_type, N>& arr) noexcept;
-    template <class Container>
-        constexpr explicit(Extent != dynamic_extent) span(Container& cont);
-    template <class Container>
-        constexpr explicit(Extent != dynamic_extent) span(const Container& cont);
+    template<class R>
+      constexpr explicit(Extent != dynamic_extent) span(R&& r);
     constexpr span(const span& other) noexcept = default;
     template <class OtherElementType, size_t OtherExtent>
         constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept;
@@ -108,6 +108,9 @@ private:
     size_type size_;  // exposition only
 };
 
+template<class It, class EndOrSize>
+    span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;
+
 template<class T, size_t N>
     span(T (&)[N]) -> span<T, N>;
 
@@ -117,11 +120,8 @@ template<class T, size_t N>
 template<class T, size_t N>
     span(const array<T, N>&) -> span<const T, N>;
 
-template<class Container>
-    span(Container&) -> span<typename Container::value_type>;
-
-template<class Container>
-    span(const Container&) -> span<const typename Container::value_type>;
+template<class R>
+    span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;
 
 } // namespace std
 
@@ -129,9 +129,13 @@ template<class Container>
 
 #include <__config>
 #include <__debug>
+#include <__iterator/concepts.h>
 #include <__iterator/wrap_iter.h>
+#include <__ranges/concepts.h>
+#include <__ranges/data.h>
 #include <__ranges/enable_borrowed_range.h>
 #include <__ranges/enable_view.h>
+#include <__ranges/size.h>
 #include <array>        // for array
 #include <cstddef>      // for byte
 #include <iterator>     // for iterators
@@ -155,46 +159,28 @@ template <typename _Tp, size_t _Extent = dynamic_extent> class span;
 
 
 template <class _Tp>
-struct __is_span_impl : public false_type {};
+struct __is_std_array : false_type {};
 
-template <class _Tp, size_t _Extent>
-struct __is_span_impl<span<_Tp, _Extent>> : public true_type {};
-
-template <class _Tp>
-struct __is_span : public __is_span_impl<remove_cv_t<_Tp>> {};
+template <class _Tp, size_t _Sz>
+struct __is_std_array<array<_Tp, _Sz>> : true_type {};
 
 template <class _Tp>
-struct __is_std_array_impl : public false_type {};
+struct __is_std_span : false_type {};
 
 template <class _Tp, size_t _Sz>
-struct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {};
-
-template <class _Tp>
-struct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {};
-
-template <class _Tp, class _ElementType, class = void>
-struct __is_span_compatible_container : public false_type {};
-
-template <class _Tp, class _ElementType>
-struct __is_span_compatible_container<_Tp, _ElementType,
-        void_t<
-        // is not a specialization of span
-            enable_if_t<!__is_span<_Tp>::value, nullptr_t>,
-        // is not a specialization of array
-            enable_if_t<!__is_std_array<_Tp>::value, nullptr_t>,
-        // is_array_v<Container> is false,
-            enable_if_t<!is_array_v<_Tp>, nullptr_t>,
-        // data(cont) and size(cont) are well formed
-            decltype(data(declval<_Tp>())),
-            decltype(size(declval<_Tp>())),
-        // remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[]
-            enable_if_t<
-                is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[],
-                                 _ElementType(*)[]>,
-                nullptr_t>
-        >>
-    : public true_type {};
+struct __is_std_span<span<_Tp, _Sz>> : true_type {};
 
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+template <class _Range, class _ElementType>
+concept __span_compatible_range =
+  ranges::contiguous_range<_Range> &&
+  ranges::sized_range<_Range> &&
+  (ranges::borrowed_range<_Range> || is_const_v<_ElementType>) &&
+  !__is_std_span<remove_cvref_t<_Range>>::value  &&
+  !__is_std_array<remove_cvref_t<_Range>>::value &&
+  !is_array_v<remove_cvref_t<_Range>> &&
+  is_convertible_v<remove_reference_t<ranges::range_reference_t<_Range>>(*)[], _ElementType(*)[]>;
+#endif
 
 template <typename _Tp, size_t _Extent>
 class _LIBCPP_TEMPLATE_VIS span {
@@ -224,10 +210,31 @@ public:
     constexpr span           (const span&) noexcept = default;
     constexpr span& operator=(const span&) noexcept = default;
 
-    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __ptr, size_type __count) : __data{__ptr}
-        { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); }
-    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __f, pointer __l) : __data{__f}
-        { (void)__l;     _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+    template <class _It,
+              enable_if_t<contiguous_iterator<_It> &&
+                              is_convertible_v<remove_reference_t<iter_reference_t<_It>>(*)[], element_type (*)[]>,
+                          nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr explicit span(_It __first, size_type __count)
+        : __data{_VSTD::to_address(__first)} {
+      (void)__count;
+      _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (iterator, len)");
+    }
+
+    template <
+        class _It, class _End,
+        enable_if_t<is_convertible_v<remove_reference_t<iter_reference_t<_It> > (*)[], element_type (*)[]> &&
+                        contiguous_iterator<_It> && sized_sentinel_for<_End, _It> && !is_convertible_v<_End, size_t>,
+                    nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr explicit span(_It __first, _End __last) : __data{_VSTD::to_address(__first)} {
+      (void)__last;
+      _LIBCPP_ASSERT((__last - __first >= 0), "invalid range in span's constructor (iterator, sentinel)");
+      _LIBCPP_ASSERT(__last - __first == _Extent,
+                     "invalid range in span's constructor (iterator, sentinel): last - first != extent");
+    }
+#endif
 
     _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent])          noexcept : __data{__arr} {}
 
@@ -241,21 +248,13 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
 
-    template <class _Container>
-    _LIBCPP_INLINE_VISIBILITY
-        constexpr explicit span(      _Container& __c,
-            enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
-        : __data{_VSTD::data(__c)} {
-            _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
-        }
-
-    template <class _Container>
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+    template <__span_compatible_range<element_type> _Range>
     _LIBCPP_INLINE_VISIBILITY
-        constexpr explicit span(const _Container& __c,
-            enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
-        : __data{_VSTD::data(__c)} {
-            _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
-        }
+    constexpr explicit span(_Range&& __r) : __data{ranges::data(__r)} {
+      _LIBCPP_ASSERT(ranges::size(__r) == _Extent, "size mismatch in span's constructor (range)");
+    }
+#endif
 
     template <class _OtherElementType>
     _LIBCPP_INLINE_VISIBILITY
@@ -402,8 +401,24 @@ public:
     constexpr span           (const span&) noexcept = default;
     constexpr span& operator=(const span&) noexcept = default;
 
-    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, size_type __count) : __data{__ptr}, __size{__count} {}
-    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<size_t>(distance(__f, __l))} {}
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+    template <class _It,
+              enable_if_t<contiguous_iterator<_It> &&
+                              is_convertible_v<remove_reference_t<iter_reference_t<_It> > (*)[], element_type (*)[]>,
+                          nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr span(_It __first, size_type __count)
+        : __data{_VSTD::to_address(__first)}, __size{__count} {}
+
+    template <
+        class _It, class _End,
+        enable_if_t<is_convertible_v<remove_reference_t<iter_reference_t<_It> > (*)[], element_type (*)[]> &&
+                        contiguous_iterator<_It> && sized_sentinel_for<_End, _It> && !is_convertible_v<_End, size_t>,
+                    nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr span(_It __first, _End __last)
+        : __data(_VSTD::to_address(__first)), __size(__last - __first) {}
+#endif
 
     template <size_t _Sz>
     _LIBCPP_INLINE_VISIBILITY
@@ -419,18 +434,11 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
 
-    template <class _Container>
-    _LIBCPP_INLINE_VISIBILITY
-        constexpr span(      _Container& __c,
-            enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
-        : __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {}
-
-    template <class _Container>
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+    template <__span_compatible_range<element_type> _Range>
     _LIBCPP_INLINE_VISIBILITY
-        constexpr span(const _Container& __c,
-            enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
-        : __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {}
-
+    constexpr span(_Range&& __r) : __data(ranges::data(__r)), __size{ranges::size(__r)} {}
+#  endif
 
     template <class _OtherElementType, size_t _OtherExtent>
     _LIBCPP_INLINE_VISIBILITY
@@ -556,7 +564,12 @@ auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept
 -> enable_if_t<!is_const_v<_Tp>, decltype(__s.__as_writable_bytes())>
 { return __s.__as_writable_bytes(); }
 
+#if !defined(_LIBCPP_HAS_NO_RANGES)
 //  Deduction guides
+template<contiguous_iterator _It, class _EndOrSize>
+    span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;
+#endif
+
 template<class _Tp, size_t _Sz>
     span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
 
@@ -566,11 +579,10 @@ template<class _Tp, size_t _Sz>
 template<class _Tp, size_t _Sz>
     span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
 
-template<class _Container>
-    span(_Container&) -> span<typename _Container::value_type>;
-
-template<class _Container>
-    span(const _Container&) -> span<const typename _Container::value_type>;
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+template<ranges::contiguous_range _Range>
+    span(_Range&&) -> span<remove_reference_t<ranges::range_reference_t<_Range>>>;
+#endif
 
 #endif // _LIBCPP_STD_VER > 17
 

diff  --git a/libcxx/test/std/containers/views/span.cons/assign.pass.cpp b/libcxx/test/std/containers/views/span.cons/assign.pass.cpp
index 0228386cc8abd..74588dfe565b0 100644
--- a/libcxx/test/std/containers/views/span.cons/assign.pass.cpp
+++ b/libcxx/test/std/containers/views/span.cons/assign.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.cons/container.fail.cpp b/libcxx/test/std/containers/views/span.cons/container.fail.cpp
deleted file mode 100644
index 6fdb8e7a5950d..0000000000000
--- a/libcxx/test/std/containers/views/span.cons/container.fail.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// <span>
-
-//  template<class Container>
-//     constexpr span(Container& cont);
-//   template<class Container>
-//     constexpr span(const Container& cont);
-//
-// Remarks: These constructors shall not participate in overload resolution unless:
-//   — extent == dynamic_extent,
-//   — Container is not a specialization of span,
-//   — Container is not a specialization of array,
-//   — is_array_v<Container> is false,
-//   — data(cont) and size(cont) are both well-formed, and
-//   — remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[].
-//
-
-#include <span>
-#include <cassert>
-#include <deque>
-#include <forward_list>
-#include <list>
-#include <vector>
-
-#include "test_macros.h"
-
-//  Look ma - I'm a container!
-template <typename T>
-struct IsAContainer {
-    constexpr IsAContainer() : v_{} {}
-    constexpr size_t size() const {return 1;}
-    constexpr       T *data() {return &v_;}
-    constexpr const T *data() const {return &v_;}
-
-    constexpr const T *getV() const {return &v_;} // for checking
-    T v_;
-};
-
-template <typename T>
-struct NotAContainerNoData {
-    size_t size() const {return 0;}
-};
-
-template <typename T>
-struct NotAContainerNoSize {
-    const T *data() const {return nullptr;}
-};
-
-template <typename T>
-struct NotAContainerPrivate {
-private:
-    size_t size() const {return 0;}
-    const T *data() const {return nullptr;}
-};
-
-template<class T, size_t extent, class container>
-std::span<T, extent> createImplicitSpan(container c) {
-    return {c}; // expected-error {{chosen constructor is explicit in copy-initialization}}
-}
-
-int main(int, char**)
-{
-
-//  Making non-const spans from const sources (a temporary binds to `const &`)
-    {
-    std::span<int>    s1{IsAContainer<int>()};          // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<int>    s3{std::vector<int>()};           // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    }
-
-//  Missing size and/or data
-    {
-    std::span<const int>    s1{NotAContainerNoData<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const int>    s3{NotAContainerNoSize<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const int>    s5{NotAContainerPrivate<int>()};  // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-
-//  Again with the standard containers
-    std::span<const int>    s11{std::deque<int>()};           // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const int>    s13{std::list<int>()};            // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const int>    s15{std::forward_list<int>()};    // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    }
-
-//  Not the same type
-    {
-    IsAContainer<int> c;
-    std::span<float>    s1{c};   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
-    }
-
-//  CV wrong
-    {
-    IsAContainer<const          int> c;
-    IsAContainer<const volatile int> cv;
-    IsAContainer<      volatile int> v;
-
-    std::span<               int> s1{c};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s2{v};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s3{cv};   // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<const          int> s4{v};    // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const          int> s5{cv};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<      volatile int> s6{c};    // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    std::span<      volatile int> s7{cv};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    }
-
-// explicit constructor necessary
-    {
-    IsAContainer<int> c;
-    const IsAContainer<int> cc;
-
-    createImplicitSpan<int, 1>(c);
-    createImplicitSpan<int, 1>(cc);
-    }
-
-  return 0;
-}

diff  --git a/libcxx/test/std/containers/views/span.cons/container.pass.cpp b/libcxx/test/std/containers/views/span.cons/container.pass.cpp
deleted file mode 100644
index c229cbaad9cac..0000000000000
--- a/libcxx/test/std/containers/views/span.cons/container.pass.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// <span>
-
-//  template<class Container>
-//     constexpr span(Container& cont);
-//   template<class Container>
-//     constexpr span(const Container& cont);
-//
-// Remarks: These constructors shall not participate in overload resolution unless:
-//   — extent == dynamic_extent,
-//   — Container is not a specialization of span,
-//   — Container is not a specialization of array,
-//   — is_array_v<Container> is false,
-//   — data(cont) and size(cont) are both well-formed, and
-//   — remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[].
-//
-
-
-#include <span>
-#include <cassert>
-#include <string>
-#include <vector>
-
-#include "test_macros.h"
-
-//  Look ma - I'm a container!
-template <typename T>
-struct IsAContainer {
-    constexpr IsAContainer() : v_{} {}
-    constexpr size_t size() const {return 1;}
-    constexpr       T *data() {return &v_;}
-    constexpr const T *data() const {return &v_;}
-    constexpr       T *begin() {return &v_;}
-    constexpr const T *begin() const {return &v_;}
-    constexpr       T *end() {return &v_ + 1;}
-    constexpr const T *end() const {return &v_ + 1;}
-
-    constexpr T const *getV() const {return &v_;} // for checking
-    T v_;
-};
-
-
-void checkCV()
-{
-    std::vector<int> v  = {1,2,3};
-
-//  Types the same
-    {
-    std::span<               int> s1{v};    // a span<               int> pointing at int.
-    }
-
-//  types 
diff erent
-    {
-    std::span<const          int> s1{v};    // a span<const          int> pointing at int.
-    std::span<      volatile int> s2{v};    // a span<      volatile int> pointing at int.
-    std::span<      volatile int> s3{v};    // a span<      volatile int> pointing at const int.
-    std::span<const volatile int> s4{v};    // a span<const volatile int> pointing at int.
-    }
-
-//  Constructing a const view from a temporary
-    {
-    std::span<const int>    s1{IsAContainer<int>()};
-    std::span<const int>    s3{std::vector<int>()};
-    (void) s1;
-    (void) s3;
-    }
-}
-
-
-template <typename T>
-constexpr bool testConstexprSpan()
-{
-    constexpr IsAContainer<const T> val{};
-    std::span<const T> s1{val};
-    return s1.data() == val.getV() && s1.size() == 1;
-}
-
-template <typename T>
-constexpr bool testConstexprSpanStatic()
-{
-    constexpr IsAContainer<const T> val{};
-    std::span<const T, 1> s1{val};
-    return s1.data() == val.getV() && s1.size() == 1;
-}
-
-template <typename T>
-void testRuntimeSpan()
-{
-    IsAContainer<T> val{};
-    const IsAContainer<T> cVal;
-    std::span<T>       s1{val};
-    std::span<const T> s2{cVal};
-    assert(s1.data() == val.getV()  && s1.size() == 1);
-    assert(s2.data() == cVal.getV() && s2.size() == 1);
-}
-
-template <typename T>
-void testRuntimeSpanStatic()
-{
-    IsAContainer<T> val{};
-    const IsAContainer<T> cVal;
-    std::span<T, 1>       s1{val};
-    std::span<const T, 1> s2{cVal};
-    assert(s1.data() == val.getV()  && s1.size() == 1);
-    assert(s2.data() == cVal.getV() && s2.size() == 1);
-}
-
-struct A{};
-
-int main(int, char**)
-{
-    static_assert(testConstexprSpan<int>(),    "");
-    static_assert(testConstexprSpan<long>(),   "");
-    static_assert(testConstexprSpan<double>(), "");
-    static_assert(testConstexprSpan<A>(),      "");
-
-    static_assert(testConstexprSpanStatic<int>(),    "");
-    static_assert(testConstexprSpanStatic<long>(),   "");
-    static_assert(testConstexprSpanStatic<double>(), "");
-    static_assert(testConstexprSpanStatic<A>(),      "");
-
-    testRuntimeSpan<int>();
-    testRuntimeSpan<long>();
-    testRuntimeSpan<double>();
-    testRuntimeSpan<std::string>();
-    testRuntimeSpan<A>();
-
-    testRuntimeSpanStatic<int>();
-    testRuntimeSpanStatic<long>();
-    testRuntimeSpanStatic<double>();
-    testRuntimeSpanStatic<std::string>();
-    testRuntimeSpanStatic<A>();
-
-    checkCV();
-
-  return 0;
-}

diff  --git a/libcxx/test/std/containers/views/span.cons/copy.pass.cpp b/libcxx/test/std/containers/views/span.cons/copy.pass.cpp
index 28f13e122ddc5..1ac7c181815ba 100644
--- a/libcxx/test/std/containers/views/span.cons/copy.pass.cpp
+++ b/libcxx/test/std/containers/views/span.cons/copy.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp b/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
index 21fd3df2cd0ed..55ed727ef4902 100644
--- a/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
@@ -6,9 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 
+//   template<class It, class EndOrSize>
+//     span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;
+//
 //   template<class T, size_t N>
 //     span(T (&)[N]) -> span<T, N>;
 //
@@ -18,12 +25,8 @@
 //   template<class T, size_t N>
 //     span(const array<T, N>&) -> span<const T, N>;
 //
-//   template<class Container>
-//     span(Container&) -> span<typename Container::value_type>;
-//
-//   template<class Container>
-//     span(const Container&) -> span<const typename Container::value_type>;
-
+//   template<class R>
+//     span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;
 
 
 #include <span>
@@ -34,10 +37,25 @@
 
 #include "test_macros.h"
 
-int main(int, char**)
-{
+void test_iterator_sentinel() {
+  int arr[] = {1, 2, 3};
+  {
+  std::span s{std::begin(arr), std::end(arr)};
+  ASSERT_SAME_TYPE(decltype(s), std::span<int>);
+  assert(s.size() == std::size(arr));
+  assert(s.data() == std::data(arr));
+  }
+  {
+  std::span s{std::begin(arr), 3};
+  ASSERT_SAME_TYPE(decltype(s), std::span<int>);
+  assert(s.size() == std::size(arr));
+  assert(s.data() == std::data(arr));
+  }
+}
+
+void test_c_array() {
     {
-    int arr[] = {1,2,3};
+    int arr[] = {1, 2, 3};
     std::span s{arr};
     ASSERT_SAME_TYPE(decltype(s), std::span<int, 3>);
     assert(s.size() == std::size(arr));
@@ -51,7 +69,9 @@ int main(int, char**)
     assert(s.size() == std::size(arr));
     assert(s.data() == std::data(arr));
     }
+}
 
+void test_std_array() {
     {
     std::array<double, 4> arr = {1.0, 2.0, 3.0, 4.0};
     std::span s{arr};
@@ -67,7 +87,9 @@ int main(int, char**)
     assert(s.size() == arr.size());
     assert(s.data() == arr.data());
     }
+}
 
+void test_range_std_container() {
     {
     std::string str{"ABCDE"};
     std::span s{str};
@@ -83,6 +105,14 @@ int main(int, char**)
     assert(s.size() == str.size());
     assert(s.data() == str.data());
     }
+}
+
+int main(int, char**)
+{
+  test_iterator_sentinel();
+  test_c_array();
+  test_std_array();
+  test_range_std_container();
 
   return 0;
 }

diff  --git a/libcxx/test/std/containers/views/span.cons/iterator_len.pass.cpp b/libcxx/test/std/containers/views/span.cons/iterator_len.pass.cpp
new file mode 100644
index 0000000000000..6670a213e7bb1
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/iterator_len.pass.cpp
@@ -0,0 +1,72 @@
+//===---------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
+
+// <span>
+
+// template <class It>
+// constexpr explicit(Extent != dynamic_extent) span(It first, size_type count);
+//  If Extent is not equal to dynamic_extent, then count shall be equal to Extent.
+//
+
+
+#include <span>
+#include <cassert>
+#include <iterator>
+#include <type_traits>
+
+template <size_t Extent>
+constexpr void test_constructibility() {
+  struct Other {};
+  static_assert(std::is_constructible_v<std::span<int, Extent>, int*, size_t>);
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, const int*, size_t>);
+  static_assert(std::is_constructible_v<std::span<const int, Extent>, int*, size_t>);
+  static_assert(std::is_constructible_v<std::span<const int, Extent>, const int*, size_t>);
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, volatile int*, size_t>);
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, const volatile int*, size_t>);
+  static_assert(!std::is_constructible_v<std::span<const int, Extent>, volatile int*, size_t>);
+  static_assert(!std::is_constructible_v<std::span<const int, Extent>, const volatile int*, size_t>);
+  static_assert(!std::is_constructible_v<std::span<volatile int, Extent>, const int*, size_t>);
+  static_assert(!std::is_constructible_v<std::span<volatile int, Extent>, const volatile int*, size_t>);
+  static_assert(
+      !std::is_constructible_v<std::span<int, Extent>, double*, size_t>); // iterator type 
diff ers from span type
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, size_t, size_t>);
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, Other*, size_t>); // unrelated iterator type
+}
+
+template <class T>
+constexpr bool test_ctor() {
+  T val[2] = {};
+  auto s1 = std::span<T>(val, 2);
+  auto s2 = std::span<T, 2>(val, 2);
+  assert(s1.data() == std::data(val) && s1.size() == std::size(val));
+  assert(s2.data() == std::data(val) && s2.size() == std::size(val));
+  return true;
+}
+
+constexpr bool test() {
+  test_constructibility<std::dynamic_extent>();
+  test_constructibility<3>();
+
+  struct A {};
+  test_ctor<int>();
+  test_ctor<A>();
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/containers/views/span.cons/iterator_len.verify.cpp b/libcxx/test/std/containers/views/span.cons/iterator_len.verify.cpp
new file mode 100644
index 0000000000000..b2472a96ac252
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/iterator_len.verify.cpp
@@ -0,0 +1,37 @@
+//===---------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
+
+// <span>
+
+// template <class It>
+// constexpr explicit(Extent != dynamic_extent) span(It first, size_type count);
+//  If Extent is not equal to dynamic_extent, then count shall be equal to Extent.
+//
+
+#include <span>
+#include <cstddef>
+
+template <class T, size_t extent>
+std::span<T, extent> createImplicitSpan(T* ptr, size_t len) {
+  return {ptr, len}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
+
+int main(int, char**) {
+  // explicit constructor necessary
+  int arr[] = {1, 2, 3};
+  createImplicitSpan<int, 1>(arr, 3);
+
+  std::span<const int> sp = {0, 0}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+
+  return 0;
+}

diff  --git a/libcxx/test/std/containers/views/span.cons/iterator_sentinel.pass.cpp b/libcxx/test/std/containers/views/span.cons/iterator_sentinel.pass.cpp
new file mode 100644
index 0000000000000..8fb9a75bf44db
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/iterator_sentinel.pass.cpp
@@ -0,0 +1,67 @@
+//===---------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
+
+// <span>
+
+// template <class It, class End>
+// constexpr explicit(Extent != dynamic_extent) span(It first, End last);
+// Requires: [first, last) shall be a valid range.
+//   If Extent is not equal to dynamic_extent, then last - first shall be equal to Extent.
+//
+
+#include <span>
+#include <cassert>
+
+#include "test_iterators.h"
+
+template <class T, class Sentinel>
+constexpr bool test_ctor() {
+  T val[2] = {};
+  auto s1 = std::span<T>(std::begin(val), Sentinel(std::end(val)));
+  auto s2 = std::span<T, 2>(std::begin(val), Sentinel(std::end(val)));
+  assert(s1.data() == std::data(val) && s1.size() == std::size(val));
+  assert(s2.data() == std::data(val) && s2.size() == std::size(val));
+  return true;
+}
+
+template <size_t Extent>
+constexpr void test_constructibility() {
+  static_assert(std::is_constructible_v<std::span<int, Extent>, int*, int*>);
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, const int*, const int*>);
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, volatile int*, volatile int*>);
+  static_assert(std::is_constructible_v<std::span<const int, Extent>, int*, int*>);
+  static_assert(std::is_constructible_v<std::span<const int, Extent>, const int*, const int*>);
+  static_assert(!std::is_constructible_v<std::span<const int, Extent>, volatile int*, volatile int*>);
+  static_assert(std::is_constructible_v<std::span<volatile int, Extent>, int*, int*>);
+  static_assert(!std::is_constructible_v<std::span<volatile int, Extent>, const int*, const int*>);
+  static_assert(std::is_constructible_v<std::span<volatile int, Extent>, volatile int*, volatile int*>);
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, int*, float*>); // types wrong
+}
+
+constexpr bool test() {
+  test_constructibility<std::dynamic_extent>();
+  test_constructibility<3>();
+  struct A {};
+  assert((test_ctor<int, int*>()));
+  assert((test_ctor<int, sized_sentinel<int*>>()));
+  assert((test_ctor<A, A*>()));
+  assert((test_ctor<A, sized_sentinel<A*>>()));
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/containers/views/span.cons/iterator_sentinel.verify.cpp b/libcxx/test/std/containers/views/span.cons/iterator_sentinel.verify.cpp
new file mode 100644
index 0000000000000..986e07612d018
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/iterator_sentinel.verify.cpp
@@ -0,0 +1,37 @@
+//===---------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
+
+// <span>
+
+// template <class It, class End>
+// constexpr explicit(Extent != dynamic_extent) span(It first, End last);
+// Requires: [first, last) shall be a valid range.
+//   If Extent is not equal to dynamic_extent, then last - first shall be equal to Extent.
+//
+
+#include <span>
+#include <iterator>
+
+
+template<class T, size_t Extent>
+std::span<T, Extent> createImplicitSpan(T* first, T* last) {
+    return {first, last}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
+
+int main(int, char**) {
+  // explicit constructor necessary
+  int arr[] = {1, 2, 3};
+  createImplicitSpan<int, 1>(std::begin(arr), std::end(arr));
+
+  return 0;
+}

diff  --git a/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp b/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp
deleted file mode 100644
index b24eecc1552ed..0000000000000
--- a/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// <span>
-
-// constexpr span(pointer ptr, size_type count);
-// Requires: [ptr, ptr + count) shall be a valid range.
-//  If extent is not equal to dynamic_extent, then count shall be equal to extent.
-//
-
-#include <span>
-#include <cassert>
-#include <string>
-
-#include "test_macros.h"
-
-
-               int   arr[] = {1,2,3};
-const          int  carr[] = {4,5,6};
-      volatile int  varr[] = {7,8,9};
-const volatile int cvarr[] = {1,3,5};
-
-template<class T, size_t extent>
-std::span<T, extent> createImplicitSpan(T* ptr, size_t len) {
-    return {ptr, len}; // expected-error {{chosen constructor is explicit in copy-initialization}}
-}
-
-int main(int, char**)
-{
-//  We can't check that the size doesn't match - because that's a runtime property
-//  std::span<int, 2>   s1(arr, 3);
-
-//  Type wrong
-    {
-    std::span<float>    s1(arr, 3);   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
-    std::span<float, 3> s2(arr, 3);   // expected-error {{no matching constructor for initialization of 'std::span<float, 3>'}}
-    }
-
-//  CV wrong (dynamically sized)
-    {
-    std::span<               int> s1{ carr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s2{ varr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s3{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<const          int> s4{ varr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const          int> s5{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<      volatile int> s6{ carr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    std::span<      volatile int> s7{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    }
-
-//  CV wrong (statically sized)
-    {
-    std::span<               int,3> s1{ carr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<               int,3> s2{ varr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<               int,3> s3{cvarr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<const          int,3> s4{ varr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
-    std::span<const          int,3> s5{cvarr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
-    std::span<      volatile int,3> s6{ carr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
-    std::span<      volatile int,3> s7{cvarr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
-    }
-
-// explicit constructor necessary
-    {
-    createImplicitSpan<int, 1>(arr, 1);
-    }
-
-  return 0;
-}

diff  --git a/libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp b/libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp
deleted file mode 100644
index 6b18ac00101f4..0000000000000
--- a/libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// <span>
-
-// constexpr span(pointer ptr, size_type count);
-// Requires: [ptr, ptr + count) shall be a valid range.
-//  If extent is not equal to dynamic_extent, then count shall be equal to extent.
-//
-
-#include <span>
-#include <cassert>
-#include <string>
-
-#include "test_macros.h"
-
-void checkCV()
-{
-                   int   arr[] = {1,2,3};
-    const          int  carr[] = {4,5,6};
-          volatile int  varr[] = {7,8,9};
-    const volatile int cvarr[] = {1,3,5};
-
-//  Types the same (dynamic sized)
-    {
-    std::span<               int> s1{  arr, 3}; // a span<               int> pointing at int.
-    std::span<const          int> s2{ carr, 3}; // a span<const          int> pointing at const int.
-    std::span<      volatile int> s3{ varr, 3}; // a span<      volatile int> pointing at volatile int.
-    std::span<const volatile int> s4{cvarr, 3}; // a span<const volatile int> pointing at const volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
-    }
-
-//  Types the same (static sized)
-    {
-    std::span<               int,3> s1{  arr, 3};   // a span<               int> pointing at int.
-    std::span<const          int,3> s2{ carr, 3};   // a span<const          int> pointing at const int.
-    std::span<      volatile int,3> s3{ varr, 3};   // a span<      volatile int> pointing at volatile int.
-    std::span<const volatile int,3> s4{cvarr, 3};   // a span<const volatile int> pointing at const volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
-    }
-
-
-//  types 
diff erent (dynamic sized)
-    {
-    std::span<const          int> s1{ arr, 3};      // a span<const          int> pointing at int.
-    std::span<      volatile int> s2{ arr, 3};      // a span<      volatile int> pointing at int.
-    std::span<      volatile int> s3{ arr, 3};      // a span<      volatile int> pointing at const int.
-    std::span<const volatile int> s4{ arr, 3};      // a span<const volatile int> pointing at int.
-    std::span<const volatile int> s5{carr, 3};      // a span<const volatile int> pointing at const int.
-    std::span<const volatile int> s6{varr, 3};      // a span<const volatile int> pointing at volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
-    }
-
-//  types 
diff erent (static sized)
-    {
-    std::span<const          int,3> s1{ arr, 3};    // a span<const          int> pointing at int.
-    std::span<      volatile int,3> s2{ arr, 3};    // a span<      volatile int> pointing at int.
-    std::span<      volatile int,3> s3{ arr, 3};    // a span<      volatile int> pointing at const int.
-    std::span<const volatile int,3> s4{ arr, 3};    // a span<const volatile int> pointing at int.
-    std::span<const volatile int,3> s5{carr, 3};    // a span<const volatile int> pointing at const int.
-    std::span<const volatile int,3> s6{varr, 3};    // a span<const volatile int> pointing at volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
-    }
-}
-
-
-template <typename T>
-constexpr bool testConstexprSpan()
-{
-    constexpr T val[2] = {};
-    std::span<const T>   s1{val, 2};
-    std::span<const T,2> s2{val, 2};
-    return
-        s1.data() == &val[0] && s1.size() == 2
-    &&  s2.data() == &val[0] && s2.size() == 2;
-}
-
-
-template <typename T>
-void testRuntimeSpan()
-{
-    T val[2] = {};
-    std::span<T>   s1{val, 2};
-    std::span<T,2> s2{val, 2};
-    assert(s1.data() == &val[0] && s1.size() == 2);
-    assert(s2.data() == &val[0] && s2.size() == 2);
-}
-
-struct A{};
-
-int main(int, char**)
-{
-    static_assert(testConstexprSpan<int>(),    "");
-    static_assert(testConstexprSpan<long>(),   "");
-    static_assert(testConstexprSpan<double>(), "");
-    static_assert(testConstexprSpan<A>(),      "");
-
-    testRuntimeSpan<int>();
-    testRuntimeSpan<long>();
-    testRuntimeSpan<double>();
-    testRuntimeSpan<std::string>();
-    testRuntimeSpan<A>();
-
-    checkCV();
-
-  return 0;
-}

diff  --git a/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp b/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp
deleted file mode 100644
index 923f13c59881f..0000000000000
--- a/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// <span>
-
-// constexpr span(pointer first, pointer last);
-// Requires: [first, last) shall be a valid range.
-//   If extent is not equal to dynamic_extent, then last - first shall be equal to extent.
-//
-
-#include <span>
-#include <cassert>
-#include <string>
-
-#include "test_macros.h"
-
-
-               int   arr[] = {1,2,3};
-const          int  carr[] = {4,5,6};
-      volatile int  varr[] = {7,8,9};
-const volatile int cvarr[] = {1,3,5};
-
-template<class T, size_t extent>
-std::span<T, extent> createImplicitSpan(T* first, T* last) {
-    return {first, last}; // expected-error {{chosen constructor is explicit in copy-initialization}}
-}
-
-int main(int, char**)
-{
-//  We can't check that the size doesn't match - because that's a runtime property
-//  std::span<int, 2>   s1(arr, arr + 3);
-
-//  Type wrong
-    {
-    std::span<float>    s1(arr, arr + 3);   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
-    std::span<float, 3> s2(arr, arr + 3);   // expected-error {{no matching constructor for initialization of 'std::span<float, 3>'}}
-    }
-
-//  CV wrong (dynamically sized)
-    {
-    std::span<               int> s1{ carr,  carr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s2{ varr,  varr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s3{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<const          int> s4{ varr,  varr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const          int> s5{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<      volatile int> s6{ carr,  carr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    std::span<      volatile int> s7{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    }
-
-//  CV wrong (statically sized)
-    {
-    std::span<               int,3> s1{ carr,  carr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<               int,3> s2{ varr,  varr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<               int,3> s3{cvarr, cvarr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<const          int,3> s4{ varr,  varr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
-    std::span<const          int,3> s5{cvarr, cvarr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
-    std::span<      volatile int,3> s6{ carr,  carr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
-    std::span<      volatile int,3> s7{cvarr, cvarr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
-    }
-
-    // explicit constructor necessary
-    {
-    createImplicitSpan<int, 1>(arr, arr + 1);
-    }
-
-  return 0;
-}

diff  --git a/libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp b/libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp
deleted file mode 100644
index 070c233ce94bd..0000000000000
--- a/libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// <span>
-
-// constexpr span(pointer first, pointer last);
-// Requires: [first, last) shall be a valid range.
-//   If extent is not equal to dynamic_extent, then last - first shall be equal to extent.
-//
-
-#include <span>
-#include <cassert>
-#include <string>
-
-#include "test_macros.h"
-
-void checkCV()
-{
-                   int   arr[] = {1,2,3};
-    const          int  carr[] = {4,5,6};
-          volatile int  varr[] = {7,8,9};
-    const volatile int cvarr[] = {1,3,5};
-
-//  Types the same (dynamic sized)
-    {
-    std::span<               int> s1{  arr,   arr + 3}; // a span<               int> pointing at int.
-    std::span<const          int> s2{ carr,  carr + 3}; // a span<const          int> pointing at const int.
-    std::span<      volatile int> s3{ varr,  varr + 3}; // a span<      volatile int> pointing at volatile int.
-    std::span<const volatile int> s4{cvarr, cvarr + 3}; // a span<const volatile int> pointing at const volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
-    }
-
-//  Types the same (static sized)
-    {
-    std::span<               int,3> s1{  arr,   arr + 3};   // a span<               int> pointing at int.
-    std::span<const          int,3> s2{ carr,  carr + 3};   // a span<const          int> pointing at const int.
-    std::span<      volatile int,3> s3{ varr,  varr + 3};   // a span<      volatile int> pointing at volatile int.
-    std::span<const volatile int,3> s4{cvarr, cvarr + 3};   // a span<const volatile int> pointing at const volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
-    }
-
-
-//  types 
diff erent (dynamic sized)
-    {
-    std::span<const          int> s1{ arr,  arr + 3};       // a span<const          int> pointing at int.
-    std::span<      volatile int> s2{ arr,  arr + 3};       // a span<      volatile int> pointing at int.
-    std::span<      volatile int> s3{ arr,  arr + 3};       // a span<      volatile int> pointing at const int.
-    std::span<const volatile int> s4{ arr,  arr + 3};       // a span<const volatile int> pointing at int.
-    std::span<const volatile int> s5{carr, carr + 3};       // a span<const volatile int> pointing at const int.
-    std::span<const volatile int> s6{varr, varr + 3};       // a span<const volatile int> pointing at volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
-    }
-
-//  types 
diff erent (static sized)
-    {
-    std::span<const          int,3> s1{ arr,  arr + 3}; // a span<const          int> pointing at int.
-    std::span<      volatile int,3> s2{ arr,  arr + 3}; // a span<      volatile int> pointing at int.
-    std::span<      volatile int,3> s3{ arr,  arr + 3}; // a span<      volatile int> pointing at const int.
-    std::span<const volatile int,3> s4{ arr,  arr + 3}; // a span<const volatile int> pointing at int.
-    std::span<const volatile int,3> s5{carr, carr + 3}; // a span<const volatile int> pointing at const int.
-    std::span<const volatile int,3> s6{varr, varr + 3}; // a span<const volatile int> pointing at volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
-    }
-}
-
-
-template <typename T>
-constexpr bool testConstexprSpan()
-{
-    constexpr T val[2] = {};
-    std::span<const T>   s1{val, val+2};
-    std::span<const T,2> s2{val, val+2};
-    return
-        s1.data() == &val[0] && s1.size() == 2
-    &&  s2.data() == &val[0] && s2.size() == 2;
-}
-
-
-template <typename T>
-void testRuntimeSpan()
-{
-    T val[2] = {};
-    std::span<T>   s1{val, val+2};
-    std::span<T,2> s2{val, val+2};
-    assert(s1.data() == &val[0] && s1.size() == 2);
-    assert(s2.data() == &val[0] && s2.size() == 2);
-}
-
-struct A{};
-
-int main(int, char**)
-{
-    static_assert(testConstexprSpan<int>(),    "");
-    static_assert(testConstexprSpan<long>(),   "");
-    static_assert(testConstexprSpan<double>(), "");
-    static_assert(testConstexprSpan<A>(),      "");
-
-    testRuntimeSpan<int>();
-    testRuntimeSpan<long>();
-    testRuntimeSpan<double>();
-    testRuntimeSpan<std::string>();
-    testRuntimeSpan<A>();
-
-    checkCV();
-
-  return 0;
-}

diff  --git a/libcxx/test/std/containers/views/span.cons/range.pass.cpp b/libcxx/test/std/containers/views/span.cons/range.pass.cpp
new file mode 100644
index 0000000000000..f5c67acff0bac
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/range.pass.cpp
@@ -0,0 +1,86 @@
+//===---------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
+
+// <span>
+
+//  template<class R>
+//    constexpr explicit(Extent != dynamic_extent) span(R&& r);
+
+
+#include <span>
+#include <cassert>
+#include <ranges>
+#include <string_view>
+#include <type_traits>
+#include <vector>
+
+#include "test_iterators.h"
+
+template <class T, size_t Extent>
+constexpr void test_from_range() {
+  T val[3]{};
+  std::span<T, Extent> s{val};
+  assert(s.size() == std::size(val));
+  assert(s.data() == std::data(val));
+}
+
+struct A {};
+
+constexpr bool test() {
+  test_from_range<int, std::dynamic_extent>();
+  test_from_range<int, 3>();
+  test_from_range<A, std::dynamic_extent>();
+  test_from_range<A, 3>();
+  return true;
+}
+
+static_assert(!std::is_constructible_v<std::span<int>, std::vector<float>&>);    // wrong type
+static_assert(!std::is_constructible_v<std::span<int, 3>, std::vector<float>&>); // wrong type
+
+static_assert(std::is_constructible_v<std::span<int>, std::vector<int>&>);                // non-borrowed lvalue
+static_assert(std::is_constructible_v<std::span<int, 3>, std::vector<int>&>);             // non-borrowed lvalue
+static_assert(std::is_constructible_v<std::span<const int>, std::vector<int>&>);          // non-borrowed lvalue
+static_assert(std::is_constructible_v<std::span<const int, 3>, std::vector<int>&>);       // non-borrowed lvalue
+static_assert(!std::is_constructible_v<std::span<int>, const std::vector<int>&>);         // non-borrowed const lvalue
+static_assert(!std::is_constructible_v<std::span<int, 3>, const std::vector<int>&>);      // non-borrowed const lvalue
+static_assert(std::is_constructible_v<std::span<const int>, const std::vector<int>&>);    // non-borrowed const lvalue
+static_assert(std::is_constructible_v<std::span<const int, 3>, const std::vector<int>&>); // non-borrowed const lvalue
+static_assert(std::is_constructible_v<std::span<const int>, std::vector<int>>);           // non-borrowed rvalue
+static_assert(std::is_constructible_v<std::span<const int, 3>, std::vector<int>>);        // non-borrowed rvalue
+static_assert(!std::is_constructible_v<std::span<int>, std::vector<int>&&>);              // non-borrowed rvalue
+static_assert(!std::is_constructible_v<std::span<int, 3>, std::vector<int>&&>);           // non-borrowed rvalue
+
+static_assert(std::is_constructible_v<std::span<int>, std::ranges::subrange<contiguous_iterator<int*>>>);         // contiguous borrowed rvalue
+static_assert(std::is_constructible_v<std::span<int, 3>, std::ranges::subrange<contiguous_iterator<int*>>>);      // contiguous borrowed rvalue
+static_assert(!std::is_constructible_v<std::span<int>, std::ranges::subrange<random_access_iterator<int*>>>);     // non-contiguous borrowed rvalue
+static_assert(!std::is_constructible_v<std::span<int, 3>, std::ranges::subrange<random_access_iterator<int*>>>);  // non-contiguous borrowed rvalue
+
+using BorrowedContiguousSizedRange = std::string_view;
+static_assert(std::is_constructible_v<std::span<const char>, BorrowedContiguousSizedRange>);
+static_assert(std::is_constructible_v<std::span<const char, 3>, BorrowedContiguousSizedRange>);
+static_assert(!std::is_constructible_v<std::span<char>, BorrowedContiguousSizedRange>);
+static_assert(!std::is_constructible_v<std::span<char, 3>, BorrowedContiguousSizedRange>);
+
+static_assert(std::is_convertible_v<BorrowedContiguousSizedRange&, std::span<const char>>);
+static_assert(!std::is_convertible_v<BorrowedContiguousSizedRange&, std::span<const char, 3>>);
+static_assert(!std::is_convertible_v<BorrowedContiguousSizedRange&, std::span<char>>);
+static_assert(!std::is_convertible_v<BorrowedContiguousSizedRange&, std::span<char, 3>>);
+static_assert(std::is_convertible_v<const BorrowedContiguousSizedRange&, std::span<const char>>);
+static_assert(!std::is_convertible_v<const BorrowedContiguousSizedRange&, std::span<const char, 3>>);
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/containers/views/span.elem/back.pass.cpp b/libcxx/test/std/containers/views/span.elem/back.pass.cpp
index dfc01d509210d..9d4fbc9fdd8e4 100644
--- a/libcxx/test/std/containers/views/span.elem/back.pass.cpp
+++ b/libcxx/test/std/containers/views/span.elem/back.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.elem/data.pass.cpp b/libcxx/test/std/containers/views/span.elem/data.pass.cpp
index 1bf63f95de987..8c5422421823f 100644
--- a/libcxx/test/std/containers/views/span.elem/data.pass.cpp
+++ b/libcxx/test/std/containers/views/span.elem/data.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.elem/front.pass.cpp b/libcxx/test/std/containers/views/span.elem/front.pass.cpp
index e1c9a0c984a23..d4e89f133c36a 100644
--- a/libcxx/test/std/containers/views/span.elem/front.pass.cpp
+++ b/libcxx/test/std/containers/views/span.elem/front.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.elem/op_idx.pass.cpp b/libcxx/test/std/containers/views/span.elem/op_idx.pass.cpp
index f6b7fbc0b9f17..2c1218cb9ace0 100644
--- a/libcxx/test/std/containers/views/span.elem/op_idx.pass.cpp
+++ b/libcxx/test/std/containers/views/span.elem/op_idx.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.iterators/begin.pass.cpp b/libcxx/test/std/containers/views/span.iterators/begin.pass.cpp
index f6b24017ffc1f..0e6f236c5edd4 100644
--- a/libcxx/test/std/containers/views/span.iterators/begin.pass.cpp
+++ b/libcxx/test/std/containers/views/span.iterators/begin.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.iterators/end.pass.cpp b/libcxx/test/std/containers/views/span.iterators/end.pass.cpp
index d531537bb195d..bb71bdd717037 100644
--- a/libcxx/test/std/containers/views/span.iterators/end.pass.cpp
+++ b/libcxx/test/std/containers/views/span.iterators/end.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp b/libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp
index 26e4389840857..bd1c3088e659c 100644
--- a/libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp
+++ b/libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.iterators/rend.pass.cpp b/libcxx/test/std/containers/views/span.iterators/rend.pass.cpp
index c2bd13aaf612b..6b57974e2a003 100644
--- a/libcxx/test/std/containers/views/span.iterators/rend.pass.cpp
+++ b/libcxx/test/std/containers/views/span.iterators/rend.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.objectrep/as_bytes.pass.cpp b/libcxx/test/std/containers/views/span.objectrep/as_bytes.pass.cpp
index 1f58d0f969f70..d2c44f3ddb00c 100644
--- a/libcxx/test/std/containers/views/span.objectrep/as_bytes.pass.cpp
+++ b/libcxx/test/std/containers/views/span.objectrep/as_bytes.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.fail.cpp b/libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.fail.cpp
index e7c4d356d6c6e..9dcebf4018efe 100644
--- a/libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.fail.cpp
+++ b/libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.fail.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.pass.cpp b/libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.pass.cpp
index 6b7bd5dcf0c1e..7f47ffd71fbe6 100644
--- a/libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.pass.cpp
+++ b/libcxx/test/std/containers/views/span.objectrep/as_writable_bytes.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.obs/empty.pass.cpp b/libcxx/test/std/containers/views/span.obs/empty.pass.cpp
index f841dc2f9f5f8..a03db77603667 100644
--- a/libcxx/test/std/containers/views/span.obs/empty.pass.cpp
+++ b/libcxx/test/std/containers/views/span.obs/empty.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.obs/size.pass.cpp b/libcxx/test/std/containers/views/span.obs/size.pass.cpp
index 5be7b9850670d..ffb28e6f76b4e 100644
--- a/libcxx/test/std/containers/views/span.obs/size.pass.cpp
+++ b/libcxx/test/std/containers/views/span.obs/size.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.obs/size_bytes.pass.cpp b/libcxx/test/std/containers/views/span.obs/size_bytes.pass.cpp
index 9ce6d2679cc52..4f5402188af9e 100644
--- a/libcxx/test/std/containers/views/span.obs/size_bytes.pass.cpp
+++ b/libcxx/test/std/containers/views/span.obs/size_bytes.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.sub/first.fail.cpp b/libcxx/test/std/containers/views/span.sub/first.fail.cpp
index 176311f36dd7d..b7c8d0643b433 100644
--- a/libcxx/test/std/containers/views/span.sub/first.fail.cpp
+++ b/libcxx/test/std/containers/views/span.sub/first.fail.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.sub/first.pass.cpp b/libcxx/test/std/containers/views/span.sub/first.pass.cpp
index 2b04cb0f71595..43134723210ac 100644
--- a/libcxx/test/std/containers/views/span.sub/first.pass.cpp
+++ b/libcxx/test/std/containers/views/span.sub/first.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.sub/last.fail.cpp b/libcxx/test/std/containers/views/span.sub/last.fail.cpp
index 9cff076dd77e1..44c61f8cc5e46 100644
--- a/libcxx/test/std/containers/views/span.sub/last.fail.cpp
+++ b/libcxx/test/std/containers/views/span.sub/last.fail.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.sub/last.pass.cpp b/libcxx/test/std/containers/views/span.sub/last.pass.cpp
index 6fa6edfc7e593..dd599a44e3136 100644
--- a/libcxx/test/std/containers/views/span.sub/last.pass.cpp
+++ b/libcxx/test/std/containers/views/span.sub/last.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.sub/subspan.fail.cpp b/libcxx/test/std/containers/views/span.sub/subspan.fail.cpp
index 33eeda0a08eaf..96595ef581812 100644
--- a/libcxx/test/std/containers/views/span.sub/subspan.fail.cpp
+++ b/libcxx/test/std/containers/views/span.sub/subspan.fail.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 

diff  --git a/libcxx/test/std/containers/views/span.sub/subspan.pass.cpp b/libcxx/test/std/containers/views/span.sub/subspan.pass.cpp
index f426ab633861c..c88022b1ee858 100644
--- a/libcxx/test/std/containers/views/span.sub/subspan.pass.cpp
+++ b/libcxx/test/std/containers/views/span.sub/subspan.pass.cpp
@@ -6,6 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// AppleClang 12.0.0 doesn't fully support ranges/concepts
+// XFAIL: apple-clang-12.0.0
 
 // <span>
 


        


More information about the libcxx-commits mailing list