[libcxx-commits] [libcxx] 4163f61 - [libc++] [ranges] Fix a missing auto(x) cast in ranges::data.
Arthur O'Dwyer via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jan 12 15:18:23 PST 2022
Author: Arthur O'Dwyer
Date: 2022-01-12T18:16:15-05:00
New Revision: 4163f61f29f47d3e0d82cec2ba4cf8997d4b6820
URL: https://github.com/llvm/llvm-project/commit/4163f61f29f47d3e0d82cec2ba4cf8997d4b6820
DIFF: https://github.com/llvm/llvm-project/commit/4163f61f29f47d3e0d82cec2ba4cf8997d4b6820.diff
LOG: [libc++] [ranges] Fix a missing auto(x) cast in ranges::data.
Also remove some bogus `std::forward`s. My impression is that these
forwards were actually harmless, because `ranges::begin(FWD(t))` is
always identical to `ranges::begin(t)` (except when it's ill-formed,
and that can't happen in this case). However, they're also superfluous
and don't reflect the wording in the standard, so let's eliminate them.
Differential Revision: https://reviews.llvm.org/D117043
Added:
Modified:
libcxx/include/__ranges/data.h
libcxx/test/std/ranges/range.access/data.pass.cpp
libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__ranges/data.h b/libcxx/include/__ranges/data.h
index cc151c59f3d78..de39312b49cda 100644
--- a/libcxx/include/__ranges/data.h
+++ b/libcxx/include/__ranges/data.h
@@ -14,8 +14,7 @@
#include <__iterator/iterator_traits.h>
#include <__memory/pointer_traits.h>
#include <__ranges/access.h>
-#include <__utility/forward.h>
-#include <concepts>
+#include <__utility/auto_cast.h>
#include <type_traits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -35,34 +34,32 @@ namespace __data {
template <class _Tp>
concept __member_data =
+ __can_borrow<_Tp> &&
requires(_Tp&& __t) {
- { _VSTD::forward<_Tp>(__t) } -> __can_borrow;
- { __t.data() } -> __ptr_to_object;
+ { _LIBCPP_AUTO_CAST(__t.data()) } -> __ptr_to_object;
};
template <class _Tp>
concept __ranges_begin_invocable =
!__member_data<_Tp> &&
+ __can_borrow<_Tp> &&
requires(_Tp&& __t) {
- { _VSTD::forward<_Tp>(__t) } -> __can_borrow;
- { ranges::begin(_VSTD::forward<_Tp>(__t)) } -> contiguous_iterator;
+ { ranges::begin(__t) } -> contiguous_iterator;
};
struct __fn {
template <__member_data _Tp>
- requires __can_borrow<_Tp>
_LIBCPP_HIDE_FROM_ABI
- constexpr __ptr_to_object auto operator()(_Tp&& __t) const
+ constexpr auto operator()(_Tp&& __t) const
noexcept(noexcept(__t.data())) {
return __t.data();
}
template<__ranges_begin_invocable _Tp>
- requires __can_borrow<_Tp>
_LIBCPP_HIDE_FROM_ABI
- constexpr __ptr_to_object auto operator()(_Tp&& __t) const
- noexcept(noexcept(_VSTD::to_address(ranges::begin(_VSTD::forward<_Tp>(__t))))) {
- return _VSTD::to_address(ranges::begin(_VSTD::forward<_Tp>(__t)));
+ constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(_VSTD::to_address(ranges::begin(__t)))) {
+ return _VSTD::to_address(ranges::begin(__t));
}
};
}
diff --git a/libcxx/test/std/ranges/range.access/data.pass.cpp b/libcxx/test/std/ranges/range.access/data.pass.cpp
index 6d0b718f6b040..da4d79d724f3b 100644
--- a/libcxx/test/std/ranges/range.access/data.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/data.pass.cpp
@@ -36,9 +36,45 @@ struct DataMember {
int x;
constexpr const int *data() const { return &x; }
};
-
static_assert( std::is_invocable_v<RangeDataT, DataMember &>);
static_assert(!std::is_invocable_v<RangeDataT, DataMember &&>);
+static_assert( std::is_invocable_v<RangeDataT, DataMember const&>);
+static_assert(!std::is_invocable_v<RangeDataT, DataMember const&&>);
+
+constexpr bool testReturnTypes() {
+ {
+ int *x[2];
+ ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int**);
+ }
+ {
+ int x[2][2];
+ ASSERT_SAME_TYPE(decltype(std::ranges::data(x)), int(*)[2]);
+ }
+ {
+ struct D {
+ char*& data();
+ short*& data() const;
+ };
+ ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<D&>())), char*);
+ static_assert(!std::is_invocable_v<RangeDataT, D&&>);
+ ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<const D&>())), short*);
+ static_assert(!std::is_invocable_v<RangeDataT, const D&&>);
+ }
+ {
+ struct NC {
+ char *begin() const;
+ char *end() const;
+ int *data();
+ };
+ static_assert(!std::ranges::contiguous_range<NC>);
+ static_assert( std::ranges::contiguous_range<const NC>);
+ ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<NC&>())), int*);
+ static_assert(!std::is_invocable_v<RangeDataT, NC&&>);
+ ASSERT_SAME_TYPE(decltype(std::ranges::data(std::declval<const NC&>())), char*);
+ static_assert(!std::is_invocable_v<RangeDataT, const NC&&>);
+ }
+ return true;
+}
struct VoidDataMember {
void *data() const;
@@ -49,21 +85,14 @@ struct Empty { };
struct EmptyDataMember {
Empty data() const;
};
-
static_assert(!std::is_invocable_v<RangeDataT, EmptyDataMember const&>);
-struct EmptyPtrDataMember {
- Empty x;
- constexpr const Empty *data() const { return &x; }
-};
-
-struct PtrConvertible {
- operator int*() const;
-};
struct PtrConvertibleDataMember {
- PtrConvertible data() const;
+ struct Ptr {
+ operator int*() const;
+ };
+ Ptr data() const;
};
-
static_assert(!std::is_invocable_v<RangeDataT, PtrConvertibleDataMember const&>);
struct NonConstDataMember {
@@ -74,14 +103,13 @@ struct NonConstDataMember {
struct EnabledBorrowingDataMember {
constexpr int *data() { return &globalBuff[0]; }
};
-
template<>
inline constexpr bool std::ranges::enable_borrowed_range<EnabledBorrowingDataMember> = true;
struct DataMemberAndBegin {
int x;
constexpr const int *data() const { return &x; }
- constexpr const int *begin() const { return &x; }
+ const int *begin() const;
};
constexpr bool testDataMember() {
@@ -147,8 +175,10 @@ struct BeginMemberRvalue {
ContiguousIter begin() &&;
};
+static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue&&>);
static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue const&>);
+static_assert(!std::is_invocable_v<RangeDataT, BeginMemberRvalue const&&>);
struct BeginMemberBorrowingEnabled {
constexpr contiguous_iterator<int*> begin() { return contiguous_iterator<int*>{&globalBuff[1]}; }
@@ -188,6 +218,8 @@ struct RandomButNotContiguous {
static_assert(!std::is_invocable_v<RangeDataT, RandomButNotContiguous>);
int main(int, char**) {
+ static_assert(testReturnTypes());
+
testDataMember();
static_assert(testDataMember());
diff --git a/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp b/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp
index 228c27774b8cc..1b5aa353d9364 100644
--- a/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.req/range.refinements/contiguous_range.compile.pass.cpp
@@ -46,8 +46,8 @@ struct ContiguousWhenNonConst {
int *end();
int *data() const;
};
-static_assert( std::ranges::random_access_range<ContiguousWhenNonConst>);
static_assert( std::ranges::contiguous_range<ContiguousWhenNonConst>);
+static_assert( std::ranges::random_access_range<const ContiguousWhenNonConst>);
static_assert(!std::ranges::contiguous_range<const ContiguousWhenNonConst>);
struct ContiguousWhenConst {
@@ -57,9 +57,9 @@ struct ContiguousWhenConst {
int *end();
const int *data() const;
};
+static_assert( std::ranges::contiguous_range<const ContiguousWhenConst>);
static_assert( std::ranges::random_access_range<ContiguousWhenConst>);
static_assert(!std::ranges::contiguous_range<ContiguousWhenConst>);
-static_assert( std::ranges::contiguous_range<const ContiguousWhenConst>);
struct DataFunctionWrongReturnType {
const int *begin() const;
@@ -67,7 +67,7 @@ struct DataFunctionWrongReturnType {
const char *data() const;
};
static_assert( std::ranges::random_access_range<DataFunctionWrongReturnType>);
-static_assert(!std::ranges::contiguous_range<const DataFunctionWrongReturnType>);
+static_assert(!std::ranges::contiguous_range<DataFunctionWrongReturnType>);
struct WrongObjectness {
const int *begin() const;
More information about the libcxx-commits
mailing list