remove the unsued abi fixes

This commit is contained in:
Sylvestre Ledru 2022-04-27 08:37:36 +02:00
parent 99fd399a04
commit 8e451fe3b3
2 changed files with 0 additions and 468 deletions

View File

@ -1,390 +0,0 @@
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

View File

@ -1,78 +0,0 @@
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