[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