Implement <span>. Reviewed as https://reviews.llvm.org/D49338
authorMarshall Clow <mclow.lists@gmail.com>
Tue, 24 Jul 2018 03:01:02 +0000 (03:01 +0000)
committerMarshall Clow <mclow.lists@gmail.com>
Tue, 24 Jul 2018 03:01:02 +0000 (03:01 +0000)
llvm-svn: 337804

42 files changed:
libcxx/include/CMakeLists.txt
libcxx/include/module.modulemap
libcxx/include/span [new file with mode: 0644]
libcxx/test/libcxx/double_include.sh.cpp
libcxx/test/std/containers/views/span.comparison/op.eq.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.comparison/op.ge.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.comparison/op.gt.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.comparison/op.le.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.comparison/op.lt.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.comparison/op.ne.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/array.fail.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/array.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/assign.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/container.fail.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/container.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/copy.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/deduct.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/default.fail.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/default.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/span.fail.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/span.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.cons/stdarray.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.elem/data.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.elem/op_idx.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.iterators/begin.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.iterators/end.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.iterators/rend.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.objectrep/as_bytes.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.obs/empty.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.obs/size.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.obs/size_bytes.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.sub/first.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.sub/last.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/span.sub/subspan.pass.cpp [new file with mode: 0644]
libcxx/test/std/containers/views/types.pass.cpp [new file with mode: 0644]

