From 3f786648773a5ce334604d7a400505fc97196226 Mon Sep 17 00:00:00 2001
From: Sedat Dilek <sedat.dilek@gmail.com>
Date: Wed, 30 Mar 2022 18:03:22 +0200
Subject: [PATCH] Add libc++ patches from upstream (post version 14.0.0)

Details see Debian bug #1008657
("clang-14: Integrate post v14.0.0 upstream patches")

Link: https://bugs.debian.org/1008657
Signed-off-by: Sedat Dilek <sedat.dilek@gmail.com>
---
 ...und-to-avoid-breaking-users-of-span-.patch | 390 ++++++++++++++++++
 ...orkaround-for-pre-ranges-CTAD-in-std.patch |  78 ++++
 debian/patches/series                         |   4 +
 3 files changed, 472 insertions(+)
 create mode 100644 debian/patches/0001-libc-Add-workaround-to-avoid-breaking-users-of-span-.patch
 create mode 100644 debian/patches/0002-libc-Re-enable-workaround-for-pre-ranges-CTAD-in-std.patch

diff --git a/debian/patches/0001-libc-Add-workaround-to-avoid-breaking-users-of-span-.patch b/debian/patches/0001-libc-Add-workaround-to-avoid-breaking-users-of-span-.patch
new file mode 100644
index 000000000000..e59a56057fb2
--- /dev/null
+++ b/debian/patches/0001-libc-Add-workaround-to-avoid-breaking-users-of-span-.patch
@@ -0,0 +1,390 @@
+From add3ab7f4c8a7f25c2940889d397cbdc9f267666 Mon Sep 17 00:00:00 2001
+From: Louis Dionne <ldionne.2@gmail.com>
+Date: Mon, 14 Mar 2022 11:50:02 -0400
+Subject: [PATCH] [libc++] Add workaround to avoid breaking users of <span>
+ when <ranges> are disabled
+
+Back in 3a208c68942e, we implemented the range-based constructor for <span>.
+However, in doing so, we removed a previous non-standard constructor that
+we provided before shipping <ranges>. Unfortunately, that breaks code that
+was relying on a range-based constructor until we ship all of <ranges>.
+
+This patch reintroduces the old non-conforming constructors and tests
+that were removed in 3a208c68942e and uses them whenever <ranges> is
+not provided (e.g. in LLVM 14). This is only a temporary workaround
+until we enable <ranges> by default in C++20, which should hopefully
+happen by LLVM 15.
+
+The goal is to cherry-pick this workaround back to the LLVM 14 release
+branch, since I suspect the constructor removal may otherwise cause
+breakage out there, like the breakage I saw internally.
+
+We could have avoided this situation by waiting for C++20 to be finalized
+before shipping std::span. For example, we could have guarded it with
+something like _LIBCPP_HAS_NO_INCOMPLETE_RANGES to prevent users from
+accidentally starting to depend on it before it is stable. We did not
+have these mechanisms when std::span was first implemented, though.
+
+NOTE: This is a pretty modified version of d4c39f1ab94 since that one
+didn't apply properly onto the release/14.x branch.
+
+(cherry picked from commit d4c39f1ab94abc1dd4fff1e82dd4fa97265940e1)
+
+Differential Revision: https://reviews.llvm.org/D121739
+---
+ libcxx/include/span                           |  50 ++++++-
+ .../containers/views/span.cons/range.pass.cpp | 141 ++++++++++++++++++
+ .../views/span.cons/range.verify.cpp          | 118 +++++++++++++++
+ 3 files changed, 306 insertions(+), 3 deletions(-)
+ create mode 100644 libcxx/test/libcxx/containers/views/span.cons/range.pass.cpp
+ create mode 100644 libcxx/test/libcxx/containers/views/span.cons/range.verify.cpp
+
+diff --git a/libcxx/include/span b/libcxx/include/span
+index fd95ecca17f7..b8dbc7e01fd6 100644
+--- a/libcxx/include/span
++++ b/libcxx/include/span
+@@ -170,7 +170,25 @@ struct __is_std_span : false_type {};
+ template <class _Tp, size_t _Sz>
+ struct __is_std_span<span<_Tp, _Sz>> : true_type {};
+ 
+-#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
++#if defined(_LIBCPP_HAS_NO_CONCEPTS) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
++// This is a temporary workaround until we ship <ranges> -- we've unfortunately been
++// shipping <span> before its API was finalized, and we used to provide a constructor
++// from container types that had the requirements below. To avoid breaking code that
++// has started relying on the range-based constructor until we ship all of <ranges>,
++// we emulate the constructor requirements like this.
++template <class _Range, class _ElementType, class = void>
++struct __span_compatible_range : false_type { };
++
++template <class _Range, class _ElementType>
++struct __span_compatible_range<_Range, _ElementType, void_t<
++    enable_if_t<!__is_std_span<remove_cvref_t<_Range>>::value>,
++    enable_if_t<!__is_std_array<remove_cvref_t<_Range>>::value>,
++    enable_if_t<!is_array_v<remove_cvref_t<_Range>>>,
++    decltype(data(declval<_Range>())),
++    decltype(size(declval<_Range>())),
++    enable_if_t<is_convertible_v<remove_pointer_t<decltype(data(declval<_Range&>()))>(*)[], _ElementType(*)[]>>
++>> : true_type { };
++#else
+ template <class _Range, class _ElementType>
+ concept __span_compatible_range =
+   ranges::contiguous_range<_Range> &&
+@@ -248,7 +266,22 @@ public:
+     _LIBCPP_INLINE_VISIBILITY
+     constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
+ 
+-#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
++#if defined(_LIBCPP_HAS_NO_CONCEPTS) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
++    template <class _Container, class = enable_if_t<
++        __span_compatible_range<_Container, element_type>::value
++    >>
++    _LIBCPP_INLINE_VISIBILITY
++    constexpr explicit span(_Container& __c) : __data{std::data(__c)} {
++      _LIBCPP_ASSERT(std::size(__c) == _Extent, "size mismatch in span's constructor (range)");
++    }
++    template <class _Container, class = enable_if_t<
++        __span_compatible_range<const _Container, element_type>::value
++    >>
++    _LIBCPP_INLINE_VISIBILITY
++    constexpr explicit span(const _Container& __c) : __data{std::data(__c)} {
++      _LIBCPP_ASSERT(std::size(__c) == _Extent, "size mismatch in span's constructor (range)");
++    }
++#else
+     template <__span_compatible_range<element_type> _Range>
+     _LIBCPP_INLINE_VISIBILITY
+     constexpr explicit span(_Range&& __r) : __data{ranges::data(__r)} {
+@@ -434,7 +467,18 @@ public:
+     _LIBCPP_INLINE_VISIBILITY
+     constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
+ 
+-#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
++#if defined(_LIBCPP_HAS_NO_CONCEPTS) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
++    template <class _Container, class = enable_if_t<
++        __span_compatible_range<_Container, element_type>::value
++    >>
++    _LIBCPP_INLINE_VISIBILITY
++    constexpr span(_Container& __c) : __data(std::data(__c)), __size{std::size(__c)} {}
++    template <class _Container, class = enable_if_t<
++        __span_compatible_range<const _Container, element_type>::value
++    >>
++    _LIBCPP_INLINE_VISIBILITY
++    constexpr span(const _Container& __c) : __data(std::data(__c)), __size{std::size(__c)} {}
++#else
+     template <__span_compatible_range<element_type> _Range>
+     _LIBCPP_INLINE_VISIBILITY
+     constexpr span(_Range&& __r) : __data(ranges::data(__r)), __size{ranges::size(__r)} {}
+diff --git a/libcxx/test/libcxx/containers/views/span.cons/range.pass.cpp b/libcxx/test/libcxx/containers/views/span.cons/range.pass.cpp
+new file mode 100644
+index 000000000000..efa1001bdb5b
+--- /dev/null
++++ b/libcxx/test/libcxx/containers/views/span.cons/range.pass.cpp
+@@ -0,0 +1,141 @@
++//===---------------------------------------------------------------------===//
++//
++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
++// See https://llvm.org/LICENSE.txt for license information.
++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
++//
++//===---------------------------------------------------------------------===//
++// UNSUPPORTED: c++03, c++11, c++14, c++17
++
++// <span>
++
++//  template<class Container>
++//    constexpr explicit(Extent != dynamic_extent) span(Container&);
++//  template<class Container>
++//    constexpr explicit(Extent != dynamic_extent) span(Container const&);
++
++// This test checks for libc++'s non-conforming temporary extension to std::span
++// to support construction from containers that look like contiguous ranges.
++//
++// This extension is only supported when we don't ship <ranges>, and we can
++// remove it once we get rid of _LIBCPP_HAS_NO_INCOMPLETE_RANGES.
++
++#include <span>
++#include <cassert>
++#include <string>
++#include <vector>
++
++#include "test_macros.h"
++
++//  Look ma - I'm a container!
++template <typename T>
++struct IsAContainer {
++    constexpr IsAContainer() : v_{} {}
++    constexpr size_t size() const {return 1;}
++    constexpr       T *data() {return &v_;}
++    constexpr const T *data() const {return &v_;}
++    constexpr       T *begin() {return &v_;}
++    constexpr const T *begin() const {return &v_;}
++    constexpr       T *end() {return &v_ + 1;}
++    constexpr const T *end() const {return &v_ + 1;}
++
++    constexpr T const *getV() const {return &v_;} // for checking
++    T v_;
++};
++
++
++void checkCV()
++{
++    std::vector<int> v  = {1,2,3};
++
++//  Types the same
++    {
++    std::span<               int> s1{v};    // a span<               int> pointing at int.
++    }
++
++//  types different
++    {
++    std::span<const          int> s1{v};    // a span<const          int> pointing at int.
++    std::span<      volatile int> s2{v};    // a span<      volatile int> pointing at int.
++    std::span<      volatile int> s3{v};    // a span<      volatile int> pointing at const int.
++    std::span<const volatile int> s4{v};    // a span<const volatile int> pointing at int.
++    }
++
++//  Constructing a const view from a temporary
++    {
++    std::span<const int>    s1{IsAContainer<int>()};
++    std::span<const int>    s3{std::vector<int>()};
++    (void) s1;
++    (void) s3;
++    }
++}
++
++
++template <typename T>
++constexpr bool testConstexprSpan()
++{
++    constexpr IsAContainer<const T> val{};
++    std::span<const T> s1{val};
++    return s1.data() == val.getV() && s1.size() == 1;
++}
++
++template <typename T>
++constexpr bool testConstexprSpanStatic()
++{
++    constexpr IsAContainer<const T> val{};
++    std::span<const T, 1> s1{val};
++    return s1.data() == val.getV() && s1.size() == 1;
++}
++
++template <typename T>
++void testRuntimeSpan()
++{
++    IsAContainer<T> val{};
++    const IsAContainer<T> cVal;
++    std::span<T>       s1{val};
++    std::span<const T> s2{cVal};
++    assert(s1.data() == val.getV()  && s1.size() == 1);
++    assert(s2.data() == cVal.getV() && s2.size() == 1);
++}
++
++template <typename T>
++void testRuntimeSpanStatic()
++{
++    IsAContainer<T> val{};
++    const IsAContainer<T> cVal;
++    std::span<T, 1>       s1{val};
++    std::span<const T, 1> s2{cVal};
++    assert(s1.data() == val.getV()  && s1.size() == 1);
++    assert(s2.data() == cVal.getV() && s2.size() == 1);
++}
++
++struct A{};
++
++int main(int, char**)
++{
++    static_assert(testConstexprSpan<int>(),    "");
++    static_assert(testConstexprSpan<long>(),   "");
++    static_assert(testConstexprSpan<double>(), "");
++    static_assert(testConstexprSpan<A>(),      "");
++
++    static_assert(testConstexprSpanStatic<int>(),    "");
++    static_assert(testConstexprSpanStatic<long>(),   "");
++    static_assert(testConstexprSpanStatic<double>(), "");
++    static_assert(testConstexprSpanStatic<A>(),      "");
++
++    testRuntimeSpan<int>();
++    testRuntimeSpan<long>();
++    testRuntimeSpan<double>();
++    testRuntimeSpan<std::string>();
++    testRuntimeSpan<A>();
++
++    testRuntimeSpanStatic<int>();
++    testRuntimeSpanStatic<long>();
++    testRuntimeSpanStatic<double>();
++    testRuntimeSpanStatic<std::string>();
++    testRuntimeSpanStatic<A>();
++
++    checkCV();
++
++    return 0;
++}
+diff --git a/libcxx/test/libcxx/containers/views/span.cons/range.verify.cpp b/libcxx/test/libcxx/containers/views/span.cons/range.verify.cpp
+new file mode 100644
+index 000000000000..f0edf4f93536
+--- /dev/null
++++ b/libcxx/test/libcxx/containers/views/span.cons/range.verify.cpp
+@@ -0,0 +1,118 @@
++//===---------------------------------------------------------------------===//
++//
++// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
++// See https://llvm.org/LICENSE.txt for license information.
++// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
++//
++//===---------------------------------------------------------------------===//
++// UNSUPPORTED: c++03, c++11, c++14, c++17
++
++// <span>
++
++//  template<class Container>
++//    constexpr explicit(Extent != dynamic_extent) span(Container&);
++//  template<class Container>
++//    constexpr explicit(Extent != dynamic_extent) span(Container const&);
++
++// This test checks for libc++'s non-conforming temporary extension to std::span
++// to support construction from containers that look like contiguous ranges.
++//
++// This extension is only supported when we don't ship <ranges>, and we can
++// remove it once we get rid of _LIBCPP_HAS_NO_INCOMPLETE_RANGES.
++
++#include <span>
++#include <cassert>
++#include <deque>
++#include <forward_list>
++#include <list>
++#include <vector>
++
++#include "test_macros.h"
++
++//  Look ma - I'm a container!
++template <typename T>
++struct IsAContainer {
++    constexpr IsAContainer() : v_{} {}
++    constexpr size_t size() const {return 1;}
++    constexpr       T *data() {return &v_;}
++    constexpr const T *data() const {return &v_;}
++
++    constexpr const T *getV() const {return &v_;} // for checking
++    T v_;
++};
++
++template <typename T>
++struct NotAContainerNoData {
++    size_t size() const {return 0;}
++};
++
++template <typename T>
++struct NotAContainerNoSize {
++    const T *data() const {return nullptr;}
++};
++
++template <typename T>
++struct NotAContainerPrivate {
++private:
++    size_t size() const {return 0;}
++    const T *data() const {return nullptr;}
++};
++
++template<class T, size_t extent, class container>
++std::span<T, extent> createImplicitSpan(container c) {
++    return {c}; // expected-error {{chosen constructor is explicit in copy-initialization}}
++}
++
++int main(int, char**)
++{
++
++//  Making non-const spans from const sources (a temporary binds to `const &`)
++    {
++    std::span<int>    s1{IsAContainer<int>()};          // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
++    std::span<int>    s3{std::vector<int>()};           // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
++    }
++
++//  Missing size and/or data
++    {
++    std::span<const int>    s1{NotAContainerNoData<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
++    std::span<const int>    s3{NotAContainerNoSize<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
++    std::span<const int>    s5{NotAContainerPrivate<int>()};  // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
++
++//  Again with the standard containers
++    std::span<const int>    s11{std::deque<int>()};           // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
++    std::span<const int>    s13{std::list<int>()};            // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
++    std::span<const int>    s15{std::forward_list<int>()};    // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
++    }
++
++//  Not the same type
++    {
++    IsAContainer<int> c;
++    std::span<float>    s1{c};   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
++    }
++
++//  CV wrong
++    {
++    IsAContainer<const          int> c;
++    IsAContainer<const volatile int> cv;
++    IsAContainer<      volatile int> v;
++
++    std::span<               int> s1{c};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
++    std::span<               int> s2{v};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
++    std::span<               int> s3{cv};   // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
++    std::span<const          int> s4{v};    // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
++    std::span<const          int> s5{cv};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
++    std::span<      volatile int> s6{c};    // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
++    std::span<      volatile int> s7{cv};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
++    }
++
++// explicit constructor necessary
++    {
++    IsAContainer<int> c;
++    const IsAContainer<int> cc;
++
++    createImplicitSpan<int, 1>(c);
++    createImplicitSpan<int, 1>(cc);
++    }
++
++    return 0;
++}
+-- 
+2.35.1
+
diff --git a/debian/patches/0002-libc-Re-enable-workaround-for-pre-ranges-CTAD-in-std.patch b/debian/patches/0002-libc-Re-enable-workaround-for-pre-ranges-CTAD-in-std.patch
new file mode 100644
index 000000000000..70666362239f
--- /dev/null
+++ b/debian/patches/0002-libc-Re-enable-workaround-for-pre-ranges-CTAD-in-std.patch
@@ -0,0 +1,78 @@
+From 3f43d803382d57e3fc010ca19833077d1023e9c9 Mon Sep 17 00:00:00 2001
+From: Louis Dionne <ldionne.2@gmail.com>
+Date: Mon, 21 Mar 2022 17:05:06 -0400
+Subject: [PATCH] [libc++] Re-enable workaround for pre-ranges CTAD in
+ std::span
+
+See https://reviews.llvm.org/D121626 for details -- this re-enables the
+CTAD we removed, since it does break some stuff as well (even though it's
+not nearly as bad as the removed constructors fixed by D121626).
+
+(cherry picked from commit 6a7f0551178e966a686dd48dfa2ea045a35addef)
+
+Differential Revision: https://reviews.llvm.org/D122201
+---
+ libcxx/include/span                                       | 8 +++++++-
+ .../test/std/containers/views/span.cons/deduct.pass.cpp   | 6 ------
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/libcxx/include/span b/libcxx/include/span
+index b8dbc7e01fd6..f33569031730 100644
+--- a/libcxx/include/span
++++ b/libcxx/include/span
+@@ -622,7 +622,13 @@ template<class _Tp, size_t _Sz>
+ template<class _Tp, size_t _Sz>
+     span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
+ 
+-#if !defined(_LIBCPP_HAS_NO_CONCEPTS) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
++#if defined(_LIBCPP_HAS_NO_CONCEPTS) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
++template<class _Container>
++    span(_Container&) -> span<typename _Container::value_type>;
++
++template<class _Container>
++    span(const _Container&) -> span<const typename _Container::value_type>;
++#else
+ template<ranges::contiguous_range _Range>
+     span(_Range&&) -> span<remove_reference_t<ranges::range_reference_t<_Range>>>;
+ #endif
+diff --git a/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp b/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
+index 81632fed711d..e632feca2e1f 100644
+--- a/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
++++ b/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
+@@ -6,7 +6,6 @@
+ //
+ //===----------------------------------------------------------------------===//
+ // UNSUPPORTED: c++03, c++11, c++14, c++17
+-// UNSUPPORTED: libcpp-no-concepts
+ 
+ // <span>
+ 
+@@ -86,7 +85,6 @@ void test_std_array() {
+     }
+ }
+ 
+-#ifndef _LIBCPP_HAS_NO_INCOMPLETE_RANGES
+ void test_range_std_container() {
+     {
+     std::string str{"ABCDE"};
+@@ -104,17 +102,13 @@ void test_range_std_container() {
+     assert(s.data() == str.data());
+     }
+ }
+-#endif // _LIBCPP_HAS_NO_INCOMPLETE_RANGES
+ 
+ int main(int, char**)
+ {
+   test_iterator_sentinel();
+   test_c_array();
+   test_std_array();
+-
+-#ifndef _LIBCPP_HAS_NO_INCOMPLETE_RANGES
+   test_range_std_container();
+-#endif // _LIBCPP_HAS_NO_INCOMPLETE_RANGES
+ 
+   return 0;
+ }
+-- 
+2.35.1
+
diff --git a/debian/patches/series b/debian/patches/series
index df956934bc21..fc005ac429df 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -150,3 +150,7 @@ wasm-ld-path.diff
 python3-scan-build.py
 revert-update-doc.diff
 fix-typo.diff
+
+# libc++ patches from upstream (post version 14.0.0)
+0001-libc-Add-workaround-to-avoid-breaking-users-of-span-.patch
+0002-libc-Re-enable-workaround-for-pre-ranges-CTAD-in-std.patch
-- 
2.35.1