index e44ff3e..c60e61e 100644 (file)
@@ -128,6 +128,7 @@ set(files
   set
   setjmp.h
   shared_mutex
+  span
   sstream
   stack
   stdbool.h
index 70f82a7..e17c3a2 100644 (file)
@@ -559,6 +559,10 @@ module std [system] {
       header "experimental/set"
       export *
     }
+    module span {
+      header "span"
+      export *
+    }
     module string {
       header "experimental/string"
       export *
diff --git a/libcxx/include/span b/libcxx/include/span
new file mode 100644 (file)
index 0000000..b1a13dd
--- /dev/null
@@ -0,0 +1,606 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_SPAN
+#define _LIBCPP_SPAN
+
+/*
+    span synopsis
+
+namespace std {
+
+// constants
+inline constexpr ptrdiff_t dynamic_extent = -1;
+
+// [views.span], class template span
+template <class ElementType, ptrdiff_t Extent = dynamic_extent>
+    class span;
+
+// [span.comparison], span comparison operators
+template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
+    constexpr bool operator==(span<T, X> l, span<U, Y> r);
+template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
+    constexpr bool operator!=(span<T, X> l, span<U, Y> r);
+template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
+    constexpr bool operator<(span<T, X> l, span<U, Y> r);
+template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
+    constexpr bool operator<=(span<T, X> l, span<U, Y> r);
+template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
+    constexpr bool operator>(span<T, X> l, span<U, Y> r);
+template <class T, ptrdiff_t X, class U, ptrdiff_t Y>
+    constexpr bool operator>=(span<T, X> l, span<U, Y> r);
+
+// [span.objectrep], views of object representation
+template <class ElementType, ptrdiff_t Extent>
+    span<const byte, ((Extent == dynamic_extent) ? dynamic_extent : 
+        (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept;
+
+template <class ElementType, ptrdiff_t Extent>
+    span<      byte, ((Extent == dynamic_extent) ? dynamic_extent : 
+        (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept;
+
+
+namespace std {
+template <class ElementType, ptrdiff_t Extent = dynamic_extent>
+class span {
+public:
+    // constants and types
+    using element_type = ElementType;
+    using value_type = remove_cv_t<ElementType>;
+    using index_type = ptrdiff_t;
+    using difference_type = ptrdiff_t;
+    using pointer = element_type*;
+    using reference = element_type&;
+    using iterator = implementation-defined;
+    using const_iterator = implementation-defined;
+    using reverse_iterator = std::reverse_iterator<iterator>;
+    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+    static constexpr index_type extent = Extent;
+
+    // [span.cons], span constructors, copy, assignment, and destructor
+    constexpr span() noexcept;
+    constexpr span(pointer ptr, index_type count);
+    constexpr span(pointer firstElem, pointer lastElem);
+    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 span(Container& cont);
+    template <class Container>
+        constexpr span(const Container& cont);
+    constexpr span(const span& other) noexcept = default;
+    template <class OtherElementType, ptrdiff_t OtherExtent>
+        constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept;
+    ~span() noexcept = default;
+    constexpr span& operator=(const span& other) noexcept = default;
+
+    // [span.sub], span subviews
+    template <ptrdiff_t Count>
+        constexpr span<element_type, Count> first() const;
+    template <ptrdiff_t Count>
+        constexpr span<element_type, Count> last() const;
+    template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
+        constexpr span<element_type, see below> subspan() const;
+
+    constexpr span<element_type, dynamic_extent> first(index_type count) const;
+    constexpr span<element_type, dynamic_extent> last(index_type count) const;
+    constexpr span<element_type, dynamic_extent> subspan(index_type offset, index_type count = dynamic_extent) const;
+
+    // [span.obs], span observers
+    constexpr index_type size() const noexcept;
+    constexpr index_type size_bytes() const noexcept;
+    constexpr bool empty() const noexcept;
+
+    // [span.elem], span element access
+    constexpr reference operator[](index_type idx) const;
+    constexpr reference operator()(index_type idx) const;
+    constexpr pointer data() const noexcept;
+
+    // [span.iterators], span iterator support
+    constexpr iterator begin() const noexcept;
+    constexpr iterator end() const noexcept;
+    constexpr const_iterator cbegin() const noexcept;
+    constexpr const_iterator cend() const noexcept;
+    constexpr reverse_iterator rbegin() const noexcept;
+    constexpr reverse_iterator rend() const noexcept;
+    constexpr const_reverse_iterator crbegin() const noexcept;
+    constexpr const_reverse_iterator crend() const noexcept;
+
+private:
+    pointer data_;     // exposition only
+    index_type size_;  // exposition only
+};
+
+template<class T, size_t N>
+    span(T (&)[N]) -> span<T, N>;
+  
+template<class T, size_t N>
+    span(array<T, N>&) -> span<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>;
+
+} // namespace std
+
+*/
+
+#include <cstddef>      // for ptrdiff_t
+#include <iterator>     // for iterators
+#include <array>        // for array
+#include <type_traits>  // for remove_cv, etc
+#include <cstddef>      // for byte
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 17
+
+inline constexpr ptrdiff_t dynamic_extent = -1;
+template <typename _Tp, ptrdiff_t _Extent = dynamic_extent> class span;
+
+
+template <class _Tp>
+struct __is_span_impl : public false_type {};
+
+template <class _Tp, ptrdiff_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>
+struct __is_std_array_impl : public 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
+            typename enable_if<!__is_span<_Tp>::value, nullptr_t>::type,
+        // is not a specialization of array
+            typename enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type,
+        // is_array_v<Container> is false,
+            typename enable_if<!is_array_v<_Tp>, nullptr_t>::type,
+        // 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(*)[]
+            typename enable_if<
+                               is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[],
+                                                _ElementType(*)[]>,
+                nullptr_t>::type
+        >>
+    : public true_type {};
+
+
+template <typename _Tp, ptrdiff_t _Extent>
+class _LIBCPP_TEMPLATE_VIS span {
+public:
+//  constants and types
+    using element_type           = _Tp;
+    using value_type             = remove_cv_t<_Tp>;
+    using index_type             = ptrdiff_t;
+    using difference_type        = ptrdiff_t;
+    using pointer                = _Tp *;
+    using const_pointer          = const _Tp *; // not in standard
+    using reference              = _Tp &;
+    using const_reference        = const _Tp &; // not in standard
+    using iterator               =  __wrap_iter<pointer>;
+    using const_iterator         =  __wrap_iter<const_pointer>;
+    using reverse_iterator       = _VSTD::reverse_iterator<iterator>;
+    using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>;
+
+    static constexpr index_type extent = _Extent;
+    static_assert (_Extent >= 0, "Can't have a span with an extent < 0");
+
+// [span.cons], span constructors, copy, assignment, and destructor 
+    _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}
+    { static_assert(_Extent == 0, "Can't default construct a statically sized span with size > 0"); }
+
+    constexpr span           (const span&) noexcept = default;
+    constexpr span& operator=(const span&) noexcept = default;
+
+    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}
+        { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); }
+    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}
+        { (void)__l;     _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent])          noexcept : __data{__arr} {}
+    _LIBCPP_INLINE_VISIBILITY constexpr span(      array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
+    _LIBCPP_INLINE_VISIBILITY constexpr span(const array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
+
+    template <class _Container>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr 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 (container))"); }
+
+    template <class _Container>
+    inline _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)}
+        { _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (const container)"); }
+
+    template <class _OtherElementType>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span(const span<_OtherElementType, _Extent>& __other,
+                       enable_if_t<
+                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
+                          nullptr_t> = nullptr)
+        : __data{__other.data()} {}
+
+    template <class _OtherElementType>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span(const span<_OtherElementType, dynamic_extent>& __other,
+                       enable_if_t<
+                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
+                          nullptr_t> = nullptr) noexcept
+        : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); }
+
+
+//  ~span() noexcept = default;
+
+    template <ptrdiff_t _Count>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span<element_type, _Count> first() const noexcept
+    {
+        static_assert(_Count >= 0, "Count must be >= 0 in span::first()");
+        static_assert(_Count <= _Extent, "Count out of range in span::first()");
+        return {data(), _Count};
+    }
+
+    template <ptrdiff_t _Count>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span<element_type, _Count> last() const noexcept
+    {
+        static_assert(_Count >= 0, "Count must be >= 0 in span::last()");
+        static_assert(_Count <= _Extent, "Count out of range in span::last()");
+        return {data() + size() - _Count, _Count};
+    }
+    
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept
+    {
+        _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)");
+        return {data(), __count};
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr span<element_type, dynamic_extent> last(index_type __count) const noexcept
+    {
+        _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)");
+        return {data() + size() - __count, __count};
+    }
+
+    template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr auto subspan() const noexcept
+        -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>
+    {
+        _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()");
+        return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
+    }
+
+
+    inline _LIBCPP_INLINE_VISIBILITY
+    constexpr span<element_type, dynamic_extent>
+       subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept
+    { 
+        _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)");
+        _LIBCPP_ASSERT((__count  >= 0 && __count  <= size()) || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)");
+        if (__count == dynamic_extent)
+            return {data() + __offset, size() - __offset};
+        _LIBCPP_ASSERT(__offset + __count <= size(), "count + offset out of range in span::subspan(offset, count)");
+        return {data() + __offset, __count};
+    }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr index_type size()       const noexcept { return _Extent; }
+    _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return _Extent * sizeof(element_type); }
+    _LIBCPP_INLINE_VISIBILITY constexpr bool empty()            const noexcept { return _Extent == 0; }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept
+    {
+        _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>[] index out of bounds");
+               return __data[__idx];
+       }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept
+    {
+        _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>() index out of bounds");
+               return __data[__idx];
+       }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr pointer data()                         const noexcept { return __data; }
+
+// [span.iter], span iterator support
+    _LIBCPP_INLINE_VISIBILITY constexpr iterator                 begin() const noexcept { return iterator(data()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr iterator                   end() const noexcept { return iterator(data() + size()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr const_iterator          cbegin() const noexcept { return const_iterator(data()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr const_iterator            cend() const noexcept { return const_iterator(data() + size()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator        rbegin() const noexcept { return reverse_iterator(end()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator          rend() const noexcept { return reverse_iterator(begin()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator   crend() const noexcept { return const_reverse_iterator(cbegin()); }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept
+    {
+        pointer __p = __data;
+        __data = __other.__data;
+        __other.__data = __p;
+    }
+    
+    _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept
+    { return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
+
+    _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writeable_bytes() const noexcept
+    { return {reinterpret_cast<byte *>(data()), size_bytes()}; }
+
+private:
+    pointer    __data;
+
+};
+
+
+template <typename _Tp>
+class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> {
+private:
+
+public:
+//  constants and types
+    using element_type           = _Tp;
+    using value_type             = remove_cv_t<_Tp>;
+    using index_type             = ptrdiff_t;
+    using difference_type        = ptrdiff_t;
+    using pointer                = _Tp *;
+    using const_pointer          = const _Tp *; // not in standard
+    using reference              = _Tp &;
+    using const_reference        = const _Tp &; // not in standard
+    using iterator               =  __wrap_iter<pointer>;
+    using const_iterator         =  __wrap_iter<const_pointer>;
+    using reverse_iterator       = _VSTD::reverse_iterator<iterator>;
+    using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>;
+
+    static constexpr index_type extent = dynamic_extent;
+
+// [span.cons], span constructors, copy, assignment, and destructor 
+    _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {}
+
+    constexpr span           (const span&) noexcept = default;
+    constexpr span& operator=(const span&) noexcept = default;
+
+    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}, __size{__count} {}
+    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{distance(__f, __l)} {}
+
+    template <size_t _Sz>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span(element_type (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {}
+
+    template <size_t _Sz>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span(array<value_type, _Sz>& __arr)       noexcept : __data{__arr.data()}, __size{_Sz} {}
+    
+    template <size_t _Sz>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span(const array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
+
+    template <class _Container>
+    inline _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{(index_type) _VSTD::size(__c)} {}
+
+    template <class _Container>
+    inline _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{(index_type) _VSTD::size(__c)} {}
+
+
+    template <class _OtherElementType, ptrdiff_t _OtherExtent>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span(const span<_OtherElementType, _OtherExtent>& __other,
+                       enable_if_t<
+                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
+                          nullptr_t> = nullptr) noexcept
+        : __data{__other.data()}, __size{__other.size()} {}
+
+//    ~span() noexcept = default;
+
+    template <ptrdiff_t _Count>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span<element_type, _Count> first() const noexcept
+    {
+        static_assert(_Count >= 0);
+        _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()");
+        return {data(), _Count};
+    }
+
+    template <ptrdiff_t _Count>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span<element_type, _Count> last() const noexcept
+    {
+        static_assert(_Count >= 0);
+        _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()");
+        return {data() + size() - _Count, _Count};
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept
+    {
+        _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)");
+        return {data(), __count};
+    }
+        
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr span<element_type, dynamic_extent> last (index_type __count) const noexcept
+    {
+        _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)");
+        return {data() + size() - __count, __count};
+    }
+
+    template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent>
+    inline _LIBCPP_INLINE_VISIBILITY
+        constexpr span<_Tp, dynamic_extent> subspan() const noexcept
+    {
+        _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()");
+        _LIBCPP_ASSERT(_Count == dynamic_extent || _Offset + _Count <= size(), "Count out of range in span::subspan()");
+        return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
+    }
+
+    constexpr span<element_type, dynamic_extent>
+    inline _LIBCPP_INLINE_VISIBILITY
+       subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept
+    { 
+        _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)");
+        _LIBCPP_ASSERT((__count  >= 0 && __count  <= size()) || __count == dynamic_extent, "count out of range in span::subspan(offset, count)");
+        if (__count == dynamic_extent)
+            return {data() + __offset, size() - __offset};
+        _LIBCPP_ASSERT(__offset + __count <= size(), "Offset + count out of range in span::subspan(offset, count)");
+        return {data() + __offset, __count};
+    }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr index_type size()       const noexcept { return __size; }
+    _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return __size * sizeof(element_type); }
+    _LIBCPP_INLINE_VISIBILITY constexpr bool empty()            const noexcept { return __size == 0; }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept
+    {
+        _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>[] index out of bounds");
+               return __data[__idx];
+       }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept
+    {
+        _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>() index out of bounds");
+               return __data[__idx];
+       }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr pointer data()                         const noexcept { return __data; }
+
+// [span.iter], span iterator support
+    _LIBCPP_INLINE_VISIBILITY constexpr iterator                 begin() const noexcept { return iterator(data()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr iterator                   end() const noexcept { return iterator(data() + size()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr const_iterator          cbegin() const noexcept { return const_iterator(data()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr const_iterator            cend() const noexcept { return const_iterator(data() + size()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator        rbegin() const noexcept { return reverse_iterator(end()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator          rend() const noexcept { return reverse_iterator(begin()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
+    _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator   crend() const noexcept { return const_reverse_iterator(cbegin()); }
+
+    _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept
+    {
+        pointer __p = __data;
+        __data = __other.__data;
+        __other.__data = __p;
+
+        index_type __sz = __size;
+        __size = __other.__size;
+        __other.__size = __sz;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept
+    { return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
+
+    _LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writeable_bytes() const noexcept
+    { return {reinterpret_cast<byte *>(data()), size_bytes()}; }
+
+private:
+    pointer    __data;
+    index_type __size;
+};
+
+template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
+    constexpr bool
+    operator==(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
+    { return equal(__lhs.begin(), __lhs.end(), __rhs.begin(), __rhs.end()); }
+
+template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
+    constexpr bool
+    operator!=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
+    { return !(__rhs == __lhs); }
+
+template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
+    constexpr bool
+    operator< (const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
+    { return lexicographical_compare (__lhs.begin(), __lhs.end(), __rhs.begin(), __rhs.end()); }
+    
+template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
+    constexpr bool
+    operator<=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
+    { return !(__rhs < __lhs); }
+
+template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
+    constexpr bool
+    operator> (const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
+    { return __rhs < __lhs; }
+    
+template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2>
+    constexpr bool
+    operator>=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs)
+    { return !(__lhs < __rhs); }
+
+//  as_bytes & as_writeable_bytes
+template <class _Tp, ptrdiff_t _Extent>
+    auto as_bytes(span<_Tp, _Extent> __s) noexcept 
+    -> decltype(__s.__as_bytes())
+    { return __s.__as_bytes(); }
+
+template <class _Tp, ptrdiff_t _Extent>
+    auto as_writeable_bytes(span<_Tp, _Extent> __s) noexcept
+    -> typename enable_if<!is_const_v<_Tp>, decltype(__s.__as_writeable_bytes())>::type
+    { return __s.__as_writeable_bytes(); }
+
+template <class _Tp, ptrdiff_t _Extent>
+    constexpr void swap(span<_Tp, _Extent> &__lhs, span<_Tp, _Extent> &__rhs) noexcept
+    { __lhs.swap(__rhs); }
+
+
+//  Deduction guides
+template<class _Tp, size_t _Sz>
+    span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
+  
+template<class _Tp, size_t _Sz>
+    span(array<_Tp, _Sz>&) -> span<_Tp, _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>;
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER > 17
+#endif // _LIBCPP_SPAN
index 0f2d1e0..dfc3d01 100644 (file)
 #ifndef _LIBCPP_HAS_NO_THREADS
 #include <shared_mutex>
 #endif
+#include <span>
 #include <sstream>
 #include <stack>
 #include <stdbool.h>
diff --git a/libcxx/test/std/containers/views/span.comparison/op.eq.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.eq.pass.cpp
new file mode 100644 (file)
index 0000000..9630545
--- /dev/null
@@ -0,0 +1,168 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<class T, ptrdiff_t X, class U, ptrdiff_t Y>
+//   constexpr bool operator==(span<T, X> l, span<U, Y> r);
+//   
+//
+// Effects: Equivalent to: return equal(l.begin(), l.end(), r.begin(), r.end());
+//
+
+#include <span>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr   int iArr1[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+            int iArr2[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+constexpr float fArr1[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+          float fArr2[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+         
+
+int main () {
+
+    constexpr std::span<const int>     csp0d{};
+    constexpr std::span<const int>     csp1d{iArr1, 10};
+    constexpr std::span<const int>     csp2d{iArr1 + 3, 2};
+    constexpr std::span<const int>     csp3d{iArr1 + 1, 2};
+    constexpr std::span<const int>     csp4d{iArr1 + 6, 2};
+
+    constexpr std::span<const int,  0> csp0s{};
+    constexpr std::span<const int, 10> csp1s{iArr1, 10};
+    constexpr std::span<const int, 2>  csp2s{iArr1 + 3, 2};
+    constexpr std::span<const int, 2>  csp3s{iArr1 + 1, 2};
+    constexpr std::span<const int, 2>  csp4s{iArr1 + 6, 2};
+
+    static_assert( (csp0d == csp0d), "");
+    static_assert( (csp0s == csp0s), "");
+    static_assert( (csp0s == csp0d), "");
+    static_assert( (csp0d == csp0s), "");
+    
+    static_assert(!(csp0d == csp1d), "");
+    static_assert(!(csp0s == csp1s), "");
+    static_assert(!(csp0s == csp1d), "");
+    static_assert(!(csp0d == csp1s), "");
+    
+    static_assert( (csp1d == csp1s), "");
+    static_assert( (csp1s == csp1d), "");
+    
+    static_assert( (csp2d == csp3d), "");
+    static_assert( (csp2s == csp3s), "");
+    static_assert( (csp2d == csp3s), "");
+    static_assert( (csp2s == csp3d), "");
+
+    static_assert( (csp2d == csp3d), "");
+    static_assert( (csp2s == csp3s), "");
+    static_assert( (csp2d == csp3s), "");
+    static_assert( (csp2s == csp3d), "");
+
+    static_assert(!(csp2d == csp4d), "");
+    static_assert(!(csp2s == csp4s), "");
+    static_assert(!(csp2d == csp4s), "");
+    static_assert(!(csp2s == csp4d), "");
+
+    static_assert(!(csp4d == csp2d), "");
+    static_assert(!(csp4s == csp2s), "");
+    static_assert(!(csp4d == csp2s), "");
+    static_assert(!(csp4s == csp2d), "");
+
+    std::span<int>     sp0d{};
+    std::span<int>     sp1d{iArr2, 10};
+    std::span<int>     sp2d{iArr2 + 3, 2};
+    std::span<int>     sp3d{iArr2 + 1, 2};
+    std::span<int>     sp4d{iArr2 + 6, 2};
+
+    std::span<int,  0> sp0s{};
+    std::span<int, 10> sp1s{iArr2, 10};
+    std::span<int, 2>  sp2s{iArr2 + 3, 2};
+    std::span<int, 2>  sp3s{iArr2 + 1, 2};
+    std::span<int, 2>  sp4s{iArr2 + 6, 2};
+
+    assert( (sp0d == sp0d));
+    assert( (sp0s == sp0s));
+    assert( (sp0s == sp0d));
+    assert( (sp0d == sp0s));
+    
+    assert(!(sp0d == sp1d));
+    assert(!(sp0s == sp1s));
+    assert(!(sp0s == sp1d));
+    assert(!(sp0d == sp1s));
+    
+    assert( (sp1d == sp1s));
+    assert( (sp1s == sp1d));
+    
+    assert( (sp2d == sp3d));
+    assert( (sp2s == sp3s));
+    assert( (sp2d == sp3s));
+    assert( (sp2s == sp3d));
+
+    assert( (sp2d == sp3d));
+    assert( (sp2s == sp3s));
+    assert( (sp2d == sp3s));
+    assert( (sp2s == sp3d));
+
+    assert(!(sp2d == sp4d));
+    assert(!(sp2s == sp4s));
+    assert(!(sp2d == sp4s));
+    assert(!(sp2s == sp4d));
+
+    assert(!(sp4d == sp2d));
+    assert(!(sp4s == sp2s));
+    assert(!(sp4d == sp2s));
+    assert(!(sp4s == sp2d));
+
+//  cross type comparisons
+    assert( (csp0d == sp0d));
+    assert( (csp0s == sp0s));
+    assert( (csp0s == sp0d));
+    assert( (csp0d == sp0s));
+    
+    assert(!(csp0d == sp1d));
+    assert(!(csp0s == sp1s));
+    assert(!(csp0s == sp1d));
+    assert(!(csp0d == sp1s));
+    
+    assert( (csp1d == sp1s));
+    assert( (csp1s == sp1d));
+    
+    assert( (csp2d == sp3d));
+    assert( (csp2s == sp3s));
+    assert( (csp2d == sp3s));
+    assert( (csp2s == sp3d));
+
+    assert( (csp2d == sp3d));
+    assert( (csp2s == sp3s));
+    assert( (csp2d == sp3s));
+    assert( (csp2s == sp3d));
+
+    assert(!(csp2d == sp4d));
+    assert(!(csp2s == sp4s));
+    assert(!(csp2d == sp4s));
+    assert(!(csp2s == sp4d));
+    
+    assert(!(csp4d == sp2d));
+    assert(!(csp4s == sp2s));
+    assert(!(csp4d == sp2s));
+    assert(!(csp4s == sp2d));
+
+//  More cross-type comparisons (int vs float)
+    static_assert(std::span<const float>{fArr1} == std::span<const   int>{iArr1}, "");
+    static_assert(std::span<const   int>{iArr1} == std::span<const float>{fArr1}, "");
+    assert(std::span<float>{fArr2} == std::span<int>{iArr2});
+    assert(std::span<int>{iArr2} == std::span<float>{fArr2});
+
+    static_assert(!(std::span<const   int>{iArr1, 9} == std::span<const float>{fArr1, 8}), "");
+}
\ No newline at end of file
diff --git a/libcxx/test/std/containers/views/span.comparison/op.ge.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.ge.pass.cpp
new file mode 100644 (file)
index 0000000..8ec1b9a
--- /dev/null
@@ -0,0 +1,153 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<class T, ptrdiff_t X, class U, ptrdiff_t Y>
+//   constexpr bool operator>=(span<T, X> l, span<U, Y> r);
+//   
+//
+// Effects: Equivalent to: return !(l < r);
+//
+
+#include <span>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr   int iArr1[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+            int iArr2[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+constexpr float fArr1[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+          float fArr2[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+         
+
+int main () {
+
+    constexpr std::span<const int>     csp0d{};
+    constexpr std::span<const int>     csp1d{iArr1, 10};
+    constexpr std::span<const int>     csp2d{iArr1 + 3, 2};
+    constexpr std::span<const int>     csp3d{iArr1 + 1, 2};
+    constexpr std::span<const int>     csp4d{iArr1 + 6, 2};
+
+    constexpr std::span<const int,  0> csp0s{};
+    constexpr std::span<const int, 10> csp1s{iArr1, 10};
+    constexpr std::span<const int, 2>  csp2s{iArr1 + 3, 2};
+    constexpr std::span<const int, 2>  csp3s{iArr1 + 1, 2};
+    constexpr std::span<const int, 2>  csp4s{iArr1 + 6, 2};
+
+    static_assert( (csp0d >= csp0d), "");
+    static_assert( (csp0s >= csp0s), "");
+    static_assert( (csp0s >= csp0d), "");
+    static_assert( (csp0d >= csp0s), "");
+    
+    static_assert(!(csp0d >= csp1d), "");
+    static_assert(!(csp0s >= csp1s), "");
+    static_assert(!(csp0s >= csp1d), "");
+    static_assert(!(csp0d >= csp1s), "");
+    
+    static_assert( (csp1d >= csp1s), "");
+    static_assert( (csp1s >= csp1d), "");
+    
+    static_assert( (csp2d >= csp3d), "");
+    static_assert( (csp2s >= csp3s), "");
+    static_assert( (csp2d >= csp3s), "");
+    static_assert( (csp2s >= csp3d), "");
+
+    static_assert(!(csp2d >= csp4d), "");
+    static_assert(!(csp2s >= csp4s), "");
+    static_assert(!(csp2d >= csp4s), "");
+    static_assert(!(csp2s >= csp4d), "");
+
+    static_assert( (csp4d >= csp2d), "");
+    static_assert( (csp4s >= csp2s), "");
+    static_assert( (csp4d >= csp2s), "");
+    static_assert( (csp4s >= csp2d), "");
+
+    std::span<int>     sp0d{};
+    std::span<int>     sp1d{iArr2, 10};
+    std::span<int>     sp2d{iArr2 + 3, 2};
+    std::span<int>     sp3d{iArr2 + 1, 2};
+    std::span<int>     sp4d{iArr2 + 6, 2};
+
+    std::span<int,  0> sp0s{};
+    std::span<int, 10> sp1s{iArr2, 10};
+    std::span<int, 2>  sp2s{iArr2 + 3, 2};
+    std::span<int, 2>  sp3s{iArr2 + 1, 2};
+    std::span<int, 2>  sp4s{iArr2 + 6, 2};
+
+    assert( (sp0d >= sp0d));
+    assert( (sp0s >= sp0s));
+    assert( (sp0s >= sp0d));
+    assert( (sp0d >= sp0s));
+    
+    assert(!(sp0d >= sp1d));
+    assert(!(sp0s >= sp1s));
+    assert(!(sp0s >= sp1d));
+    assert(!(sp0d >= sp1s));
+    
+    assert( (sp1d >= sp1s));
+    assert( (sp1s >= sp1d));
+    
+    assert( (sp2d >= sp3d));
+    assert( (sp2s >= sp3s));
+    assert( (sp2d >= sp3s));
+    assert( (sp2s >= sp3d));
+
+    assert(!(sp2d >= sp4d));
+    assert(!(sp2s >= sp4s));
+    assert(!(sp2d >= sp4s));
+    assert(!(sp2s >= sp4d));
+
+    assert( (sp4d > sp2d));
+    assert( (sp4s > sp2s));
+    assert( (sp4d > sp2s));
+    assert( (sp4s > sp2d));
+
+//  cross type comparisons
+    assert( (csp0d >= sp0d));
+    assert( (csp0s >= sp0s));
+    assert( (csp0s >= sp0d));
+    assert( (csp0d >= sp0s));
+    
+    assert(!(csp0d >= sp1d));
+    assert(!(csp0s >= sp1s));
+    assert(!(csp0s >= sp1d));
+    assert(!(csp0d >= sp1s));
+    
+    assert( (csp1d >= sp1s));
+    assert( (csp1s >= sp1d));
+    
+    assert( (csp2d >= sp3d));
+    assert( (csp2s >= sp3s));
+    assert( (csp2d >= sp3s));
+    assert( (csp2s >= sp3d));
+
+    assert(!(csp2d >= sp4d));
+    assert(!(csp2s >= sp4s));
+    assert(!(csp2d >= sp4s));
+    assert(!(csp2s >= sp4d));
+    
+    assert( (csp4d > sp2d));
+    assert( (csp4s > sp2s));
+    assert( (csp4d > sp2s));
+    assert( (csp4s > sp2d));
+
+//  More cross-type comparisons (int vs float)
+    static_assert(!(std::span<const float>{fArr1, 8} >= std::span<const   int>{iArr1, 9}), "");
+    static_assert(!(std::span<const   int>{iArr1, 8} >= std::span<const float>{fArr1, 9}), "");
+    assert( (std::span<float>{fArr2} >= std::span<int>{iArr2}));
+    assert( (std::span<int>{iArr2} >= std::span<float>{fArr2}));
+
+    static_assert( (std::span<const   int>{iArr1, 9} >= std::span<const float>{fArr1, 8}), "");
+}
diff --git a/libcxx/test/std/containers/views/span.comparison/op.gt.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.gt.pass.cpp
new file mode 100644 (file)
index 0000000..345a291
--- /dev/null
@@ -0,0 +1,154 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<class T, ptrdiff_t X, class U, ptrdiff_t Y>
+//   constexpr bool operator>(span<T, X> l, span<U, Y> r);
+//   
+//
+// Effects: Equivalent to: return (r < l);
+//
+
+#include <span>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr   int iArr1[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+            int iArr2[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+constexpr float fArr1[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+          float fArr2[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+         
+
+int main () {
+
+    constexpr std::span<const int>     csp0d{};
+    constexpr std::span<const int>     csp1d{iArr1, 10};
+    constexpr std::span<const int>     csp2d{iArr1 + 3, 2};
+    constexpr std::span<const int>     csp3d{iArr1 + 1, 2};
+    constexpr std::span<const int>     csp4d{iArr1 + 6, 2};
+
+    constexpr std::span<const int,  0> csp0s{};
+    constexpr std::span<const int, 10> csp1s{iArr1, 10};
+    constexpr std::span<const int, 2>  csp2s{iArr1 + 3, 2};
+    constexpr std::span<const int, 2>  csp3s{iArr1 + 1, 2};
+    constexpr std::span<const int, 2>  csp4s{iArr1 + 6, 2};
+
+    static_assert(!(csp0d > csp0d), "");
+    static_assert(!(csp0s > csp0s), "");
+    static_assert(!(csp0s > csp0d), "");
+    static_assert(!(csp0d > csp0s), "");
+    
+    static_assert(!(csp0d > csp1d), "");
+    static_assert(!(csp0s > csp1s), "");
+    static_assert(!(csp0s > csp1d), "");
+    static_assert(!(csp0d > csp1s), "");
+    
+    static_assert(!(csp1d > csp1s), "");
+    static_assert(!(csp1s > csp1d), "");
+    
+    static_assert(!(csp2d > csp3d), "");
+    static_assert(!(csp2s > csp3s), "");
+    static_assert(!(csp2d > csp3s), "");
+    static_assert(!(csp2s > csp3d), "");
+
+    static_assert(!(csp2d > csp4d), "");
+    static_assert(!(csp2s > csp4s), "");
+    static_assert(!(csp2d > csp4s), "");
+    static_assert(!(csp2s > csp4d), "");
+
+    static_assert( (csp4d > csp2d), "");
+    static_assert( (csp4s > csp2s), "");
+    static_assert( (csp4d > csp2s), "");
+    static_assert( (csp4s > csp2d), "");
+
+    std::span<int>     sp0d{};
+    std::span<int>     sp1d{iArr2, 10};
+    std::span<int>     sp2d{iArr2 + 3, 2};
+    std::span<int>     sp3d{iArr2 + 1, 2};
+    std::span<int>     sp4d{iArr2 + 6, 2};
+
+    std::span<int,  0> sp0s{};
+    std::span<int, 10> sp1s{iArr2, 10};
+    std::span<int, 2>  sp2s{iArr2 + 3, 2};
+    std::span<int, 2>  sp3s{iArr2 + 1, 2};
+    std::span<int, 2>  sp4s{iArr2 + 6, 2};
+
+    assert(!(sp0d > sp0d));
+    assert(!(sp0s > sp0s));
+    assert(!(sp0s > sp0d));
+    assert(!(sp0d > sp0s));
+    
+    assert(!(sp0d > sp1d));
+    assert(!(sp0s > sp1s));
+    assert(!(sp0s > sp1d));
+    assert(!(sp0d > sp1s));
+    
+    assert(!(sp1d > sp1s));
+    assert(!(sp1s > sp1d));
+    
+    assert(!(sp2d > sp3d));
+    assert(!(sp2s > sp3s));
+    assert(!(sp2d > sp3s));
+    assert(!(sp2s > sp3d));
+
+    assert(!(sp2d > sp4d));
+    assert(!(sp2s > sp4s));
+    assert(!(sp2d > sp4s));
+    assert(!(sp2s > sp4d));
+
+    assert( (sp4d > sp2d));
+    assert( (sp4s > sp2s));
+    assert( (sp4d > sp2s));
+    assert( (sp4s > sp2d));
+
+//  cross type comparisons
+    assert(!(csp0d > sp0d));
+    assert(!(csp0s > sp0s));
+    assert(!(csp0s > sp0d));
+    assert(!(csp0d > sp0s));
+    
+    assert(!(csp0d > sp1d));
+    assert(!(csp0s > sp1s));
+    assert(!(csp0s > sp1d));
+    assert(!(csp0d > sp1s));
+    
+    assert(!(csp1d > sp1s));
+    assert(!(csp1s > sp1d));
+    
+    assert(!(csp2d > sp3d));
+    assert(!(csp2s > sp3s));
+    assert(!(csp2d > sp3s));
+    assert(!(csp2s > sp3d));
+
+    assert(!(csp2d > sp4d));
+    assert(!(csp2s > sp4s));
+    assert(!(csp2d > sp4s));
+    assert(!(csp2s > sp4d));
+    
+    assert( (csp4d > sp2d));
+    assert( (csp4s > sp2s));
+    assert( (csp4d > sp2s));
+    assert( (csp4s > sp2d));
+
+
+//  More cross-type comparisons (int vs float)
+    static_assert(!(std::span<const float>{fArr1, 8} > std::span<const   int>{iArr1, 9}), "");
+    static_assert(!(std::span<const   int>{iArr1, 8} > std::span<const float>{fArr1, 9}), "");
+    assert(!(std::span<float>{fArr2} > std::span<int>{iArr2}));
+    assert(!(std::span<int>{iArr2} > std::span<float>{fArr2}));
+
+    static_assert( (std::span<const   int>{iArr1, 9} > std::span<const float>{fArr1, 8}), "");
+}
\ No newline at end of file
diff --git a/libcxx/test/std/containers/views/span.comparison/op.le.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.le.pass.cpp
new file mode 100644 (file)
index 0000000..f2fbc86
--- /dev/null
@@ -0,0 +1,153 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<class T, ptrdiff_t X, class U, ptrdiff_t Y>
+//   constexpr bool operator<=(span<T, X> l, span<U, Y> r);
+//   
+//
+// Effects: Equivalent to: return !(r < l);
+//
+
+#include <span>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr   int iArr1[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+            int iArr2[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+constexpr float fArr1[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+          float fArr2[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+         
+
+int main () {
+
+    constexpr std::span<const int>     csp0d{};
+    constexpr std::span<const int>     csp1d{iArr1, 10};
+    constexpr std::span<const int>     csp2d{iArr1 + 3, 2};
+    constexpr std::span<const int>     csp3d{iArr1 + 1, 2};
+    constexpr std::span<const int>     csp4d{iArr1 + 6, 2};
+
+    constexpr std::span<const int,  0> csp0s{};
+    constexpr std::span<const int, 10> csp1s{iArr1, 10};
+    constexpr std::span<const int, 2>  csp2s{iArr1 + 3, 2};
+    constexpr std::span<const int, 2>  csp3s{iArr1 + 1, 2};
+    constexpr std::span<const int, 2>  csp4s{iArr1 + 6, 2};
+
+    static_assert( (csp0d <= csp0d), "");
+    static_assert( (csp0s <= csp0s), "");
+    static_assert( (csp0s <= csp0d), "");
+    static_assert( (csp0d <= csp0s), "");
+    
+    static_assert( (csp0d <= csp1d), "");
+    static_assert( (csp0s <= csp1s), "");
+    static_assert( (csp0s <= csp1d), "");
+    static_assert( (csp0d <= csp1s), "");
+    
+    static_assert( (csp1d <= csp1s), "");
+    static_assert( (csp1s <= csp1d), "");
+    
+    static_assert( (csp2d <= csp3d), "");
+    static_assert( (csp2s <= csp3s), "");
+    static_assert( (csp2d <= csp3s), "");
+    static_assert( (csp2s <= csp3d), "");
+
+    static_assert( (csp2d <= csp4d), "");
+    static_assert( (csp2s <= csp4s), "");
+    static_assert( (csp2d <= csp4s), "");
+    static_assert( (csp2s <= csp4d), "");
+
+    static_assert(!(csp4d <= csp2d), "");
+    static_assert(!(csp4s <= csp2s), "");
+    static_assert(!(csp4d <= csp2s), "");
+    static_assert(!(csp4s <= csp2d), "");
+
+    std::span<int>     sp0d{};
+    std::span<int>     sp1d{iArr2, 10};
+    std::span<int>     sp2d{iArr2 + 3, 2};
+    std::span<int>     sp3d{iArr2 + 1, 2};
+    std::span<int>     sp4d{iArr2 + 6, 2};
+
+    std::span<int,  0> sp0s{};
+    std::span<int, 10> sp1s{iArr2, 10};
+    std::span<int, 2>  sp2s{iArr2 + 3, 2};
+    std::span<int, 2>  sp3s{iArr2 + 1, 2};
+    std::span<int, 2>  sp4s{iArr2 + 6, 2};
+
+    assert( (sp0d <= sp0d));
+    assert( (sp0s <= sp0s));
+    assert( (sp0s <= sp0d));
+    assert( (sp0d <= sp0s));
+    
+    assert( (sp0d <= sp1d));
+    assert( (sp0s <= sp1s));
+    assert( (sp0s <= sp1d));
+    assert( (sp0d <= sp1s));
+    
+    assert( (sp1d <= sp1s));
+    assert( (sp1s <= sp1d));
+    
+    assert( (sp2d <= sp3d));
+    assert( (sp2s <= sp3s));
+    assert( (sp2d <= sp3s));
+    assert( (sp2s <= sp3d));
+
+    assert( (sp2d <= sp4d));
+    assert( (sp2s <= sp4s));
+    assert( (sp2d <= sp4s));
+    assert( (sp2s <= sp4d));
+
+    assert(!(sp4d <= sp2d));
+    assert(!(sp4s <= sp2s));
+    assert(!(sp4d <= sp2s));
+    assert(!(sp4s <= sp2d));
+
+//  cross type comparisons
+    assert( (csp0d <= sp0d));
+    assert( (csp0s <= sp0s));
+    assert( (csp0s <= sp0d));
+    assert( (csp0d <= sp0s));
+    
+    assert( (csp0d <= sp1d));
+    assert( (csp0s <= sp1s));
+    assert( (csp0s <= sp1d));
+    assert( (csp0d <= sp1s));
+    
+    assert( (csp1d <= sp1s));
+    assert( (csp1s <= sp1d));
+    
+    assert( (csp2d <= sp3d));
+    assert( (csp2s <= sp3s));
+    assert( (csp2d <= sp3s));
+    assert( (csp2s <= sp3d));
+
+    assert( (csp2d <= sp4d));
+    assert( (csp2s <= sp4s));
+    assert( (csp2d <= sp4s));
+    assert( (csp2s <= sp4d));
+    
+    assert(!(csp4d <= sp2d));
+    assert(!(csp4s <= sp2s));
+    assert(!(csp4d <= sp2s));
+    assert(!(csp4s <= sp2d));
+
+//  More cross-type comparisons (int vs float)
+    static_assert(std::span<const float>{fArr1, 8} <= std::span<const   int>{iArr1, 9}, "");
+    static_assert(std::span<const   int>{iArr1, 8} <= std::span<const float>{fArr1, 9}, "");
+    assert( (std::span<float>{fArr2} <= std::span<int>{iArr2}));
+    assert( (std::span<int>{iArr2} <= std::span<float>{fArr2}));
+    
+    static_assert(!(std::span<const   int>{iArr1, 9} <= std::span<const float>{fArr1, 8}), "");
+}
\ No newline at end of file
diff --git a/libcxx/test/std/containers/views/span.comparison/op.lt.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.lt.pass.cpp
new file mode 100644 (file)
index 0000000..1a7de29
--- /dev/null
@@ -0,0 +1,154 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<class T, ptrdiff_t X, class U, ptrdiff_t Y>
+//   constexpr bool operator<(span<T, X> l, span<U, Y> r);
+//   
+//
+// Effects: Equivalent to:
+//      return lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
+//
+
+#include <span>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr   int iArr1[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+            int iArr2[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+constexpr float fArr1[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+          float fArr2[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+         
+
+int main () {
+
+    constexpr std::span<const int>     csp0d{};
+    constexpr std::span<const int>     csp1d{iArr1, 10};
+    constexpr std::span<const int>     csp2d{iArr1 + 3, 2};
+    constexpr std::span<const int>     csp3d{iArr1 + 1, 2};
+    constexpr std::span<const int>     csp4d{iArr1 + 6, 2};
+
+    constexpr std::span<const int,  0> csp0s{};
+    constexpr std::span<const int, 10> csp1s{iArr1, 10};
+    constexpr std::span<const int, 2>  csp2s{iArr1 + 3, 2};
+    constexpr std::span<const int, 2>  csp3s{iArr1 + 1, 2};
+    constexpr std::span<const int, 2>  csp4s{iArr1 + 6, 2};
+
+    static_assert(!(csp0d < csp0d), "");
+    static_assert(!(csp0s < csp0s), "");
+    static_assert(!(csp0s < csp0d), "");
+    static_assert(!(csp0d < csp0s), "");
+    
+    static_assert( (csp0d < csp1d), "");
+    static_assert( (csp0s < csp1s), "");
+    static_assert( (csp0s < csp1d), "");
+    static_assert( (csp0d < csp1s), "");
+    
+    static_assert(!(csp1d < csp1s), "");
+    static_assert(!(csp1s < csp1d), "");
+    
+    static_assert(!(csp2d < csp3d), "");
+    static_assert(!(csp2s < csp3s), "");
+    static_assert(!(csp2d < csp3s), "");
+    static_assert(!(csp2s < csp3d), "");
+
+    static_assert( (csp2d < csp4d), "");
+    static_assert( (csp2s < csp4s), "");
+    static_assert( (csp2d < csp4s), "");
+    static_assert( (csp2s < csp4d), "");
+
+    static_assert(!(csp4d < csp2d), "");
+    static_assert(!(csp4s < csp2s), "");
+    static_assert(!(csp4d < csp2s), "");
+    static_assert(!(csp4s < csp2d), "");
+
+    std::span<int>     sp0d{};
+    std::span<int>     sp1d{iArr2, 10};
+    std::span<int>     sp2d{iArr2 + 3, 2};
+    std::span<int>     sp3d{iArr2 + 1, 2};
+    std::span<int>     sp4d{iArr2 + 6, 2};
+
+    std::span<int,  0> sp0s{};
+    std::span<int, 10> sp1s{iArr2, 10};
+    std::span<int, 2>  sp2s{iArr2 + 3, 2};
+    std::span<int, 2>  sp3s{iArr2 + 1, 2};
+    std::span<int, 2>  sp4s{iArr2 + 6, 2};
+
+    assert(!(sp0d < sp0d));
+    assert(!(sp0s < sp0s));
+    assert(!(sp0s < sp0d));
+    assert(!(sp0d < sp0s));
+    
+    assert( (sp0d < sp1d));
+    assert( (sp0s < sp1s));
+    assert( (sp0s < sp1d));
+    assert( (sp0d < sp1s));
+    
+    assert(!(sp1d < sp1s));
+    assert(!(sp1s < sp1d));
+    
+    assert(!(sp2d < sp3d));
+    assert(!(sp2s < sp3s));
+    assert(!(sp2d < sp3s));
+    assert(!(sp2s < sp3d));
+
+    assert( (sp2d < sp4d));
+    assert( (sp2s < sp4s));
+    assert( (sp2d < sp4s));
+    assert( (sp2s < sp4d));
+
+    assert(!(sp4d < sp2d));
+    assert(!(sp4s < sp2s));
+    assert(!(sp4d < sp2s));
+    assert(!(sp4s < sp2d));
+
+//  cross type comparisons
+    assert(!(csp0d < sp0d));
+    assert(!(csp0s < sp0s));
+    assert(!(csp0s < sp0d));
+    assert(!(csp0d < sp0s));
+    
+    assert( (csp0d < sp1d));
+    assert( (csp0s < sp1s));
+    assert( (csp0s < sp1d));
+    assert( (csp0d < sp1s));
+    
+    assert(!(csp1d < sp1s));
+    assert(!(csp1s < sp1d));
+    
+    assert(!(csp2d < sp3d));
+    assert(!(csp2s < sp3s));
+    assert(!(csp2d < sp3s));
+    assert(!(csp2s < sp3d));
+
+    assert( (csp2d < sp4d));
+    assert( (csp2s < sp4s));
+    assert( (csp2d < sp4s));
+    assert( (csp2s < sp4d));
+    
+    assert(!(csp4d < sp2d));
+    assert(!(csp4s < sp2s));
+    assert(!(csp4d < sp2s));
+    assert(!(csp4s < sp2d));
+
+//  More cross-type comparisons (int vs float)
+    static_assert(std::span<const float>{fArr1, 8} < std::span<const   int>{iArr1, 9}, "");
+    static_assert(std::span<const   int>{iArr1, 8} < std::span<const float>{fArr1, 9}, "");
+    assert(!(std::span<float>{fArr2} < std::span<int>{iArr2}));
+    assert(!(std::span<int>{iArr2} < std::span<float>{fArr2}));
+
+    static_assert(!(std::span<const   int>{iArr1, 9} < std::span<const float>{fArr1, 8}), "");  
+}
\ No newline at end of file
diff --git a/libcxx/test/std/containers/views/span.comparison/op.ne.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.ne.pass.cpp
new file mode 100644 (file)
index 0000000..ecf05b3
--- /dev/null
@@ -0,0 +1,168 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<class T, ptrdiff_t X, class U, ptrdiff_t Y>
+//   constexpr bool operator!=(span<T, X> l, span<U, Y> r);
+//   
+//
+// Effects: Equivalent to: return !(l == r);
+//
+
+#include <span>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr   int iArr1[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+            int iArr2[] = { 0,  1,  2,  1,  2,  5,  6,  7,  8,  9};
+constexpr float fArr1[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+          float fArr2[]  = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.};
+         
+
+int main () {
+
+    constexpr std::span<const int>     csp0d{};
+    constexpr std::span<const int>     csp1d{iArr1, 10};
+    constexpr std::span<const int>     csp2d{iArr1 + 3, 2};
+    constexpr std::span<const int>     csp3d{iArr1 + 1, 2};
+    constexpr std::span<const int>     csp4d{iArr1 + 6, 2};
+
+    constexpr std::span<const int,  0> csp0s{};
+    constexpr std::span<const int, 10> csp1s{iArr1, 10};
+    constexpr std::span<const int, 2>  csp2s{iArr1 + 3, 2};
+    constexpr std::span<const int, 2>  csp3s{iArr1 + 1, 2};
+    constexpr std::span<const int, 2>  csp4s{iArr1 + 6, 2};
+
+    static_assert(!(csp0d != csp0d), "");
+    static_assert(!(csp0s != csp0s), "");
+    static_assert(!(csp0s != csp0d), "");
+    static_assert(!(csp0d != csp0s), "");
+    
+    static_assert( (csp0d != csp1d), "");
+    static_assert( (csp0s != csp1s), "");
+    static_assert( (csp0s != csp1d), "");
+    static_assert( (csp0d != csp1s), "");
+    
+    static_assert(!(csp1d != csp1s), "");
+    static_assert(!(csp1s != csp1d), "");
+    
+    static_assert(!(csp2d != csp3d), "");
+    static_assert(!(csp2s != csp3s), "");
+    static_assert(!(csp2d != csp3s), "");
+    static_assert(!(csp2s != csp3d), "");
+
+    static_assert(!(csp2d != csp3d), "");
+    static_assert(!(csp2s != csp3s), "");
+    static_assert(!(csp2d != csp3s), "");
+    static_assert(!(csp2s != csp3d), "");
+
+    static_assert( (csp2d != csp4d), "");
+    static_assert( (csp2s != csp4s), "");
+    static_assert( (csp2d != csp4s), "");
+    static_assert( (csp2s != csp4d), "");
+
+    static_assert( (csp4d != csp2d), "");
+    static_assert( (csp4s != csp2s), "");
+    static_assert( (csp4d != csp2s), "");
+    static_assert( (csp4s != csp2d), "");
+
+    std::span<int>     sp0d{};
+    std::span<int>     sp1d{iArr2, 10};
+    std::span<int>     sp2d{iArr2 + 3, 2};
+    std::span<int>     sp3d{iArr2 + 1, 2};
+    std::span<int>     sp4d{iArr2 + 6, 2};
+
+    std::span<int,  0> sp0s{};
+    std::span<int, 10> sp1s{iArr2, 10};
+    std::span<int, 2>  sp2s{iArr2 + 3, 2};
+    std::span<int, 2>  sp3s{iArr2 + 1, 2};
+    std::span<int, 2>  sp4s{iArr2 + 6, 2};
+
+    assert(!(sp0d != sp0d));
+    assert(!(sp0s != sp0s));
+    assert(!(sp0s != sp0d));
+    assert(!(sp0d != sp0s));
+    
+    assert( (sp0d != sp1d));
+    assert( (sp0s != sp1s));
+    assert( (sp0s != sp1d));
+    assert( (sp0d != sp1s));
+    
+    assert(!(sp1d != sp1s));
+    assert(!(sp1s != sp1d));
+    
+    assert(!(sp2d != sp3d));
+    assert(!(sp2s != sp3s));
+    assert(!(sp2d != sp3s));
+    assert(!(sp2s != sp3d));
+
+    assert(!(sp2d != sp3d));
+    assert(!(sp2s != sp3s));
+    assert(!(sp2d != sp3s));
+    assert(!(sp2s != sp3d));
+
+    assert( (sp2d != sp4d));
+    assert( (sp2s != sp4s));
+    assert( (sp2d != sp4s));
+    assert( (sp2s != sp4d));
+
+    assert( (sp4d != sp2d));
+    assert( (sp4s != sp2s));
+    assert( (sp4d != sp2s));
+    assert( (sp4s != sp2d));
+
+//  cross type comparisons
+    assert(!(csp0d != sp0d));
+    assert(!(csp0s != sp0s));
+    assert(!(csp0s != sp0d));
+    assert(!(csp0d != sp0s));
+    
+    assert( (csp0d != sp1d));
+    assert( (csp0s != sp1s));
+    assert( (csp0s != sp1d));
+    assert( (csp0d != sp1s));
+    
+    assert(!(csp1d != sp1s));
+    assert(!(csp1s != sp1d));
+    
+    assert(!(csp2d != sp3d));
+    assert(!(csp2s != sp3s));
+    assert(!(csp2d != sp3s));
+    assert(!(csp2s != sp3d));
+
+    assert(!(csp2d != sp3d));
+    assert(!(csp2s != sp3s));
+    assert(!(csp2d != sp3s));
+    assert(!(csp2s != sp3d));
+
+    assert( (csp2d != sp4d));
+    assert( (csp2s != sp4s));
+    assert( (csp2d != sp4s));
+    assert( (csp2s != sp4d));
+    
+    assert( (csp4d != sp2d));
+    assert( (csp4s != sp2s));
+    assert( (csp4d != sp2s));
+    assert( (csp4s != sp2d));
+
+//  More cross-type comparisons (int vs float)
+    static_assert(!(std::span<const float>{fArr1} != std::span<const   int>{iArr1}), "");
+    static_assert(!(std::span<const   int>{iArr1} != std::span<const float>{fArr1}), "");
+    assert(!(std::span<float>{fArr2} != std::span<int>{iArr2}));
+    assert(!(std::span<int>{iArr2} != std::span<float>{fArr2}));
+
+    static_assert( (std::span<const   int>{iArr1, 9} != std::span<const float>{fArr1, 8}), "");
+}
\ No newline at end of file
diff --git a/libcxx/test/std/containers/views/span.cons/array.fail.cpp b/libcxx/test/std/containers/views/span.cons/array.fail.cpp
new file mode 100644 (file)
index 0000000..7ef49fc
--- /dev/null
@@ -0,0 +1,72 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// 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;  
+//
+// Remarks: These constructors shall not participate in overload resolution unless:
+//   â€” extent == dynamic_extent || N == extent is true, and
+//   â€” remove_pointer_t<decltype(data(arr))>(*)[] is convertible to ElementType(*)[].
+//
+
+
+#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};
+
+int main ()
+{
+//  Size wrong
+    {
+    std::span<int, 2>   s1(arr); // expected-error {{no matching constructor for initialization of 'std::span<int, 2>'}}
+    }
+    
+//  Type wrong
+    {
+    std::span<float>    s1(arr);   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
+    std::span<float, 3> s2(arr);   // expected-error {{no matching constructor for initialization of 'std::span<float, 3>'}}
+    }
+    
+//  CV wrong (dynamically sized)
+    {
+    std::span<               int> s1{ carr};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s2{ varr};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s3{cvarr};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<const          int> s4{ varr};    // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+    std::span<const          int> s5{cvarr};    // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+    std::span<      volatile int> s6{ carr};    // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    std::span<      volatile int> s7{cvarr};    // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    }
+
+//  CV wrong (statically sized)
+    {
+    std::span<               int,3> s1{ carr};  // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
+    std::span<               int,3> s2{ varr};  // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
+    std::span<               int,3> s3{cvarr};  // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
+    std::span<const          int,3> s4{ varr};  // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
+    std::span<const          int,3> s5{cvarr};  // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
+    std::span<      volatile int,3> s6{ carr};  // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
+    std::span<      volatile int,3> s7{cvarr};  // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
+    }
+}
diff --git a/libcxx/test/std/containers/views/span.cons/array.pass.cpp b/libcxx/test/std/containers/views/span.cons/array.pass.cpp
new file mode 100644 (file)
index 0000000..80a0f07
--- /dev/null
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<size_t N>
+//     constexpr span(element_type (&arr)[N]) noexcept;
+//
+// Remarks: These constructors shall not participate in overload resolution unless:
+//   â€” extent == dynamic_extent || N == extent is true, and
+//   â€” remove_pointer_t<decltype(data(arr))>(*)[] is convertible to ElementType(*)[].
+//
+
+
+#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};    // a span<               int> pointing at int.
+    std::span<const          int> s2{ carr};    // a span<const          int> pointing at const int.
+    std::span<      volatile int> s3{ varr};    // a span<      volatile int> pointing at volatile int.
+    std::span<const volatile int> s4{cvarr};    // 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};  // a span<               int> pointing at int.
+    std::span<const          int,3> s2{ carr};  // a span<const          int> pointing at const int.
+    std::span<      volatile int,3> s3{ varr};  // a span<      volatile int> pointing at volatile int.
+    std::span<const volatile int,3> s4{cvarr};  // a span<const volatile int> pointing at const volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
+    }
+
+
+//  types different (dynamic sized)
+    {
+    std::span<const          int> s1{ arr};     // a span<const          int> pointing at int.
+    std::span<      volatile int> s2{ arr};     // a span<      volatile int> pointing at int.
+    std::span<      volatile int> s3{ arr};     // a span<      volatile int> pointing at const int.
+    std::span<const volatile int> s4{ arr};     // a span<const volatile int> pointing at int.
+    std::span<const volatile int> s5{carr};     // a span<const volatile int> pointing at const int.
+    std::span<const volatile int> s6{varr};     // a span<const volatile int> pointing at volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
+    }
+
+//  types different (static sized)
+    {
+    std::span<const          int,3> s1{ arr};   // a span<const          int> pointing at int.
+    std::span<      volatile int,3> s2{ arr};   // a span<      volatile int> pointing at int.
+    std::span<      volatile int,3> s3{ arr};   // a span<      volatile int> pointing at const int.
+    std::span<const volatile int,3> s4{ arr};   // a span<const volatile int> pointing at int.
+    std::span<const volatile int,3> s5{carr};   // a span<const volatile int> pointing at const int.
+    std::span<const volatile int,3> s6{varr};   // 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] = {};
+
+    ASSERT_NOEXCEPT(std::span<const T>   {val});
+    ASSERT_NOEXCEPT(std::span<const T, 2>{val});
+    std::span<const T>    s1{val};
+    std::span<const T, 2> s2{val};
+    return
+        s1.data() == &val[0] && s1.size() == 2
+    &&  s2.data() == &val[0] && s2.size() == 2;
+}
+
+
+template <typename T>
+void testRuntimeSpan()
+{
+    T val[2] = {};
+    ASSERT_NOEXCEPT(std::span<T>   {val});
+    ASSERT_NOEXCEPT(std::span<T, 2>{val});
+    std::span<T>    s1{val};
+    std::span<T, 2> s2{val};
+    assert(s1.data() == &val[0] && s1.size() == 2);
+    assert(s2.data() == &val[0] && s2.size() == 2);
+}
+
+struct A{};
+
+int main ()
+{
+    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();
+}
diff --git a/libcxx/test/std/containers/views/span.cons/assign.pass.cpp b/libcxx/test/std/containers/views/span.cons/assign.pass.cpp
new file mode 100644 (file)
index 0000000..b5bd7ae
--- /dev/null
@@ -0,0 +1,293 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+//  constexpr span& operator=(const span& other) noexcept = default;
+
+#include <span>
+#include <cassert>
+#include <string>
+#include <utility>
+
+#include "test_macros.h"
+
+template <typename T>
+constexpr bool doAssign(T lhs, T rhs)
+{
+    ASSERT_NOEXCEPT(std::declval<T&>() = rhs);
+    lhs = rhs;
+    return lhs.data() == rhs.data()
+     &&    lhs.size() == rhs.size();
+}
+
+struct A{};
+
+constexpr int carr1[] = {1,2,3,4};
+constexpr int carr2[] = {3,4,5};
+constexpr int carr3[] = {7,8};
+          int   arr[] = {5,6,7,9};
+std::string strs[] = {"ABC", "DEF", "GHI"};
+
+
+int main ()
+{
+
+//  constexpr dynamically sized assignment
+    {
+//  On systems where 'ptrdiff_t' is a synonym for 'int',
+//  the call span(ptr, 0) selects the (pointer, index_type) constructor.
+//  On systems where 'ptrdiff_t' is NOT a synonym for 'int',
+//  it is ambiguous, because of 0 also being convertible to a null pointer
+//  and so the compiler can't choose between:
+//      span(pointer, index_type)
+//  and span(pointer, pointer)
+//  We cast zero to std::ptrdiff_t to remove that ambiguity.
+//  Example:
+//      On darwin x86_64, ptrdiff_t is the same as long int.
+//      On darwin i386, ptrdiff_t is the same as int.
+        constexpr std::span<const int> spans[] = {
+            {},
+            {carr1, static_cast<std::ptrdiff_t>(0)},
+            {carr1,     1},
+            {carr1,     2},
+            {carr1,     3},
+            {carr1,     4},
+            {carr2, static_cast<std::ptrdiff_t>(0)},
+            {carr2,     1},
+            {carr2,     2},
+            {carr2,     3},
+            {carr3, static_cast<std::ptrdiff_t>(0)},
+            {carr3,     1},
+            {carr3,     2}
+            };
+
+        static_assert(std::size(spans) == 13, "" );
+        
+//  No for loops in constexpr land :-(
+        static_assert(doAssign(spans[0], spans[0]), "");
+        static_assert(doAssign(spans[0], spans[1]), "");
+        static_assert(doAssign(spans[0], spans[2]), "");
+        static_assert(doAssign(spans[0], spans[3]), "");
+        static_assert(doAssign(spans[0], spans[4]), "");
+        static_assert(doAssign(spans[0], spans[5]), "");
+        static_assert(doAssign(spans[0], spans[6]), "");
+        static_assert(doAssign(spans[0], spans[7]), "");
+        static_assert(doAssign(spans[0], spans[8]), "");
+        static_assert(doAssign(spans[0], spans[9]), "");
+        static_assert(doAssign(spans[0], spans[10]), "");
+        static_assert(doAssign(spans[0], spans[11]), "");
+        static_assert(doAssign(spans[0], spans[12]), "");
+
+        static_assert(doAssign(spans[1], spans[1]), "");
+        static_assert(doAssign(spans[1], spans[2]), "");
+        static_assert(doAssign(spans[1], spans[3]), "");
+        static_assert(doAssign(spans[1], spans[4]), "");
+        static_assert(doAssign(spans[1], spans[5]), "");
+        static_assert(doAssign(spans[1], spans[6]), "");
+        static_assert(doAssign(spans[1], spans[7]), "");
+        static_assert(doAssign(spans[1], spans[8]), "");
+        static_assert(doAssign(spans[1], spans[9]), "");
+        static_assert(doAssign(spans[1], spans[10]), "");
+        static_assert(doAssign(spans[1], spans[11]), "");
+        static_assert(doAssign(spans[1], spans[12]), "");
+
+        static_assert(doAssign(spans[2], spans[2]), "");
+        static_assert(doAssign(spans[2], spans[3]), "");
+        static_assert(doAssign(spans[2], spans[4]), "");
+        static_assert(doAssign(spans[2], spans[5]), "");
+        static_assert(doAssign(spans[2], spans[6]), "");
+        static_assert(doAssign(spans[2], spans[7]), "");
+        static_assert(doAssign(spans[2], spans[8]), "");
+        static_assert(doAssign(spans[2], spans[9]), "");
+        static_assert(doAssign(spans[2], spans[10]), "");
+        static_assert(doAssign(spans[2], spans[11]), "");
+        static_assert(doAssign(spans[2], spans[12]), "");
+
+        static_assert(doAssign(spans[3], spans[3]), "");
+        static_assert(doAssign(spans[3], spans[4]), "");
+        static_assert(doAssign(spans[3], spans[4]), "");
+        static_assert(doAssign(spans[3], spans[4]), "");
+        static_assert(doAssign(spans[3], spans[4]), "");
+        static_assert(doAssign(spans[3], spans[4]), "");
+        static_assert(doAssign(spans[3], spans[4]), "");
+        static_assert(doAssign(spans[3], spans[4]), "");
+        static_assert(doAssign(spans[3], spans[4]), "");
+        static_assert(doAssign(spans[3], spans[10]), "");
+        static_assert(doAssign(spans[3], spans[11]), "");
+        static_assert(doAssign(spans[3], spans[12]), "");
+
+        static_assert(doAssign(spans[4], spans[4]), "");
+        static_assert(doAssign(spans[4], spans[5]), "");
+        static_assert(doAssign(spans[4], spans[6]), "");
+        static_assert(doAssign(spans[4], spans[7]), "");
+        static_assert(doAssign(spans[4], spans[8]), "");
+        static_assert(doAssign(spans[4], spans[9]), "");
+        static_assert(doAssign(spans[4], spans[10]), "");
+        static_assert(doAssign(spans[4], spans[11]), "");
+        static_assert(doAssign(spans[4], spans[12]), "");
+
+        static_assert(doAssign(spans[5], spans[5]), "");
+        static_assert(doAssign(spans[5], spans[6]), "");
+        static_assert(doAssign(spans[5], spans[7]), "");
+        static_assert(doAssign(spans[5], spans[8]), "");
+        static_assert(doAssign(spans[5], spans[9]), "");
+        static_assert(doAssign(spans[5], spans[10]), "");
+        static_assert(doAssign(spans[5], spans[11]), "");
+        static_assert(doAssign(spans[5], spans[12]), "");
+
+        static_assert(doAssign(spans[6], spans[6]), "");
+        static_assert(doAssign(spans[6], spans[7]), "");
+        static_assert(doAssign(spans[6], spans[8]), "");
+        static_assert(doAssign(spans[6], spans[9]), "");
+        static_assert(doAssign(spans[6], spans[10]), "");
+        static_assert(doAssign(spans[6], spans[11]), "");
+        static_assert(doAssign(spans[6], spans[12]), "");
+
+        static_assert(doAssign(spans[7], spans[7]), "");
+        static_assert(doAssign(spans[7], spans[8]), "");
+        static_assert(doAssign(spans[7], spans[9]), "");
+        static_assert(doAssign(spans[7], spans[10]), "");
+        static_assert(doAssign(spans[7], spans[11]), "");
+        static_assert(doAssign(spans[7], spans[12]), "");
+
+        static_assert(doAssign(spans[8], spans[8]), "");
+        static_assert(doAssign(spans[8], spans[9]), "");
+        static_assert(doAssign(spans[8], spans[10]), "");
+        static_assert(doAssign(spans[8], spans[11]), "");
+        static_assert(doAssign(spans[8], spans[12]), "");
+
+        static_assert(doAssign(spans[9], spans[9]), "");
+        static_assert(doAssign(spans[9], spans[10]), "");
+        static_assert(doAssign(spans[9], spans[11]), "");
+        static_assert(doAssign(spans[9], spans[12]), "");
+
+        static_assert(doAssign(spans[10], spans[10]), "");
+        static_assert(doAssign(spans[10], spans[11]), "");
+        static_assert(doAssign(spans[10], spans[12]), "");
+
+        static_assert(doAssign(spans[11], spans[11]), "");
+        static_assert(doAssign(spans[11], spans[12]), "");
+
+        static_assert(doAssign(spans[12], spans[12]), "");
+
+//      for (size_t i = 0; i < std::size(spans); ++i)
+//          for (size_t j = i; j < std::size(spans); ++j)
+//              static_assert(doAssign(spans[i], spans[j]), "");
+    }
+
+//  constexpr statically sized assignment
+    {
+        constexpr std::span<const int,2> spans[] = {
+            {carr1, 2},
+            {carr1 + 1, 2},
+            {carr1 + 2, 2},
+            {carr2, 2},
+            {carr2 + 1, 2},
+            {carr3, 2}
+            };
+        
+        static_assert(std::size(spans) == 6, "" );
+
+//  No for loops in constexpr land :-(
+        static_assert(doAssign(spans[0], spans[0]), "");
+        static_assert(doAssign(spans[0], spans[1]), "");
+        static_assert(doAssign(spans[0], spans[2]), "");
+        static_assert(doAssign(spans[0], spans[3]), "");
+        static_assert(doAssign(spans[0], spans[4]), "");
+        static_assert(doAssign(spans[0], spans[5]), "");
+
+        static_assert(doAssign(spans[1], spans[1]), "");
+        static_assert(doAssign(spans[1], spans[2]), "");
+        static_assert(doAssign(spans[1], spans[3]), "");
+        static_assert(doAssign(spans[1], spans[4]), "");
+        static_assert(doAssign(spans[1], spans[5]), "");
+
+        static_assert(doAssign(spans[2], spans[2]), "");
+        static_assert(doAssign(spans[2], spans[3]), "");
+        static_assert(doAssign(spans[2], spans[4]), "");
+        static_assert(doAssign(spans[2], spans[5]), "");
+
+        static_assert(doAssign(spans[3], spans[3]), "");
+        static_assert(doAssign(spans[3], spans[4]), "");
+        static_assert(doAssign(spans[3], spans[5]), "");
+
+        static_assert(doAssign(spans[4], spans[4]), "");
+        static_assert(doAssign(spans[4], spans[5]), "");
+
+        static_assert(doAssign(spans[5], spans[5]), "");
+
+//      for (size_t i = 0; i < std::size(spans); ++i)
+//          for (size_t j = i; j < std::size(spans); ++j)
+//              static_assert(doAssign(spans[i], spans[j]), "");
+    }
+
+
+//  dynamically sized assignment
+    {
+        std::span<int> spans[] = {
+            {},
+            {arr,     arr + 1},
+            {arr,     arr + 2},
+            {arr,     arr + 3},
+            {arr + 1, arr + 3} // same size as s2
+            };
+        
+        for (size_t i = 0; i < std::size(spans); ++i)
+            for (size_t j = i; j < std::size(spans); ++j)
+                assert((doAssign(spans[i], spans[j])));
+    }
+
+//  statically sized assignment
+    {
+        std::span<int,2> spans[] = {
+            {arr,     arr + 2},
+            {arr + 1, arr + 3},
+            {arr + 2, arr + 4}
+            };
+        
+        for (size_t i = 0; i < std::size(spans); ++i)
+            for (size_t j = i; j < std::size(spans); ++j)
+                assert((doAssign(spans[i], spans[j])));
+    }
+
+//  dynamically sized assignment
+    {
+    std::span<std::string> spans[] = {
+            {strs,     strs},
+            {strs,     strs + 1},
+            {strs,     strs + 2},
+            {strs,     strs + 3},
+            {strs + 1, strs + 1},
+            {strs + 1, strs + 2},
+            {strs + 1, strs + 3},
+            {strs + 2, strs + 2},
+            {strs + 2, strs + 3},
+            {strs + 3, strs + 3}
+            };
+        
+        for (size_t i = 0; i < std::size(spans); ++i)
+            for (size_t j = i; j < std::size(spans); ++j)
+                assert((doAssign(spans[i], spans[j])));
+    }
+
+    {
+    std::span<std::string, 1> spans[] = {
+            {strs,     strs + 1},
+            {strs + 1, strs + 2},
+            {strs + 2, strs + 3}
+            };
+        
+        for (size_t i = 0; i < std::size(spans); ++i)
+            for (size_t j = i; j < std::size(spans); ++j)
+                assert((doAssign(spans[i], spans[j])));
+    }
+}
diff --git a/libcxx/test/std/containers/views/span.cons/container.fail.cpp b/libcxx/test/std/containers/views/span.cons/container.fail.cpp
new file mode 100644 (file)
index 0000000..ecd7fcb
--- /dev/null
@@ -0,0 +1,117 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, 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:
+//   â€” 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 <list>
+#include <forward_list>
+#include <deque>
+
+#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;}
+};
+
+
+int main ()
+{
+
+//  Missing size and/or data
+    {
+    std::span<int>    s1{IsAContainer<int>()};          // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<int, 0> s2{IsAContainer<int>()};          // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    std::span<int>    s3{NotAContainerNoData<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<int, 0> s4{NotAContainerNoData<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    std::span<int>    s5{NotAContainerNoSize<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<int, 0> s6{NotAContainerNoSize<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    std::span<int>    s7{NotAContainerPrivate<int>()};  // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<int, 0> s8{NotAContainerPrivate<int>()};  // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+
+//  Again with the standard containers
+    std::span<int>    s11{std::deque<int>()};           // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<int, 0> s12{std::deque<int>()};           // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    std::span<int>    s13{std::list<int>()};            // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<int, 0> s14{std::list<int>()};            // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    std::span<int>    s15{std::forward_list<int>()};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<int, 0> s16{std::forward_list<int>()};    // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    }
+
+//  Not the same type
+    {
+    std::span<float>    s1{IsAContainer<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
+    std::span<float, 0> s2{IsAContainer<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<float, 0>'}}    
+    }
+
+//  CV wrong (dynamically sized)
+    {
+    std::span<               int> s1{IsAContainer<const          int>()};   // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s2{IsAContainer<      volatile int>()};   // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s3{IsAContainer<const volatile int>()};   // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<const          int> s4{IsAContainer<      volatile int>()};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+    std::span<const          int> s5{IsAContainer<const volatile int>()};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+    std::span<      volatile int> s6{IsAContainer<const          int>()};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    std::span<      volatile int> s7{IsAContainer<const volatile int>()};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    }
+
+//  CV wrong (statically sized)
+    {
+    std::span<               int,1> s1{IsAContainer<const          int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}}
+    std::span<               int,1> s2{IsAContainer<      volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}}
+    std::span<               int,1> s3{IsAContainer<const volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}}
+    std::span<const          int,1> s4{IsAContainer<      volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 1>'}}
+    std::span<const          int,1> s5{IsAContainer<const volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 1>'}}
+    std::span<      volatile int,1> s6{IsAContainer<const          int>()}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 1>'}}
+    std::span<      volatile int,1> s7{IsAContainer<const volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 1>'}}
+    }
+
+}
diff --git a/libcxx/test/std/containers/views/span.cons/container.pass.cpp b/libcxx/test/std/containers/views/span.cons/container.pass.cpp
new file mode 100644 (file)
index 0000000..478a3da
--- /dev/null
@@ -0,0 +1,118 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, 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:
+//   â€” 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 const *getV() const {return &v_;} // for checking
+    T v_;
+};
+
+
+void checkCV()
+{
+    std::vector<int> v  = {1,2,3};
+
+//  Types the same (dynamic sized)
+    {
+    std::span<               int> s1{v};    // a span<               int> pointing at int.
+    }
+
+//  Types the same (static sized)
+    {
+    std::span<               int,3> s1{v};  // a span<               int> pointing at int.
+    }
+
+//  types different (dynamic sized)
+    {
+    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.
+    }
+
+//  types different (static sized)
+    {
+    std::span<const          int,3> s1{v};  // a span<const          int> pointing at int.
+    std::span<      volatile int,3> s2{v};  // a span<      volatile int> pointing at int.
+    std::span<      volatile int,3> s3{v};  // a span<      volatile int> pointing at const int.
+    std::span<const volatile int,3> s4{v};  // a span<const volatile int> pointing at int.
+    }
+}
+
+
+template <typename T>
+constexpr bool testConstexprSpan()
+{
+    constexpr IsAContainer<const T> val{};
+    std::span<const T>    s1{val};
+    std::span<const T, 1> s2{val};
+    return
+        s1.data() == val.getV() && s1.size() == 1
+    &&  s2.data() == val.getV() && s2.size() == 1;
+}
+
+
+template <typename T>
+void testRuntimeSpan()
+{
+    IsAContainer<T> val{};
+    std::span<const T>    s1{val};
+    std::span<const T, 1> s2{val};
+    assert(s1.data() == val.getV() && s1.size() == 1);
+    assert(s2.data() == val.getV() && s2.size() == 1);
+}
+
+struct A{};
+
+int main ()
+{
+    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();
+}
diff --git a/libcxx/test/std/containers/views/span.cons/copy.pass.cpp b/libcxx/test/std/containers/views/span.cons/copy.pass.cpp
new file mode 100644 (file)
index 0000000..2cfffbb
--- /dev/null
@@ -0,0 +1,71 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+//  constexpr span(const span& other) noexcept = default;
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+template <typename T>
+constexpr bool doCopy(const T &rhs)
+{
+    ASSERT_NOEXCEPT(T{rhs});
+    T lhs{rhs};
+    return lhs.data() == rhs.data()
+     &&    lhs.size() == rhs.size();
+}
+
+struct A{};
+
+template <typename T>
+void testCV ()
+{
+    int  arr[] = {1,2,3};
+    assert((doCopy(std::span<T>  ()          )));
+    assert((doCopy(std::span<T,0>()          )));
+    assert((doCopy(std::span<T>  (&arr[0], 1))));
+    assert((doCopy(std::span<T,1>(&arr[0], 1))));
+    assert((doCopy(std::span<T>  (&arr[0], 2))));
+    assert((doCopy(std::span<T,2>(&arr[0], 2))));
+}
+
+
+int main ()
+{
+    constexpr int carr[] = {1,2,3};
+    
+    static_assert(doCopy(std::span<      int>  ()),            "");
+    static_assert(doCopy(std::span<      int,0>()),            "");
+    static_assert(doCopy(std::span<const int>  (&carr[0], 1)), "");
+    static_assert(doCopy(std::span<const int,1>(&carr[0], 1)), "");
+    static_assert(doCopy(std::span<const int>  (&carr[0], 2)), "");
+    static_assert(doCopy(std::span<const int,2>(&carr[0], 2)), "");
+
+    static_assert(doCopy(std::span<long>()),   "");
+    static_assert(doCopy(std::span<double>()), "");
+    static_assert(doCopy(std::span<A>()),      "");
+
+    std::string s;
+    assert(doCopy(std::span<std::string>   ()     ));
+    assert(doCopy(std::span<std::string, 0>()     ));
+    assert(doCopy(std::span<std::string>   (&s, 1)));
+    assert(doCopy(std::span<std::string, 1>(&s, 1)));
+
+    testCV<               int>();
+    testCV<const          int>();
+    testCV<      volatile int>();
+    testCV<const volatile int>();
+}
diff --git a/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp b/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
new file mode 100644 (file)
index 0000000..3410bb3
--- /dev/null
@@ -0,0 +1,83 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+//   template<class T, size_t N>
+//     span(T (&)[N]) -> span<T, N>;
+// 
+//   template<class T, size_t N>
+//     span(array<T, N>&) -> span<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>;
+
+
+
+#include <span>
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <string>
+#include <type_traits>
+
+#include "test_macros.h"
+
+int main ()
+{
+    {
+    int arr[] = {1,2,3};
+    std::span s{arr};
+    using S = decltype(s);
+    ASSERT_SAME_TYPE(S, std::span<int, 3>);
+    assert((std::equal(std::begin(arr), std::end(arr), s.begin(), s.end())));
+    }
+
+    {
+    std::array<double, 4> arr = {1.0, 2.0, 3.0, 4.0};
+    std::span s{arr};
+    using S = decltype(s);
+    ASSERT_SAME_TYPE(S, std::span<double, 4>);
+    assert((std::equal(std::begin(arr), std::end(arr), s.begin(), s.end())));
+    }
+
+    {
+    const std::array<long, 5> arr = {4, 5, 6, 7, 8};
+    std::span s{arr};
+    using S = decltype(s);
+    ASSERT_SAME_TYPE(S, std::span<const long, 5>);
+    assert((std::equal(std::begin(arr), std::end(arr), s.begin(), s.end())));
+    }
+    
+    {
+    std::string str{"ABCDE"};
+    std::span s{str};
+    using S = decltype(s);
+    ASSERT_SAME_TYPE(S, std::span<char>);
+    assert((size_t)s.size() == str.size());
+    assert((std::equal(s.begin(), s.end(), std::begin(s), std::end(s))));
+    }
+
+    {
+    const std::string str{"QWERTYUIOP"};
+    std::span s{str};
+    using S = decltype(s);
+    ASSERT_SAME_TYPE(S, std::span<const char>);
+    assert((size_t)s.size() == str.size());
+    assert((std::equal(s.begin(), s.end(), std::begin(s), std::end(s))));
+    }
+}
diff --git a/libcxx/test/std/containers/views/span.cons/default.fail.cpp b/libcxx/test/std/containers/views/span.cons/default.fail.cpp
new file mode 100644 (file)
index 0000000..d1fefe5
--- /dev/null
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr span() noexcept;
+//
+//  Remarks: This constructor shall not participate in overload resolution
+//          unless Extent <= 0 is true.
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+int main ()
+{
+    std::span<int, 2> s; // expected-error@span:* {{static_assert failed "Can't default construct a statically sized span with size > 0"}}
+    
+//  TODO: This is what I want:
+// eXpected-error {{no matching constructor for initialization of 'std::span<int, 2>'}}
+}
diff --git a/libcxx/test/std/containers/views/span.cons/default.pass.cpp b/libcxx/test/std/containers/views/span.cons/default.pass.cpp
new file mode 100644 (file)
index 0000000..f7e4966
--- /dev/null
@@ -0,0 +1,82 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr span() noexcept;
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+void checkCV()
+{
+//  Types the same (dynamic sized)
+    {
+    std::span<               int> s1;
+    std::span<const          int> s2;
+    std::span<      volatile int> s3;
+    std::span<const volatile int> s4;
+    assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
+    }
+
+//  Types the same (static sized)
+    {
+    std::span<               int,0> s1;
+    std::span<const          int,0> s2;
+    std::span<      volatile int,0> s3;
+    std::span<const volatile int,0> s4;
+    assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
+    }
+}
+
+
+template <typename T>
+constexpr bool testConstexprSpan()
+{
+    std::span<const T>    s1;
+    std::span<const T, 0> s2;
+    return
+        s1.data() == nullptr && s1.size() == 0
+    &&  s2.data() == nullptr && s2.size() == 0;
+}
+
+
+template <typename T>
+void testRuntimeSpan()
+{
+    ASSERT_NOEXCEPT(T{});
+    std::span<const T>    s1;
+    std::span<const T, 0> s2;
+    assert(s1.data() == nullptr && s1.size() == 0);
+    assert(s2.data() == nullptr && s2.size() == 0);
+}
+
+
+struct A{};
+
+int main ()
+{
+    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();
+}
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
new file mode 100644 (file)
index 0000000..db24e3d
--- /dev/null
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr span(pointer ptr, index_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};
+
+int main ()
+{
+//  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>'}}
+    }
+}
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
new file mode 100644 (file)
index 0000000..7302759
--- /dev/null
@@ -0,0 +1,113 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr span(pointer ptr, index_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 different (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 different (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 ()
+{
+    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();
+}
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
new file mode 100644 (file)
index 0000000..a55f059
--- /dev/null
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, 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};
+
+int main ()
+{
+//  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>'}}
+    }
+}
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
new file mode 100644 (file)
index 0000000..afb525e
--- /dev/null
@@ -0,0 +1,113 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, 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 different (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 different (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 ()
+{
+    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();
+}
diff --git a/libcxx/test/std/containers/views/span.cons/span.fail.cpp b/libcxx/test/std/containers/views/span.cons/span.fail.cpp
new file mode 100644 (file)
index 0000000..1fa7155
--- /dev/null
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<class OtherElementType, ptrdiff_t OtherExtent>
+//    constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept;
+//
+//  Remarks: This constructor shall not participate in overload resolution unless:
+//      Extent == dynamic_extent || Extent == OtherExtent is true, and
+//      OtherElementType(*)[] is convertible to ElementType(*)[].
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+void checkCV ()
+{
+//  std::span<               int>   sp;
+    std::span<const          int>  csp;
+    std::span<      volatile int>  vsp;
+    std::span<const volatile int> cvsp;
+
+//  std::span<               int, 0>   sp0;
+    std::span<const          int, 0>  csp0;
+    std::span<      volatile int, 0>  vsp0;
+    std::span<const volatile int, 0> cvsp0;
+
+//  Try to remove const and/or volatile (dynamic -> dynamic)
+    {
+    std::span<               int> s1{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s2{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s3{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+
+    std::span<const          int> s4{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+    std::span<const          int> s5{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+
+    std::span<      volatile int> s6{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    std::span<      volatile int> s7{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    }
+
+//  Try to remove const and/or volatile (static -> static)
+    {
+    std::span<               int, 0> s1{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    std::span<               int, 0> s2{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    std::span<               int, 0> s3{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+
+    std::span<const          int, 0> s4{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}}
+    std::span<const          int, 0> s5{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}}
+
+    std::span<      volatile int, 0> s6{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}}
+    std::span<      volatile int, 0> s7{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}}
+    }
+
+//  Try to remove const and/or volatile (static -> dynamic)
+    {
+    std::span<               int> s1{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s2{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s3{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+
+    std::span<const          int> s4{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+    std::span<const          int> s5{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+
+    std::span<      volatile int> s6{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    std::span<      volatile int> s7{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    }
+
+//  Try to remove const and/or volatile (static -> static)
+    {
+    std::span<               int, 0> s1{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    std::span<               int, 0> s2{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+    std::span<               int, 0> s3{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}}
+
+    std::span<const          int, 0> s4{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}}
+    std::span<const          int, 0> s5{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}}
+
+    std::span<      volatile int, 0> s6{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}}
+    std::span<      volatile int, 0> s7{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}}
+    }
+}
+
+int main ()
+{
+    std::span<int>      sp;
+    std::span<int, 0>   sp0;
+
+    std::span<float> s1{sp};    // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
+    std::span<float> s2{sp0};   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
+    std::span<float, 0> s3{sp}; // expected-error {{no matching constructor for initialization of 'std::span<float, 0>'}}
+    std::span<float, 0> s4{sp0};    // expected-error {{no matching constructor for initialization of 'std::span<float, 0>'}}
+    
+    checkCV();
+}
diff --git a/libcxx/test/std/containers/views/span.cons/span.pass.cpp b/libcxx/test/std/containers/views/span.cons/span.pass.cpp
new file mode 100644 (file)
index 0000000..b2024ce
--- /dev/null
@@ -0,0 +1,142 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<class OtherElementType, ptrdiff_t OtherExtent>
+//    constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept;
+//
+//  Remarks: This constructor shall not participate in overload resolution unless:
+//      Extent == dynamic_extent || Extent == OtherExtent is true, and
+//      OtherElementType(*)[] is convertible to ElementType(*)[].
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+void checkCV()
+{
+    std::span<               int>   sp;
+//  std::span<const          int>  csp;
+    std::span<      volatile int>  vsp;
+//  std::span<const volatile int> cvsp;
+
+    std::span<               int, 0>   sp0;
+//  std::span<const          int, 0>  csp0;
+    std::span<      volatile int, 0>  vsp0;
+//  std::span<const volatile int, 0> cvsp0;
+
+//  dynamic -> dynamic
+    {
+        std::span<const          int> s1{  sp}; // a span<const          int> pointing at int.
+        std::span<      volatile int> s2{  sp}; // a span<      volatile int> pointing at int.
+        std::span<const volatile int> s3{  sp}; // a span<const volatile int> pointing at int.
+        std::span<const volatile int> s4{ vsp}; // a span<const volatile int> pointing at volatile int.
+        assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
+    }
+
+//  static -> static
+    {
+        std::span<const          int, 0> s1{  sp0}; // a span<const          int> pointing at int.
+        std::span<      volatile int, 0> s2{  sp0}; // a span<      volatile int> pointing at int.
+        std::span<const volatile int, 0> s3{  sp0}; // a span<const volatile int> pointing at int.
+        std::span<const volatile int, 0> s4{ vsp0}; // a span<const volatile int> pointing at volatile int.
+        assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
+    }
+
+//  static -> dynamic
+    {
+        std::span<const          int> s1{  sp0};    // a span<const          int> pointing at int.
+        std::span<      volatile int> s2{  sp0};    // a span<      volatile int> pointing at int.
+        std::span<const volatile int> s3{  sp0};    // a span<const volatile int> pointing at int.
+        std::span<const volatile int> s4{ vsp0};    // a span<const volatile int> pointing at volatile int.
+        assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
+    }
+
+//  dynamic -> static
+    {
+        std::span<const          int, 0> s1{  sp};  // a span<const          int> pointing at int.
+        std::span<      volatile int, 0> s2{  sp};  // a span<      volatile int> pointing at int.
+        std::span<const volatile int, 0> s3{  sp};  // a span<const volatile int> pointing at int.
+        std::span<const volatile int, 0> s4{ vsp};  // a span<const volatile int> pointing at volatile int.
+        assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
+    }
+}
+
+
+template <typename T>
+constexpr bool testConstexprSpan()
+{
+    std::span<T>    s0{};
+    std::span<T, 0> s1(s0); // dynamic -> static
+    std::span<T>    s2(s1); // static -> dynamic
+    ASSERT_NOEXCEPT(std::span<T>   {s0});
+    ASSERT_NOEXCEPT(std::span<T, 0>{s1});
+    ASSERT_NOEXCEPT(std::span<T>   {s1});
+    ASSERT_NOEXCEPT(std::span<T, 0>{s0});
+
+    return
+        s1.data() == nullptr && s1.size() == 0
+    &&  s2.data() == nullptr && s2.size() == 0;
+}
+
+
+template <typename T>
+void testRuntimeSpan()
+{
+    std::span<T>    s0{};
+    std::span<T, 0> s1(s0); // dynamic -> static
+    std::span<T>    s2(s1); // static -> dynamic
+    ASSERT_NOEXCEPT(std::span<T>   {s0});
+    ASSERT_NOEXCEPT(std::span<T, 0>{s1});
+    ASSERT_NOEXCEPT(std::span<T>   {s1});
+    ASSERT_NOEXCEPT(std::span<T, 0>{s0});
+
+    assert(s1.data() == nullptr && s1.size() == 0);
+    assert(s2.data() == nullptr && s2.size() == 0);
+}
+
+
+template <typename Dest, typename Src>
+bool testConversionSpan()
+{
+    static_assert(std::is_convertible_v<Src(*)[], Dest(*)[]>, "Bad input types to 'testConversionSpan");
+    std::span<Src>    s0d{};
+    std::span<Src>    s0s{};
+    std::span<Dest, 0> s1(s0d); // dynamic -> static
+    std::span<Dest>    s2(s0s); // static -> dynamic
+        s1.data() == nullptr && s1.size() == 0
+    &&  s2.data() == nullptr && s2.size() == 0;
+}
+
+struct A{};
+
+int main ()
+{
+    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>();
+
+//  TODO: Add some conversion tests here that aren't "X --> const X"
+//  assert((testConversionSpan<unsigned char, char>()));
+
+    checkCV();
+}
diff --git a/libcxx/test/std/containers/views/span.cons/stdarray.pass.cpp b/libcxx/test/std/containers/views/span.cons/stdarray.pass.cpp
new file mode 100644 (file)
index 0000000..204935d
--- /dev/null
@@ -0,0 +1,111 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// 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;  
+//
+// Remarks: These constructors shall not participate in overload resolution unless:
+//   â€” extent == dynamic_extent || N == extent is true, and
+//   â€” remove_pointer_t<decltype(data(arr))>(*)[] is convertible to ElementType(*)[].
+//
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+
+void checkCV()
+{
+    std::array<int, 3> arr  = {1,2,3};
+//  STL says these are not cromulent
+//  std::array<const int,3> carr = {4,5,6};
+//  std::array<volatile int, 3> varr = {7,8,9};
+//  std::array<const volatile int, 3> cvarr = {1,3,5};
+
+//  Types the same (dynamic sized)
+    {
+    std::span<               int> s1{  arr};    // a span<               int> pointing at int.
+    }
+
+//  Types the same (static sized)
+    {
+    std::span<               int,3> s1{  arr};  // a span<               int> pointing at int.
+    }
+
+
+//  types different (dynamic sized)
+    {
+    std::span<const          int> s1{ arr};     // a span<const          int> pointing at int.
+    std::span<      volatile int> s2{ arr};     // a span<      volatile int> pointing at int.
+    std::span<      volatile int> s3{ arr};     // a span<      volatile int> pointing at const int.
+    std::span<const volatile int> s4{ arr};     // a span<const volatile int> pointing at int.
+    }
+
+//  types different (static sized)
+    {
+    std::span<const          int,3> s1{ arr};   // a span<const          int> pointing at int.
+    std::span<      volatile int,3> s2{ arr};   // a span<      volatile int> pointing at int.
+    std::span<      volatile int,3> s3{ arr};   // a span<      volatile int> pointing at const int.
+    std::span<const volatile int,3> s4{ arr};   // a span<const volatile int> pointing at int.
+    }
+}
+
+
+template <typename T>
+constexpr bool testConstexprSpan()
+{
+    constexpr std::array<T,2> val = { T(), T() };
+    ASSERT_NOEXCEPT(std::span<const T>   {val});
+    ASSERT_NOEXCEPT(std::span<const T, 2>{val});
+    std::span<const T>    s1{val};
+    std::span<const T, 2> s2{val};
+    return
+        s1.data() == &val[0] && s1.size() == 2
+    &&  s2.data() == &val[0] && s2.size() == 2;
+}
+
+
+template <typename T>
+void testRuntimeSpan()
+{
+    std::array<T,2> val;
+    ASSERT_NOEXCEPT(std::span<T>   {val});
+    ASSERT_NOEXCEPT(std::span<T, 2>{val});
+    std::span<T>    s1{val};
+    std::span<T, 2> s2{val};
+    assert(s1.data() == &val[0] && s1.size() == 2);
+    assert(s2.data() == &val[0] && s2.size() == 2);
+}
+
+struct A{};
+
+int main ()
+{
+    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();
+}
diff --git a/libcxx/test/std/containers/views/span.elem/data.pass.cpp b/libcxx/test/std/containers/views/span.elem/data.pass.cpp
new file mode 100644 (file)
index 0000000..3bc6fbb
--- /dev/null
@@ -0,0 +1,121 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr pointer data() const noexcept;
+//
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+
+template <typename Span>
+constexpr bool testConstexprSpan(Span sp, typename Span::pointer ptr)
+{
+    ASSERT_NOEXCEPT(sp.data());
+    return sp.data() == ptr;
+}
+
+
+template <typename Span>
+void testRuntimeSpan(Span sp, typename Span::pointer ptr)
+{
+    ASSERT_NOEXCEPT(sp.data());
+    assert(sp.data() == ptr);
+}
+
+struct A{};
+constexpr int iArr1[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+          int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+int main ()
+{
+
+//  dynamic size
+    static_assert(testConstexprSpan(std::span<int>(), nullptr),         "");
+    static_assert(testConstexprSpan(std::span<long>(), nullptr),        "");
+    static_assert(testConstexprSpan(std::span<double>(), nullptr),      "");
+    static_assert(testConstexprSpan(std::span<A>(), nullptr),           "");
+    static_assert(testConstexprSpan(std::span<std::string>(), nullptr), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), iArr1), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), iArr1), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), iArr1), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), iArr1), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1 + 1, 1), iArr1 + 1), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1 + 2, 2), iArr1 + 2), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1 + 3, 3), iArr1 + 3), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1 + 4, 4), iArr1 + 4), "");
+
+//  static size
+    static_assert(testConstexprSpan(std::span<int, 0>(), nullptr),         "");
+    static_assert(testConstexprSpan(std::span<long, 0>(), nullptr),        "");
+    static_assert(testConstexprSpan(std::span<double, 0>(), nullptr),      "");
+    static_assert(testConstexprSpan(std::span<A, 0>(), nullptr),           "");
+    static_assert(testConstexprSpan(std::span<std::string, 0>(), nullptr), "");
+
+    static_assert(testConstexprSpan(std::span<const int, 1>(iArr1, 1), iArr1), "");
+    static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), iArr1), "");
+    static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), iArr1), "");
+    static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), iArr1), "");
+
+    static_assert(testConstexprSpan(std::span<const int, 1>(iArr1 + 1, 1), iArr1 + 1), "");
+    static_assert(testConstexprSpan(std::span<const int, 2>(iArr1 + 2, 2), iArr1 + 2), "");
+    static_assert(testConstexprSpan(std::span<const int, 3>(iArr1 + 3, 3), iArr1 + 3), "");
+    static_assert(testConstexprSpan(std::span<const int, 4>(iArr1 + 4, 4), iArr1 + 4), "");
+
+
+//  dynamic size
+    testRuntimeSpan(std::span<int>(), nullptr);
+    testRuntimeSpan(std::span<long>(), nullptr);
+    testRuntimeSpan(std::span<double>(), nullptr);
+    testRuntimeSpan(std::span<A>(), nullptr);
+    testRuntimeSpan(std::span<std::string>(), nullptr);
+
+    testRuntimeSpan(std::span<int>(iArr2, 1), iArr2);
+    testRuntimeSpan(std::span<int>(iArr2, 2), iArr2);
+    testRuntimeSpan(std::span<int>(iArr2, 3), iArr2);
+    testRuntimeSpan(std::span<int>(iArr2, 4), iArr2);
+
+    testRuntimeSpan(std::span<int>(iArr2 + 1, 1), iArr2 + 1);
+    testRuntimeSpan(std::span<int>(iArr2 + 2, 2), iArr2 + 2);
+    testRuntimeSpan(std::span<int>(iArr2 + 3, 3), iArr2 + 3);
+    testRuntimeSpan(std::span<int>(iArr2 + 4, 4), iArr2 + 4);
+
+//  static size
+    testRuntimeSpan(std::span<int, 0>(), nullptr);
+    testRuntimeSpan(std::span<long, 0>(), nullptr);
+    testRuntimeSpan(std::span<double, 0>(), nullptr);
+    testRuntimeSpan(std::span<A, 0>(), nullptr);
+    testRuntimeSpan(std::span<std::string, 0>(), nullptr);
+
+    testRuntimeSpan(std::span<int, 1>(iArr2, 1), iArr2);
+    testRuntimeSpan(std::span<int, 2>(iArr2, 2), iArr2);
+    testRuntimeSpan(std::span<int, 3>(iArr2, 3), iArr2);
+    testRuntimeSpan(std::span<int, 4>(iArr2, 4), iArr2);
+
+    testRuntimeSpan(std::span<int, 1>(iArr2 + 1, 1), iArr2 + 1);
+    testRuntimeSpan(std::span<int, 2>(iArr2 + 2, 2), iArr2 + 2);
+    testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3), iArr2 + 3);
+    testRuntimeSpan(std::span<int, 4>(iArr2 + 4, 4), iArr2 + 4);
+
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>(&s, 1), &s);
+    testRuntimeSpan(std::span<std::string, 1>(&s, 1), &s);
+
+}
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
new file mode 100644 (file)
index 0000000..a88f441
--- /dev/null
@@ -0,0 +1,119 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr reference operator[](index_type idx) const;
+// constexpr reference operator()(index_type idx) const;
+//
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+
+template <typename Span>
+constexpr bool testConstexprSpan(Span sp, ptrdiff_t idx)
+{
+    _LIBCPP_ASSERT(noexcept(sp[idx]), "");
+    _LIBCPP_ASSERT(noexcept(sp(idx)), "");
+    
+    typename Span::reference r1 = sp[idx];
+    typename Span::reference r2 = sp(idx);
+    typename Span::reference r3 = *(sp.data() + idx);
+    return r1 == r2 && r2 == r3;
+}
+
+
+template <typename Span>
+void testRuntimeSpan(Span sp, ptrdiff_t idx)
+{
+    _LIBCPP_ASSERT(noexcept(sp[idx]), "");
+    _LIBCPP_ASSERT(noexcept(sp(idx)), "");
+    
+    typename Span::reference r1 = sp[idx];
+    typename Span::reference r2 = sp(idx);
+    typename Span::reference r3 = *(sp.data() + idx);
+    assert(r1 == r2 && r2 == r3);
+}
+
+struct A{};
+constexpr int iArr1[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+          int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+int main ()
+{
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), 0), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 0), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 1), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 0), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 1), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 2), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 0), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 1), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 2), "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 3), "");
+
+
+    static_assert(testConstexprSpan(std::span<const int, 1>(iArr1, 1), 0), "");
+
+    static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), 0), "");
+    static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), 1), "");
+
+    static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 0), "");
+    static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 1), "");
+    static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 2), "");
+
+    static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 0), "");
+    static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 1), "");
+    static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 2), "");
+    static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 3), "");
+
+
+    testRuntimeSpan(std::span<int>(iArr2, 1), 0);
+
+    testRuntimeSpan(std::span<int>(iArr2, 2), 0);
+    testRuntimeSpan(std::span<int>(iArr2, 2), 1);
+
+    testRuntimeSpan(std::span<int>(iArr2, 3), 0);
+    testRuntimeSpan(std::span<int>(iArr2, 3), 1);
+    testRuntimeSpan(std::span<int>(iArr2, 3), 2);
+
+    testRuntimeSpan(std::span<int>(iArr2, 4), 0);
+    testRuntimeSpan(std::span<int>(iArr2, 4), 1);
+    testRuntimeSpan(std::span<int>(iArr2, 4), 2);
+    testRuntimeSpan(std::span<int>(iArr2, 4), 3);
+
+
+    testRuntimeSpan(std::span<int, 1>(iArr2, 1), 0);
+
+    testRuntimeSpan(std::span<int, 2>(iArr2, 2), 0);
+    testRuntimeSpan(std::span<int, 2>(iArr2, 2), 1);
+
+    testRuntimeSpan(std::span<int, 3>(iArr2, 3), 0);
+    testRuntimeSpan(std::span<int, 3>(iArr2, 3), 1);
+    testRuntimeSpan(std::span<int, 3>(iArr2, 3), 2);
+
+    testRuntimeSpan(std::span<int, 4>(iArr2, 4), 0);
+    testRuntimeSpan(std::span<int, 4>(iArr2, 4), 1);
+    testRuntimeSpan(std::span<int, 4>(iArr2, 4), 2);
+    testRuntimeSpan(std::span<int, 4>(iArr2, 4), 3);
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>   (&s, 1), 0);
+    testRuntimeSpan(std::span<std::string, 1>(&s, 1), 0);
+}
diff --git a/libcxx/test/std/containers/views/span.iterators/begin.pass.cpp b/libcxx/test/std/containers/views/span.iterators/begin.pass.cpp
new file mode 100644 (file)
index 0000000..c8b9900
--- /dev/null
@@ -0,0 +1,116 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr       iterator  begin() const noexcept;
+// constexpr const_iterator cbegin() const noexcept;
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+template <class Span>
+constexpr bool testConstexprSpan(Span s)
+{
+    bool ret = true;
+    typename Span::iterator b        = s. begin();
+    typename Span::const_iterator cb = s.cbegin();
+
+    if (s.empty())
+    {
+        ret = ret &&  ( b ==  s.end());
+        ret = ret &&  (cb == s.cend());
+    }
+    else
+    {
+        ret = ret &&  (  *b ==  s[0]);
+        ret = ret &&  ( &*b == &s[0]);
+        ret = ret &&  ( *cb ==  s[0]);
+        ret = ret &&  (&*cb == &s[0]);
+    }
+    ret = ret && (b == cb);
+    return ret;
+}
+
+
+template <class Span>
+void testRuntimeSpan(Span s)
+{
+    typename Span::iterator b        = s. begin();
+    typename Span::const_iterator cb = s.cbegin();
+
+    if (s.empty())
+    {
+        assert( b ==  s.end());
+        assert(cb == s.cend());
+    }
+    else
+    {
+        assert(  *b ==  s[0]);
+        assert( &*b == &s[0]);
+        assert( *cb ==  s[0]);
+        assert(&*cb == &s[0]);
+    }
+    assert(b == cb);
+}
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr int iArr1[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+          int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+
+int main()
+{
+    static_assert(testConstexprSpan(std::span<int>()),            "");
+    static_assert(testConstexprSpan(std::span<long>()),           "");
+    static_assert(testConstexprSpan(std::span<double>()),         "");
+    static_assert(testConstexprSpan(std::span<A>()),              "");
+    static_assert(testConstexprSpan(std::span<std::string>()),    "");
+
+    static_assert(testConstexprSpan(std::span<int, 0>()),         "");
+    static_assert(testConstexprSpan(std::span<long, 0>()),        "");
+    static_assert(testConstexprSpan(std::span<double, 0>()),      "");
+    static_assert(testConstexprSpan(std::span<A, 0>()),           "");
+    static_assert(testConstexprSpan(std::span<std::string, 0>()), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 1)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 2)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 5)),    "");
+
+
+    testRuntimeSpan(std::span<int>        ());
+    testRuntimeSpan(std::span<long>       ());
+    testRuntimeSpan(std::span<double>     ());
+    testRuntimeSpan(std::span<A>          ());
+    testRuntimeSpan(std::span<std::string>());
+
+    testRuntimeSpan(std::span<int, 0>        ());
+    testRuntimeSpan(std::span<long, 0>       ());
+    testRuntimeSpan(std::span<double, 0>     ());
+    testRuntimeSpan(std::span<A, 0>          ());
+    testRuntimeSpan(std::span<std::string, 0>());
+
+    testRuntimeSpan(std::span<int>(iArr2, 1));
+    testRuntimeSpan(std::span<int>(iArr2, 2));
+    testRuntimeSpan(std::span<int>(iArr2, 3));
+    testRuntimeSpan(std::span<int>(iArr2, 4));
+    testRuntimeSpan(std::span<int>(iArr2, 5));
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0));
+    testRuntimeSpan(std::span<std::string>(&s, 1));
+}
diff --git a/libcxx/test/std/containers/views/span.iterators/end.pass.cpp b/libcxx/test/std/containers/views/span.iterators/end.pass.cpp
new file mode 100644 (file)
index 0000000..2b64b0f
--- /dev/null
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr       iterator  end() const noexcept;
+// constexpr const_iterator cend() const noexcept;
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+template <class Span>
+constexpr bool testConstexprSpan(Span s)
+{
+    bool ret = true;
+    typename Span::iterator e        = s. end();
+    typename Span::const_iterator ce = s.cend();
+    if (s.empty())
+    {
+        ret = ret &&  ( e ==  s.begin());
+        ret = ret &&  (ce == s.cbegin());
+    }
+    else
+    {
+        ret = ret &&  ( e !=  s.begin());
+        ret = ret &&  (ce != s.cbegin());
+    }
+
+    ret = ret &&  (( e -  s.begin()) == s.size());
+    ret = ret &&  ((ce - s.cbegin()) == s.size());
+
+    ret = ret &&  (e == ce);
+    return ret;
+}
+
+template <class Span>
+void testRuntimeSpan(Span s)
+{
+    typename Span::iterator e        = s. end();
+    typename Span::const_iterator ce = s.cend();
+    if (s.empty())
+    {
+        assert( e ==  s.begin());
+        assert(ce == s.cbegin());
+    }
+    else
+    {
+        assert( e !=  s.begin());
+        assert(ce != s.cbegin());
+    }
+
+    assert(( e -  s.begin()) == s.size());
+    assert((ce - s.cbegin()) == s.size());
+
+    assert(e == ce);
+}
+
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr int iArr1[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+          int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+
+int main()
+{
+    static_assert(testConstexprSpan(std::span<int>()),            "");
+    static_assert(testConstexprSpan(std::span<long>()),           "");
+    static_assert(testConstexprSpan(std::span<double>()),         "");
+    static_assert(testConstexprSpan(std::span<A>()),              "");
+    static_assert(testConstexprSpan(std::span<std::string>()),    "");
+
+    static_assert(testConstexprSpan(std::span<int, 0>()),         "");
+    static_assert(testConstexprSpan(std::span<long, 0>()),        "");
+    static_assert(testConstexprSpan(std::span<double, 0>()),      "");
+    static_assert(testConstexprSpan(std::span<A, 0>()),           "");
+    static_assert(testConstexprSpan(std::span<std::string, 0>()), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 1)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 2)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 5)),    "");
+
+
+    testRuntimeSpan(std::span<int>        ());
+    testRuntimeSpan(std::span<long>       ());
+    testRuntimeSpan(std::span<double>     ());
+    testRuntimeSpan(std::span<A>          ());
+    testRuntimeSpan(std::span<std::string>());
+
+    testRuntimeSpan(std::span<int, 0>        ());
+    testRuntimeSpan(std::span<long, 0>       ());
+    testRuntimeSpan(std::span<double, 0>     ());
+    testRuntimeSpan(std::span<A, 0>          ());
+    testRuntimeSpan(std::span<std::string, 0>());
+
+    testRuntimeSpan(std::span<int>(iArr2, 1));
+    testRuntimeSpan(std::span<int>(iArr2, 2));
+    testRuntimeSpan(std::span<int>(iArr2, 3));
+    testRuntimeSpan(std::span<int>(iArr2, 4));
+    testRuntimeSpan(std::span<int>(iArr2, 5));
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0));
+    testRuntimeSpan(std::span<std::string>(&s, 1));
+}
diff --git a/libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp b/libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp
new file mode 100644 (file)
index 0000000..c0776c0
--- /dev/null
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr       reverse_iterator  rbegin() const noexcept;
+// constexpr const_reverse_iterator crbegin() const noexcept;
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+template <class Span>
+constexpr bool testConstexprSpan(Span s)
+{
+    bool ret = true;
+    typename Span::reverse_iterator b        = s. rbegin();
+    typename Span::const_reverse_iterator cb = s.crbegin();
+    if (s.empty())
+    {
+        ret = ret &&  ( b ==  s.rend());
+        ret = ret &&  (cb == s.crend());
+    }
+    else
+    {
+        const typename Span::index_type last = s.size() - 1;
+        ret = ret &&  (  *b ==  s[last]);
+        ret = ret &&  ( &*b == &s[last]);
+        ret = ret &&  ( *cb ==  s[last]);
+        ret = ret &&  (&*cb == &s[last]);
+    }
+    ret = ret &&  (b == cb);
+    return ret;
+}
+
+
+template <class Span>
+void testRuntimeSpan(Span s)
+{
+    typename Span::reverse_iterator b        = s. rbegin();
+    typename Span::const_reverse_iterator cb = s.crbegin();
+    if (s.empty())
+    {
+        assert( b ==  s.rend());
+        assert(cb == s.crend());
+    }
+    else
+    {
+        const typename Span::index_type last = s.size() - 1;
+        assert(  *b ==  s[last]);
+        assert( &*b == &s[last]);
+        assert( *cb ==  s[last]);
+        assert(&*cb == &s[last]);
+    }
+    assert(b == cb);
+}
+
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr int iArr1[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+          int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+
+int main()
+{
+    static_assert(testConstexprSpan(std::span<int>()),            "");
+    static_assert(testConstexprSpan(std::span<long>()),           "");
+    static_assert(testConstexprSpan(std::span<double>()),         "");
+    static_assert(testConstexprSpan(std::span<A>()),              "");
+    static_assert(testConstexprSpan(std::span<std::string>()),    "");
+
+    static_assert(testConstexprSpan(std::span<int, 0>()),         "");
+    static_assert(testConstexprSpan(std::span<long, 0>()),        "");
+    static_assert(testConstexprSpan(std::span<double, 0>()),      "");
+    static_assert(testConstexprSpan(std::span<A, 0>()),           "");
+    static_assert(testConstexprSpan(std::span<std::string, 0>()), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 1)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 2)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 5)),    "");
+
+
+    testRuntimeSpan(std::span<int>        ());
+    testRuntimeSpan(std::span<long>       ());
+    testRuntimeSpan(std::span<double>     ());
+    testRuntimeSpan(std::span<A>          ());
+    testRuntimeSpan(std::span<std::string>());
+
+    testRuntimeSpan(std::span<int, 0>        ());
+    testRuntimeSpan(std::span<long, 0>       ());
+    testRuntimeSpan(std::span<double, 0>     ());
+    testRuntimeSpan(std::span<A, 0>          ());
+    testRuntimeSpan(std::span<std::string, 0>());
+
+    testRuntimeSpan(std::span<int>(iArr2, 1));
+    testRuntimeSpan(std::span<int>(iArr2, 2));
+    testRuntimeSpan(std::span<int>(iArr2, 3));
+    testRuntimeSpan(std::span<int>(iArr2, 4));
+    testRuntimeSpan(std::span<int>(iArr2, 5));
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>(&s, static_cast<std::ptrdiff_t>(0)));
+    testRuntimeSpan(std::span<std::string>(&s, 1));
+}
diff --git a/libcxx/test/std/containers/views/span.iterators/rend.pass.cpp b/libcxx/test/std/containers/views/span.iterators/rend.pass.cpp
new file mode 100644 (file)
index 0000000..abcead4
--- /dev/null
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr       reverse_iterator  rend() const noexcept;
+// constexpr const_reverse_iterator crend() const noexcept;
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+template <class Span>
+constexpr bool testConstexprSpan(Span s)
+{
+    bool ret = true;
+    typename Span::reverse_iterator e        = s. rend();
+    typename Span::const_reverse_iterator ce = s.crend();
+    if (s.empty())
+    {
+        ret = ret &&  ( e ==  s.rbegin());
+        ret = ret &&  (ce == s.crbegin());
+    }
+    else
+    {
+        ret = ret &&  ( e !=  s.rbegin());
+        ret = ret &&  (ce != s.crbegin());
+    }
+
+    ret = ret &&  (( e -  s.rbegin()) == s.size());
+    ret = ret &&  ((ce - s.crbegin()) == s.size());
+
+    ret = ret &&  (e == ce);
+    return ret;
+}
+
+template <class Span>
+void testRuntimeSpan(Span s)
+{
+    typename Span::reverse_iterator e        = s. rend();
+    typename Span::const_reverse_iterator ce = s.crend();
+    if (s.empty())
+    {
+        assert( e ==  s.rbegin());
+        assert(ce == s.crbegin());
+    }
+    else
+    {
+        assert( e !=  s.rbegin());
+        assert(ce != s.crbegin());
+    }
+
+    assert(( e -  s.rbegin()) == s.size());
+    assert((ce - s.crbegin()) == s.size());
+
+    assert(e == ce);
+}
+
+
+struct A{};
+bool operator==(A, A) {return true;}
+
+constexpr int iArr1[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+          int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+
+int main()
+{
+    static_assert(testConstexprSpan(std::span<int>()),            "");
+    static_assert(testConstexprSpan(std::span<long>()),           "");
+    static_assert(testConstexprSpan(std::span<double>()),         "");
+    static_assert(testConstexprSpan(std::span<A>()),              "");
+    static_assert(testConstexprSpan(std::span<std::string>()),    "");
+
+    static_assert(testConstexprSpan(std::span<int, 0>()),         "");
+    static_assert(testConstexprSpan(std::span<long, 0>()),        "");
+    static_assert(testConstexprSpan(std::span<double, 0>()),      "");
+    static_assert(testConstexprSpan(std::span<A, 0>()),           "");
+    static_assert(testConstexprSpan(std::span<std::string, 0>()), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 1)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 2)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4)),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 5)),    "");
+
+
+    testRuntimeSpan(std::span<int>        ());
+    testRuntimeSpan(std::span<long>       ());
+    testRuntimeSpan(std::span<double>     ());
+    testRuntimeSpan(std::span<A>          ());
+    testRuntimeSpan(std::span<std::string>());
+
+    testRuntimeSpan(std::span<int, 0>        ());
+    testRuntimeSpan(std::span<long, 0>       ());
+    testRuntimeSpan(std::span<double, 0>     ());
+    testRuntimeSpan(std::span<A, 0>          ());
+    testRuntimeSpan(std::span<std::string, 0>());
+
+    testRuntimeSpan(std::span<int>(iArr2, 1));
+    testRuntimeSpan(std::span<int>(iArr2, 2));
+    testRuntimeSpan(std::span<int>(iArr2, 3));
+    testRuntimeSpan(std::span<int>(iArr2, 4));
+    testRuntimeSpan(std::span<int>(iArr2, 5));
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0));
+    testRuntimeSpan(std::span<std::string>(&s, 1));
+}
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
new file mode 100644 (file)
index 0000000..b081b95
--- /dev/null
@@ -0,0 +1,78 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template <class ElementType, ptrdiff_t Extent>
+//     span<const byte,
+//          Extent == dynamic_extent
+//              ? dynamic_extent
+//              : static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent>
+//     as_bytes(span<ElementType, Extent> s) noexcept;
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+template<typename Span>
+void testRuntimeSpan(Span sp)
+{
+    ASSERT_NOEXCEPT(std::as_bytes(sp));
+
+    auto spBytes = std::as_bytes(sp);
+    using SB = decltype(spBytes);
+    ASSERT_SAME_TYPE(const std::byte, typename SB::element_type);
+
+    if (sp.extent == std::dynamic_extent)
+        assert(spBytes.extent == std::dynamic_extent);
+    else
+        assert(spBytes.extent == static_cast<std::ptrdiff_t>(sizeof(typename Span::element_type)) * sp.extent);
+        
+    assert((void *) spBytes.data() == (void *) sp.data());
+    assert(spBytes.size() == sp.size_bytes());
+}
+
+struct A{};
+int iArr2[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+
+int main ()
+{
+    testRuntimeSpan(std::span<int>        ());
+    testRuntimeSpan(std::span<long>       ());
+    testRuntimeSpan(std::span<double>     ());
+    testRuntimeSpan(std::span<A>          ());
+    testRuntimeSpan(std::span<std::string>());
+
+    testRuntimeSpan(std::span<int, 0>        ());
+    testRuntimeSpan(std::span<long, 0>       ());
+    testRuntimeSpan(std::span<double, 0>     ());
+    testRuntimeSpan(std::span<A, 0>          ());
+    testRuntimeSpan(std::span<std::string, 0>());
+
+    testRuntimeSpan(std::span<int>(iArr2, 1));
+    testRuntimeSpan(std::span<int>(iArr2, 2));
+    testRuntimeSpan(std::span<int>(iArr2, 3));
+    testRuntimeSpan(std::span<int>(iArr2, 4));
+    testRuntimeSpan(std::span<int>(iArr2, 5));
+
+    testRuntimeSpan(std::span<int, 1>(iArr2 + 5, 1));
+    testRuntimeSpan(std::span<int, 2>(iArr2 + 4, 2));
+    testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3));
+    testRuntimeSpan(std::span<int, 4>(iArr2 + 2, 4));
+    testRuntimeSpan(std::span<int, 5>(iArr2 + 1, 5));
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0));
+    testRuntimeSpan(std::span<std::string>(&s, 1));
+}
diff --git a/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp b/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp
new file mode 100644 (file)
index 0000000..28a4c45
--- /dev/null
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template <class ElementType, ptrdiff_t Extent>
+//     span<byte,
+//          Extent == dynamic_extent
+//              ? dynamic_extent
+//              : static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent>
+//     as_writeable_bytes(span<ElementType, Extent> s) noexcept;
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+const int iArr2[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+
+struct A {};
+
+int main ()
+{
+    std::as_writeable_bytes(std::span<const int>());            // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+    std::as_writeable_bytes(std::span<const long>());           // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+    std::as_writeable_bytes(std::span<const double>());         // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+    std::as_writeable_bytes(std::span<const A>());              // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+    std::as_writeable_bytes(std::span<const std::string>());    // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+
+    std::as_writeable_bytes(std::span<const int, 0>());         // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+    std::as_writeable_bytes(std::span<const long, 0>());        // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+    std::as_writeable_bytes(std::span<const double, 0>());      // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+    std::as_writeable_bytes(std::span<const A, 0>());           // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+    std::as_writeable_bytes(std::span<const std::string, 0>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+
+    std::as_writeable_bytes(std::span<const int>   (iArr2, 1));     // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+    std::as_writeable_bytes(std::span<const int, 1>(iArr2 + 5, 1)); // expected-error {{no matching function for call to 'as_writeable_bytes'}}
+}
diff --git a/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp b/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp
new file mode 100644 (file)
index 0000000..24e3fb2
--- /dev/null
@@ -0,0 +1,78 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template <class ElementType, ptrdiff_t Extent>
+//     span<byte,
+//          Extent == dynamic_extent
+//              ? dynamic_extent
+//              : static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent>
+//     as_writeable_bytes(span<ElementType, Extent> s) noexcept;
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+template<typename Span>
+void testRuntimeSpan(Span sp)
+{
+    ASSERT_NOEXCEPT(std::as_writeable_bytes(sp));
+
+    auto spBytes = std::as_writeable_bytes(sp);
+    using SB = decltype(spBytes);
+    ASSERT_SAME_TYPE(std::byte, typename SB::element_type);
+
+    if (sp.extent == std::dynamic_extent)
+        assert(spBytes.extent == std::dynamic_extent);
+    else
+        assert(spBytes.extent == static_cast<std::ptrdiff_t>(sizeof(typename Span::element_type)) * sp.extent);
+        
+    assert(static_cast<void*>(spBytes.data()) == static_cast<void*>(sp.data()));
+    assert(spBytes.size() == sp.size_bytes());
+}
+
+struct A{};
+int iArr2[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+
+int main ()
+{
+    testRuntimeSpan(std::span<int>        ());
+    testRuntimeSpan(std::span<long>       ());
+    testRuntimeSpan(std::span<double>     ());
+    testRuntimeSpan(std::span<A>          ());
+    testRuntimeSpan(std::span<std::string>());
+
+    testRuntimeSpan(std::span<int, 0>        ());
+    testRuntimeSpan(std::span<long, 0>       ());
+    testRuntimeSpan(std::span<double, 0>     ());
+    testRuntimeSpan(std::span<A, 0>          ());
+    testRuntimeSpan(std::span<std::string, 0>());
+
+    testRuntimeSpan(std::span<int>(iArr2, 1));
+    testRuntimeSpan(std::span<int>(iArr2, 2));
+    testRuntimeSpan(std::span<int>(iArr2, 3));
+    testRuntimeSpan(std::span<int>(iArr2, 4));
+    testRuntimeSpan(std::span<int>(iArr2, 5));
+
+    testRuntimeSpan(std::span<int, 1>(iArr2 + 5, 1));
+    testRuntimeSpan(std::span<int, 2>(iArr2 + 4, 2));
+    testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3));
+    testRuntimeSpan(std::span<int, 4>(iArr2 + 2, 4));
+    testRuntimeSpan(std::span<int, 5>(iArr2 + 1, 5));
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0));
+    testRuntimeSpan(std::span<std::string>(&s, 1));
+}
diff --git a/libcxx/test/std/containers/views/span.obs/empty.pass.cpp b/libcxx/test/std/containers/views/span.obs/empty.pass.cpp
new file mode 100644 (file)
index 0000000..a48c0d0
--- /dev/null
@@ -0,0 +1,73 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr bool empty() const noexcept;
+//
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+struct A{};
+constexpr int iArr1[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+          int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+int main ()
+{
+    static_assert( noexcept(std::span<int>   ().empty()), "");
+    static_assert( noexcept(std::span<int, 0>().empty()), "");
+
+
+    static_assert( std::span<int>().empty(),            "");
+    static_assert( std::span<long>().empty(),           "");
+    static_assert( std::span<double>().empty(),         "");
+    static_assert( std::span<A>().empty(),              "");
+    static_assert( std::span<std::string>().empty(),    "");
+
+    static_assert( std::span<int, 0>().empty(),         "");
+    static_assert( std::span<long, 0>().empty(),        "");
+    static_assert( std::span<double, 0>().empty(),      "");
+    static_assert( std::span<A, 0>().empty(),           "");
+    static_assert( std::span<std::string, 0>().empty(), "");
+
+    static_assert(!std::span<const int>(iArr1, 1).empty(), "");
+    static_assert(!std::span<const int>(iArr1, 2).empty(), "");
+    static_assert(!std::span<const int>(iArr1, 3).empty(), "");
+    static_assert(!std::span<const int>(iArr1, 4).empty(), "");
+    static_assert(!std::span<const int>(iArr1, 5).empty(), "");
+    
+    assert( (std::span<int>().empty()           ));
+    assert( (std::span<long>().empty()          ));
+    assert( (std::span<double>().empty()        ));
+    assert( (std::span<A>().empty()             ));
+    assert( (std::span<std::string>().empty()   ));
+
+    assert( (std::span<int, 0>().empty()        ));
+    assert( (std::span<long, 0>().empty()       ));
+    assert( (std::span<double, 0>().empty()     ));
+    assert( (std::span<A, 0>().empty()          ));
+    assert( (std::span<std::string, 0>().empty()));
+
+    assert(!(std::span<int, 1>(iArr2, 1).empty()));
+    assert(!(std::span<int, 2>(iArr2, 2).empty()));
+    assert(!(std::span<int, 3>(iArr2, 3).empty()));
+    assert(!(std::span<int, 4>(iArr2, 4).empty()));
+    assert(!(std::span<int, 5>(iArr2, 5).empty()));
+
+    std::string s;
+    assert( ((std::span<std::string>(&s, (std::ptrdiff_t) 0)).empty()));
+    assert(!((std::span<std::string>(&s, 1).empty())));
+}
diff --git a/libcxx/test/std/containers/views/span.obs/size.pass.cpp b/libcxx/test/std/containers/views/span.obs/size.pass.cpp
new file mode 100644 (file)
index 0000000..c33fd3f
--- /dev/null
@@ -0,0 +1,91 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr index_type size() const noexcept;
+//
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+
+template <typename Span>
+constexpr bool testConstexprSpan(Span sp, ptrdiff_t sz)
+{
+    ASSERT_NOEXCEPT(sp.size());
+    return sp.size() == sz;
+}
+
+
+template <typename Span>
+void testRuntimeSpan(Span sp, ptrdiff_t sz)
+{
+    ASSERT_NOEXCEPT(sp.size());
+    assert(sp.size() == sz);
+}
+
+struct A{};
+constexpr int iArr1[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+          int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+int main ()
+{
+    static_assert(testConstexprSpan(std::span<int>(), 0),            "");
+    static_assert(testConstexprSpan(std::span<long>(), 0),           "");
+    static_assert(testConstexprSpan(std::span<double>(), 0),         "");
+    static_assert(testConstexprSpan(std::span<A>(), 0),              "");
+    static_assert(testConstexprSpan(std::span<std::string>(), 0),    "");
+
+    static_assert(testConstexprSpan(std::span<int, 0>(), 0),         "");
+    static_assert(testConstexprSpan(std::span<long, 0>(), 0),        "");
+    static_assert(testConstexprSpan(std::span<double, 0>(), 0),      "");
+    static_assert(testConstexprSpan(std::span<A, 0>(), 0),           "");
+    static_assert(testConstexprSpan(std::span<std::string, 0>(), 0), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), 1),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 2),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 3),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 4),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 5), 5),    "");
+
+    testRuntimeSpan(std::span<int>        (), 0);
+    testRuntimeSpan(std::span<long>       (), 0);
+    testRuntimeSpan(std::span<double>     (), 0);
+    testRuntimeSpan(std::span<A>          (), 0);
+    testRuntimeSpan(std::span<std::string>(), 0);
+
+    testRuntimeSpan(std::span<int, 0>        (), 0);
+    testRuntimeSpan(std::span<long, 0>       (), 0);
+    testRuntimeSpan(std::span<double, 0>     (), 0);
+    testRuntimeSpan(std::span<A, 0>          (), 0);
+    testRuntimeSpan(std::span<std::string, 0>(), 0);
+
+    testRuntimeSpan(std::span<int>(iArr2, 1), 1);
+    testRuntimeSpan(std::span<int>(iArr2, 2), 2);
+    testRuntimeSpan(std::span<int>(iArr2, 3), 3);
+    testRuntimeSpan(std::span<int>(iArr2, 4), 4);
+    testRuntimeSpan(std::span<int>(iArr2, 5), 5);
+
+    testRuntimeSpan(std::span<int, 1>(iArr2 + 5, 1), 1);
+    testRuntimeSpan(std::span<int, 2>(iArr2 + 4, 2), 2);
+    testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3), 3);
+    testRuntimeSpan(std::span<int, 4>(iArr2 + 2, 4), 4);
+    testRuntimeSpan(std::span<int, 5>(iArr2 + 1, 5), 5);
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0), 0);
+    testRuntimeSpan(std::span<std::string>(&s, 1), 1);
+}
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
new file mode 100644 (file)
index 0000000..1ee75d9
--- /dev/null
@@ -0,0 +1,92 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// constexpr index_type size_bytes() const noexcept;
+//
+//  Effects: Equivalent to: return size() * sizeof(element_type);
+
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+
+template <typename Span>
+constexpr bool testConstexprSpan(Span sp, ptrdiff_t sz)
+{
+    ASSERT_NOEXCEPT(sp.size_bytes());
+    return (size_t) sp.size_bytes() == sz * sizeof(typename Span::element_type);
+}
+
+
+template <typename Span>
+void testRuntimeSpan(Span sp, ptrdiff_t sz)
+{
+    ASSERT_NOEXCEPT(sp.size_bytes());
+    assert((size_t) sp.size_bytes() == sz * sizeof(typename Span::element_type));
+}
+
+struct A{};
+constexpr int iArr1[] = { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9};
+          int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
+
+int main ()
+{
+    static_assert(testConstexprSpan(std::span<int>(), 0),            "");
+    static_assert(testConstexprSpan(std::span<long>(), 0),           "");
+    static_assert(testConstexprSpan(std::span<double>(), 0),         "");
+    static_assert(testConstexprSpan(std::span<A>(), 0),              "");
+    static_assert(testConstexprSpan(std::span<std::string>(), 0),    "");
+
+    static_assert(testConstexprSpan(std::span<int, 0>(), 0),         "");
+    static_assert(testConstexprSpan(std::span<long, 0>(), 0),        "");
+    static_assert(testConstexprSpan(std::span<double, 0>(), 0),      "");
+    static_assert(testConstexprSpan(std::span<A, 0>(), 0),           "");
+    static_assert(testConstexprSpan(std::span<std::string, 0>(), 0), "");
+
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), 1),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 2),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 3),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 4),    "");
+    static_assert(testConstexprSpan(std::span<const int>(iArr1, 5), 5),    "");
+
+    testRuntimeSpan(std::span<int>        (), 0);
+    testRuntimeSpan(std::span<long>       (), 0);
+    testRuntimeSpan(std::span<double>     (), 0);
+    testRuntimeSpan(std::span<A>          (), 0);
+    testRuntimeSpan(std::span<std::string>(), 0);
+
+    testRuntimeSpan(std::span<int, 0>        (), 0);
+    testRuntimeSpan(std::span<long, 0>       (), 0);
+    testRuntimeSpan(std::span<double, 0>     (), 0);
+    testRuntimeSpan(std::span<A, 0>          (), 0);
+    testRuntimeSpan(std::span<std::string, 0>(), 0);
+
+    testRuntimeSpan(std::span<int>(iArr2, 1), 1);
+    testRuntimeSpan(std::span<int>(iArr2, 2), 2);
+    testRuntimeSpan(std::span<int>(iArr2, 3), 3);
+    testRuntimeSpan(std::span<int>(iArr2, 4), 4);
+    testRuntimeSpan(std::span<int>(iArr2, 5), 5);
+
+    testRuntimeSpan(std::span<int, 1>(iArr2 + 5, 1), 1);
+    testRuntimeSpan(std::span<int, 2>(iArr2 + 4, 2), 2);
+    testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3), 3);
+    testRuntimeSpan(std::span<int, 4>(iArr2 + 2, 4), 4);
+    testRuntimeSpan(std::span<int, 5>(iArr2 + 1, 5), 5);
+
+    std::string s;
+    testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0), 0);
+    testRuntimeSpan(std::span<std::string>(&s, 1), 1);
+}
diff --git a/libcxx/test/std/containers/views/span.sub/first.pass.cpp b/libcxx/test/std/containers/views/span.sub/first.pass.cpp
new file mode 100644 (file)
index 0000000..3bfdab9
--- /dev/null
@@ -0,0 +1,136 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<ptrdiff_t Count>
+//  constexpr span<element_type, Count> first() const;
+//
+// constexpr span<element_type, dynamic_extent> first(index_type count) const;
+//
+//  Requires: 0 <= Count && Count <= size().
+
+
+#include <span>
+#include <cassert>
+#include <algorithm>
+#include <string>
+
+#include "test_macros.h"
+
+template <typename Span, ptrdiff_t Count>
+constexpr bool testConstexprSpan(Span sp)
+{
+    LIBCPP_ASSERT((noexcept(sp.template first<Count>())));
+    LIBCPP_ASSERT((noexcept(sp.first(Count))));
+    auto s1 = sp.template first<Count>();
+    auto s2 = sp.first(Count);
+    using S1 = decltype(s1);
+    using S2 = decltype(s2);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
+    static_assert(S1::extent == Count, "");
+    static_assert(S2::extent == std::dynamic_extent, "");
+    return
+        s1.data() == s2.data()
+     && s1.size() == s2.size()
+     && std::equal(s1.begin(), s1.end(), sp.begin());
+}
+
+
+template <typename Span, ptrdiff_t Count>
+void testRuntimeSpan(Span sp)
+{
+    LIBCPP_ASSERT((noexcept(sp.template first<Count>())));
+    LIBCPP_ASSERT((noexcept(sp.first(Count))));
+    auto s1 = sp.template first<Count>();
+    auto s2 = sp.first(Count);
+    using S1 = decltype(s1);
+    using S2 = decltype(s2);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
+    static_assert(S1::extent == Count, "");
+    static_assert(S2::extent == std::dynamic_extent, "");
+    assert(s1.data() == s2.data());
+    assert(s1.size() == s2.size());
+    assert(std::equal(s1.begin(), s1.end(), sp.begin()));
+}
+
+
+constexpr int carr1[] = {1,2,3,4};
+          int   arr[] = {5,6,7};
+std::string   sarr [] = { "ABC", "DEF", "GHI", "JKL", "MNO"};
+
+int main ()
+{
+    {
+    using Sp = std::span<const int>;
+    static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
+
+    static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
+    }
+
+    {
+    using Sp = std::span<const int, 4>;
+
+    static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
+    }
+
+    {
+    using Sp = std::span<int>;
+    testRuntimeSpan<Sp, 0>(Sp{});
+
+    testRuntimeSpan<Sp, 0>(Sp{arr});
+    testRuntimeSpan<Sp, 1>(Sp{arr});
+    testRuntimeSpan<Sp, 2>(Sp{arr});
+    testRuntimeSpan<Sp, 3>(Sp{arr});
+    }
+
+    {
+    using Sp = std::span<int, 3>;
+
+    testRuntimeSpan<Sp, 0>(Sp{arr});
+    testRuntimeSpan<Sp, 1>(Sp{arr});
+    testRuntimeSpan<Sp, 2>(Sp{arr});
+    testRuntimeSpan<Sp, 3>(Sp{arr});
+    }
+
+    {
+    using Sp = std::span<std::string>;
+    testConstexprSpan<Sp, 0>(Sp{});
+    
+    testRuntimeSpan<Sp, 0>(Sp{sarr});
+    testRuntimeSpan<Sp, 1>(Sp{sarr});
+    testRuntimeSpan<Sp, 2>(Sp{sarr});
+    testRuntimeSpan<Sp, 3>(Sp{sarr});
+    testRuntimeSpan<Sp, 4>(Sp{sarr});
+    testRuntimeSpan<Sp, 5>(Sp{sarr});
+    }
+
+    {
+    using Sp = std::span<std::string, 5>;
+    
+    testRuntimeSpan<Sp, 0>(Sp{sarr});
+    testRuntimeSpan<Sp, 1>(Sp{sarr});
+    testRuntimeSpan<Sp, 2>(Sp{sarr});
+    testRuntimeSpan<Sp, 3>(Sp{sarr});
+    testRuntimeSpan<Sp, 4>(Sp{sarr});
+    testRuntimeSpan<Sp, 5>(Sp{sarr});
+    }
+}
diff --git a/libcxx/test/std/containers/views/span.sub/last.pass.cpp b/libcxx/test/std/containers/views/span.sub/last.pass.cpp
new file mode 100644 (file)
index 0000000..4e378fe
--- /dev/null
@@ -0,0 +1,136 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<ptrdiff_t Count>
+//  constexpr span<element_type, Count> last() const;
+//
+// constexpr span<element_type, dynamic_extent> last(index_type count) const;
+//
+//  Requires: 0 <= Count && Count <= size().
+
+
+#include <span>
+#include <cassert>
+#include <algorithm>
+#include <string>
+
+#include "test_macros.h"
+
+template <typename Span, ptrdiff_t Count>
+constexpr bool testConstexprSpan(Span sp)
+{
+    LIBCPP_ASSERT((noexcept(sp.template last<Count>())));
+    LIBCPP_ASSERT((noexcept(sp.last(Count))));
+    auto s1 = sp.template last<Count>();
+    auto s2 = sp.last(Count);
+    using S1 = decltype(s1);
+    using S2 = decltype(s2);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
+    static_assert(S1::extent == Count, "");
+    static_assert(S2::extent == std::dynamic_extent, "");
+    return
+        s1.data() == s2.data()
+     && s1.size() == s2.size()
+     && std::equal(s1.begin(), s1.end(), sp.end() - Count);
+}
+
+
+template <typename Span, ptrdiff_t Count>
+void testRuntimeSpan(Span sp)
+{
+    LIBCPP_ASSERT((noexcept(sp.template last<Count>())));
+    LIBCPP_ASSERT((noexcept(sp.last(Count))));
+    auto s1 = sp.template last<Count>();
+    auto s2 = sp.last(Count);
+    using S1 = decltype(s1);
+    using S2 = decltype(s2);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
+    static_assert(S1::extent == Count, "");
+    static_assert(S2::extent == std::dynamic_extent, "");
+    assert(s1.data() == s2.data());
+    assert(s1.size() == s2.size());
+    assert(std::equal(s1.begin(), s1.end(), sp.end() - Count));
+}
+
+
+constexpr int carr1[] = {1,2,3,4};
+          int   arr[] = {5,6,7};
+std::string   sarr [] = { "ABC", "DEF", "GHI", "JKL", "MNO"};
+
+int main ()
+{
+    {
+    using Sp = std::span<const int>;
+    static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
+
+    static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
+    }
+
+    {
+    using Sp = std::span<const int, 4>;
+
+    static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
+    }
+
+    {
+    using Sp = std::span<int>;
+    testRuntimeSpan<Sp, 0>(Sp{});
+
+    testRuntimeSpan<Sp, 0>(Sp{arr});
+    testRuntimeSpan<Sp, 1>(Sp{arr});
+    testRuntimeSpan<Sp, 2>(Sp{arr});
+    testRuntimeSpan<Sp, 3>(Sp{arr});
+    }
+
+    {
+    using Sp = std::span<int, 3>;
+
+    testRuntimeSpan<Sp, 0>(Sp{arr});
+    testRuntimeSpan<Sp, 1>(Sp{arr});
+    testRuntimeSpan<Sp, 2>(Sp{arr});
+    testRuntimeSpan<Sp, 3>(Sp{arr});
+    }
+
+    {
+    using Sp = std::span<std::string>;
+    testConstexprSpan<Sp, 0>(Sp{});
+    
+    testRuntimeSpan<Sp, 0>(Sp{sarr});
+    testRuntimeSpan<Sp, 1>(Sp{sarr});
+    testRuntimeSpan<Sp, 2>(Sp{sarr});
+    testRuntimeSpan<Sp, 3>(Sp{sarr});
+    testRuntimeSpan<Sp, 4>(Sp{sarr});
+    testRuntimeSpan<Sp, 5>(Sp{sarr});
+    }
+
+    {
+    using Sp = std::span<std::string, 5>;
+    
+    testRuntimeSpan<Sp, 0>(Sp{sarr});
+    testRuntimeSpan<Sp, 1>(Sp{sarr});
+    testRuntimeSpan<Sp, 2>(Sp{sarr});
+    testRuntimeSpan<Sp, 3>(Sp{sarr});
+    testRuntimeSpan<Sp, 4>(Sp{sarr});
+    testRuntimeSpan<Sp, 5>(Sp{sarr});
+    }
+}
diff --git a/libcxx/test/std/containers/views/span.sub/subspan.pass.cpp b/libcxx/test/std/containers/views/span.sub/subspan.pass.cpp
new file mode 100644 (file)
index 0000000..79cdc7b
--- /dev/null
@@ -0,0 +1,210 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
+//   constexpr span<element_type, see below> subspan() const;
+//
+// constexpr span<element_type, dynamic_extent> subspan(
+//   index_type offset, index_type count = dynamic_extent) const;
+//
+//  Requires: (0 <= Offset && Offset <= size())
+//      && (Count == dynamic_extent || Count >= 0 && Offset + Count <= size())
+
+#include <span>
+#include <cassert>
+#include <algorithm>
+#include <string>
+
+#include "test_macros.h"
+
+template <typename Span, ptrdiff_t Offset, ptrdiff_t Count>
+constexpr bool testConstexprSpan(Span sp)
+{
+    LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>())));
+    LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count))));
+    auto s1 = sp.template subspan<Offset, Count>();
+    auto s2 = sp.subspan(Offset, Count);
+    using S1 = decltype(s1);
+    using S2 = decltype(s2);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
+    static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Count), "");
+    static_assert(S2::extent == std::dynamic_extent, "");
+    return
+        s1.data() == s2.data()
+     && s1.size() == s2.size()
+     && std::equal(s1.begin(), s1.end(), sp.begin() + Offset);
+}
+
+template <typename Span, ptrdiff_t Offset>
+constexpr bool testConstexprSpan(Span sp)
+{
+    LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>())));
+    LIBCPP_ASSERT((noexcept(sp.subspan(Offset))));
+    auto s1 = sp.template subspan<Offset>();
+    auto s2 = sp.subspan(Offset);
+    using S1 = decltype(s1);
+    using S2 = decltype(s2);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
+    static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), "");
+    static_assert(S2::extent == std::dynamic_extent, "");
+    return
+        s1.data() == s2.data()
+     && s1.size() == s2.size()
+     && std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end());
+}
+
+
+template <typename Span, ptrdiff_t Offset, ptrdiff_t Count>
+void testRuntimeSpan(Span sp)
+{
+    LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>())));
+    LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count))));
+    auto s1 = sp.template subspan<Offset, Count>();
+    auto s2 = sp.subspan(Offset, Count);
+    using S1 = decltype(s1);
+    using S2 = decltype(s2);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
+    static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Count), "");
+    static_assert(S2::extent == std::dynamic_extent, "");
+    assert(s1.data() == s2.data());
+    assert(s1.size() == s2.size());
+    assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset));
+}
+
+
+template <typename Span, ptrdiff_t Offset>
+void testRuntimeSpan(Span sp)
+{
+    LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>())));
+    LIBCPP_ASSERT((noexcept(sp.subspan(Offset))));
+    auto s1 = sp.template subspan<Offset>();
+    auto s2 = sp.subspan(Offset);
+    using S1 = decltype(s1);
+    using S2 = decltype(s2);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
+    ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
+    static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), "");
+    static_assert(S2::extent == std::dynamic_extent, "");
+    assert(s1.data() == s2.data());
+    assert(s1.size() == s2.size());
+    assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end()));
+}
+
+
+constexpr int carr1[] = {1,2,3,4};
+          int  arr1[] = {5,6,7};
+
+int main ()
+{
+    {
+    using Sp = std::span<const int>;
+    static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
+
+    static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), "");
+
+    static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), "");
+    }
+
+    {
+    using Sp = std::span<const int, 4>;
+
+    static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), "");
+
+    static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), "");
+    }
+
+    {
+    using Sp = std::span<const int>;
+    static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
+
+    static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
+    }
+
+    {
+    using Sp = std::span<const int, 4>;
+
+    static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
+
+    static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
+    static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
+    }
+
+    {
+    using Sp = std::span<int>;
+    testRuntimeSpan<Sp, 0>(Sp{});
+
+    testRuntimeSpan<Sp, 0, 3>(Sp{arr1});
+    testRuntimeSpan<Sp, 0, 2>(Sp{arr1});
+    testRuntimeSpan<Sp, 0, 1>(Sp{arr1});
+    testRuntimeSpan<Sp, 0, 0>(Sp{arr1});
+
+    testRuntimeSpan<Sp, 1, 2>(Sp{arr1});
+    testRuntimeSpan<Sp, 2, 1>(Sp{arr1});
+    testRuntimeSpan<Sp, 3, 0>(Sp{arr1});
+    }
+
+    {
+    using Sp = std::span<int, 3>;
+
+    testRuntimeSpan<Sp, 0, 3>(Sp{arr1});
+    testRuntimeSpan<Sp, 0, 2>(Sp{arr1});
+    testRuntimeSpan<Sp, 0, 1>(Sp{arr1});
+    testRuntimeSpan<Sp, 0, 0>(Sp{arr1});
+
+    testRuntimeSpan<Sp, 1, 2>(Sp{arr1});
+    testRuntimeSpan<Sp, 2, 1>(Sp{arr1});
+    testRuntimeSpan<Sp, 3, 0>(Sp{arr1});
+    }
+
+    {
+    using Sp = std::span<int>;
+    testRuntimeSpan<Sp, 0>(Sp{});
+
+    testRuntimeSpan<Sp, 0>(Sp{arr1});
+    testRuntimeSpan<Sp, 1>(Sp{arr1});
+    testRuntimeSpan<Sp, 2>(Sp{arr1});
+    testRuntimeSpan<Sp, 3>(Sp{arr1});
+    }
+
+    {
+    using Sp = std::span<int, 3>;
+
+    testRuntimeSpan<Sp, 0>(Sp{arr1});
+    testRuntimeSpan<Sp, 1>(Sp{arr1});
+    testRuntimeSpan<Sp, 2>(Sp{arr1});
+    testRuntimeSpan<Sp, 3>(Sp{arr1});
+    }
+}
diff --git a/libcxx/test/std/containers/views/types.pass.cpp b/libcxx/test/std/containers/views/types.pass.cpp
new file mode 100644 (file)
index 0000000..082abeb
--- /dev/null
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+//===------------------------------ span ---------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 
+
+// <span>
+
+// template<class ElementType, ptrdiff_t Extent = dynamic_extent>
+// class span {
+// public:
+//  // constants and types
+//  using element_type           = ElementType;
+//  using value_type             = remove_cv_t<ElementType>;
+//  using index_type             = ptrdiff_t;
+//  using difference_type        = ptrdiff_t;
+//  using pointer                = element_type *;
+//  using reference              = element_type &;
+//  using iterator               = implementation-defined;
+//  using const_iterator         = implementation-defined;
+//  using reverse_iterator       = std::reverse_iterator<iterator>;
+//  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+// 
+//  static constexpr index_type extent = Extent;
+// 
+
+#include <span>
+#include <cassert>
+#include <iterator>
+#include <string>
+
+#include "test_macros.h"
+
+template <typename S, typename Iter>
+void testIterator()
+{
+    typedef std::iterator_traits<Iter> ItT;
+
+    ASSERT_SAME_TYPE(typename ItT::iterator_category, std::random_access_iterator_tag);
+    ASSERT_SAME_TYPE(typename ItT::value_type,        typename S::value_type);
+    ASSERT_SAME_TYPE(typename ItT::reference,         typename S::reference);
+    ASSERT_SAME_TYPE(typename ItT::pointer,           typename S::pointer);
+    ASSERT_SAME_TYPE(typename ItT::difference_type,   typename S::difference_type);
+}
+
+template <typename S, typename Iter>
+void testConstIterator()
+{
+    typedef std::iterator_traits<Iter> ItT;
+
+    ASSERT_SAME_TYPE(typename ItT::iterator_category, std::random_access_iterator_tag);
+    ASSERT_SAME_TYPE(typename ItT::value_type,        typename S::value_type);
+//  I'd like to say 'const typename S::pointer' here, but that gives me
+//      a const pointer to a non-const value, which is not what I want.
+    ASSERT_SAME_TYPE(typename ItT::reference,         typename S::element_type const &);
+    ASSERT_SAME_TYPE(typename ItT::pointer,           typename S::element_type const *);
+    ASSERT_SAME_TYPE(typename ItT::difference_type,   typename S::difference_type);
+}
+
+template <typename S, typename ElementType, std::ptrdiff_t Size>
+void testSpan()
+{
+    ASSERT_SAME_TYPE(typename S::element_type,    ElementType);
+    ASSERT_SAME_TYPE(typename S::value_type,      std::remove_cv_t<ElementType>);
+    ASSERT_SAME_TYPE(typename S::index_type,      std::ptrdiff_t);
+    ASSERT_SAME_TYPE(typename S::difference_type, std::ptrdiff_t);
+    ASSERT_SAME_TYPE(typename S::pointer,         ElementType *);
+    ASSERT_SAME_TYPE(typename S::reference,       ElementType &);
+    
+    static_assert(S::extent == Size); // check that it exists
+
+    testIterator<S, typename S::iterator>();
+    testIterator<S, typename S::reverse_iterator>();
+    testConstIterator<S, typename S::const_iterator>();
+    testConstIterator<S, typename S::const_reverse_iterator>();
+}
+
+
+template <typename T>
+void test()
+{
+    testSpan<std::span<               T>,                T, -1>();
+    testSpan<std::span<const          T>, const          T, -1>();
+    testSpan<std::span<      volatile T>,       volatile T, -1>();
+    testSpan<std::span<const volatile T>, const volatile T, -1>();
+
+    testSpan<std::span<               T, 5>,                T, 5>();
+    testSpan<std::span<const          T, 5>, const          T, 5>();
+    testSpan<std::span<      volatile T, 5>,       volatile T, 5>();
+    testSpan<std::span<const volatile T, 5>, const volatile T, 5>();
+}
+
+struct A{};
+
+int main ()
+{
+    test<int>();
+    test<long>();
+    test<double>();
+    test<std::string>();
+    test<A>();
+}