50 changes: 17 additions & 33 deletions libcxx/include/__ranges/filter_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER > 17

namespace ranges {

template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class __filter_view_iterator;

template <input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class __filter_view_sentinel;

template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class filter_view : public view_interface<filter_view<_View, _Pred>> {
Expand All @@ -67,11 +58,8 @@ namespace ranges {
using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>;
_LIBCPP_NO_UNIQUE_ADDRESS _Cache __cached_begin_ = _Cache();

using __iterator = __filter_view_iterator<_View, _Pred>;
using __sentinel = __filter_view_sentinel<_View, _Pred>;

friend __iterator;
friend __sentinel;
class __iterator;
class __sentinel;

public:
_LIBCPP_HIDE_FROM_ABI
Expand Down Expand Up @@ -131,13 +119,11 @@ namespace ranges {

template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class __filter_view_iterator : public __filter_iterator_category<_View> {

using __filter_view = filter_view<_View, _Pred>;
class filter_view<_View, _Pred>::__iterator : public __filter_iterator_category<_View> {

public:
_LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __current_ = iterator_t<_View>();
_LIBCPP_NO_UNIQUE_ADDRESS __filter_view* __parent_ = nullptr;
_LIBCPP_NO_UNIQUE_ADDRESS filter_view* __parent_ = nullptr;

using iterator_concept =
_If<bidirectional_range<_View>, bidirectional_iterator_tag,
Expand All @@ -149,10 +135,10 @@ namespace ranges {
using difference_type = range_difference_t<_View>;

_LIBCPP_HIDE_FROM_ABI
__filter_view_iterator() requires default_initializable<iterator_t<_View>> = default;
__iterator() requires default_initializable<iterator_t<_View>> = default;

_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator(__filter_view& __parent, iterator_t<_View> __current)
constexpr __iterator(filter_view& __parent, iterator_t<_View> __current)
: __current_(std::move(__current)), __parent_(std::addressof(__parent))
{ }

Expand All @@ -171,50 +157,50 @@ namespace ranges {
}

_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator& operator++() {
constexpr __iterator& operator++() {
__current_ = ranges::find_if(std::move(++__current_), ranges::end(__parent_->__base_),
std::ref(*__parent_->__pred_));
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr void operator++(int) { ++*this; }
_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator operator++(int) requires forward_range<_View> {
constexpr __iterator operator++(int) requires forward_range<_View> {
auto __tmp = *this;
++*this;
return __tmp;
}

_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator& operator--() requires bidirectional_range<_View> {
constexpr __iterator& operator--() requires bidirectional_range<_View> {
do {
--__current_;
} while (!std::invoke(*__parent_->__pred_, *__current_));
return *this;
}
_LIBCPP_HIDE_FROM_ABI
constexpr __filter_view_iterator operator--(int) requires bidirectional_range<_View> {
constexpr __iterator operator--(int) requires bidirectional_range<_View> {
auto tmp = *this;
--*this;
return tmp;
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(__filter_view_iterator const& __x, __filter_view_iterator const& __y)
friend constexpr bool operator==(__iterator const& __x, __iterator const& __y)
requires equality_comparable<iterator_t<_View>>
{
return __x.__current_ == __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr range_rvalue_reference_t<_View> iter_move(__filter_view_iterator const& __it)
friend constexpr range_rvalue_reference_t<_View> iter_move(__iterator const& __it)
noexcept(noexcept(ranges::iter_move(__it.__current_)))
{
return ranges::iter_move(__it.__current_);
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr void iter_swap(__filter_view_iterator const& __x, __filter_view_iterator const& __y)
friend constexpr void iter_swap(__iterator const& __x, __iterator const& __y)
noexcept(noexcept(ranges::iter_swap(__x.__current_, __y.__current_)))
requires indirectly_swappable<iterator_t<_View>>
{
Expand All @@ -224,25 +210,23 @@ namespace ranges {

template<input_range _View, indirect_unary_predicate<iterator_t<_View>> _Pred>
requires view<_View> && is_object_v<_Pred>
class __filter_view_sentinel {
using __filter_view = filter_view<_View, _Pred>;

class filter_view<_View, _Pred>::__sentinel {
public:
sentinel_t<_View> __end_ = sentinel_t<_View>();

_LIBCPP_HIDE_FROM_ABI
__filter_view_sentinel() = default;
__sentinel() = default;

_LIBCPP_HIDE_FROM_ABI
constexpr explicit __filter_view_sentinel(__filter_view& __parent)
constexpr explicit __sentinel(filter_view& __parent)
: __end_(ranges::end(__parent.__base_))
{ }

_LIBCPP_HIDE_FROM_ABI
constexpr sentinel_t<_View> base() const { return __end_; }

_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(__filter_view_iterator<_View, _Pred> const& __x, __filter_view_sentinel const& __y) {
operator==(__iterator const& __x, __sentinel const& __y) {
return __x.__current_ == __y.__end_;
}
};
Expand Down
432 changes: 204 additions & 228 deletions libcxx/include/__ranges/iota_view.h

Large diffs are not rendered by default.

26 changes: 9 additions & 17 deletions libcxx/include/__ranges/istream_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,10 @@ namespace ranges {
template <class _Val, class _CharT, class _Traits>
concept __stream_extractable = requires(basic_istream<_CharT, _Traits>& __is, _Val& __t) { __is >> __t; };

template <movable _Val, class _CharT, class _Traits>
requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits>
class __basic_istream_view_iterator;

template <movable _Val, class _CharT, class _Traits = char_traits<_CharT>>
requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits>
class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT, _Traits>> {
using __iterator = __basic_istream_view_iterator<_Val, _CharT, _Traits>;

template <movable _ValueType, class _CharType, class _TraitsType>
requires default_initializable<_ValueType> && __stream_extractable<_ValueType, _CharType, _TraitsType>
friend class __basic_istream_view_iterator;
class __iterator;

public:
_LIBCPP_HIDE_FROM_ABI constexpr explicit basic_istream_view(basic_istream<_CharT, _Traits>& __stream)
Expand All @@ -67,23 +59,23 @@ class basic_istream_view : public view_interface<basic_istream_view<_Val, _CharT

template <movable _Val, class _CharT, class _Traits>
requires default_initializable<_Val> && __stream_extractable<_Val, _CharT, _Traits>
class __basic_istream_view_iterator {
class basic_istream_view<_Val, _CharT, _Traits>::__iterator {
public:
using iterator_concept = input_iterator_tag;
using difference_type = ptrdiff_t;
using value_type = _Val;

_LIBCPP_HIDE_FROM_ABI constexpr explicit __basic_istream_view_iterator(
_LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(
basic_istream_view<_Val, _CharT, _Traits>& __parent) noexcept
: __parent_(std::addressof(__parent)) {}

__basic_istream_view_iterator(const __basic_istream_view_iterator&) = delete;
_LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator(__basic_istream_view_iterator&&) = default;
__iterator(const __iterator&) = delete;
_LIBCPP_HIDE_FROM_ABI __iterator(__iterator&&) = default;

__basic_istream_view_iterator& operator=(const __basic_istream_view_iterator&) = delete;
_LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator=(__basic_istream_view_iterator&&) = default;
__iterator& operator=(const __iterator&) = delete;
_LIBCPP_HIDE_FROM_ABI __iterator& operator=(__iterator&&) = default;

_LIBCPP_HIDE_FROM_ABI __basic_istream_view_iterator& operator++() {
_LIBCPP_HIDE_FROM_ABI __iterator& operator++() {
*__parent_->__stream_ >> __parent_->__value_;
return *this;
}
Expand All @@ -92,7 +84,7 @@ class __basic_istream_view_iterator {

_LIBCPP_HIDE_FROM_ABI _Val& operator*() const { return __parent_->__value_; }

_LIBCPP_HIDE_FROM_ABI friend bool operator==(const __basic_istream_view_iterator& __x, default_sentinel_t) {
_LIBCPP_HIDE_FROM_ABI friend bool operator==(const __iterator& __x, default_sentinel_t) {
return !*__x.__get_parent_stream();
}

Expand Down
89 changes: 38 additions & 51 deletions libcxx/include/__ranges/join_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,34 +69,16 @@ namespace ranges {
>;
};

template <input_range _View, bool _Const>
requires view<_View> && input_range<range_reference_t<_View>>
struct __join_view_iterator;

template <input_range _View, bool _Const>
requires view<_View> && input_range<range_reference_t<_View>>
struct __join_view_sentinel;

template<input_range _View>
requires view<_View> && input_range<range_reference_t<_View>>
class join_view
: public view_interface<join_view<_View>> {
private:
using _InnerRange = range_reference_t<_View>;

template<bool _Const>
using __iterator = __join_view_iterator<_View, _Const>;

template<bool _Const>
using __sentinel = __join_view_sentinel<_View, _Const>;
template<bool> struct __iterator;

template <input_range _View2, bool _Const2>
requires view<_View2> && input_range<range_reference_t<_View2>>
friend struct __join_view_iterator;

template <input_range _View2, bool _Const2>
requires view<_View2> && input_range<range_reference_t<_View2>>
friend struct __join_view_sentinel;
template<bool> struct __sentinel;

template <class>
friend struct std::__segmented_iterator_traits;
Expand Down Expand Up @@ -167,12 +149,12 @@ namespace ranges {
}
};

template<input_range _View, bool _Const>
template<input_range _View>
requires view<_View> && input_range<range_reference_t<_View>>
struct __join_view_sentinel {
template<input_range _View2, bool>
requires view<_View2> && input_range<range_reference_t<_View2>>
friend struct __join_view_sentinel;
template<bool _Const>
struct join_view<_View>::__sentinel {
template<bool>
friend struct __sentinel;

private:
using _Parent = __maybe_const<_Const, join_view<_View>>;
Expand All @@ -181,37 +163,42 @@ namespace ranges {

public:
_LIBCPP_HIDE_FROM_ABI
__join_view_sentinel() = default;
__sentinel() = default;

_LIBCPP_HIDE_FROM_ABI
constexpr explicit __join_view_sentinel(_Parent& __parent)
constexpr explicit __sentinel(_Parent& __parent)
: __end_(ranges::end(__parent.__base_)) {}

_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_sentinel(__join_view_sentinel<_View, !_Const> __s)
constexpr __sentinel(__sentinel<!_Const> __s)
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
: __end_(std::move(__s.__end_)) {}

template<bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __join_view_iterator<_View, _OtherConst>& __x, const __join_view_sentinel& __y) {
friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __x.__outer_ == __y.__end_;
}
};

template<input_range _View, bool _Const>
// https://reviews.llvm.org/D142811#inline-1383022
// To simplify the segmented iterator traits specialization,
// make the iterator `final`
template<input_range _View>
requires view<_View> && input_range<range_reference_t<_View>>
struct __join_view_iterator
template<bool _Const>
struct join_view<_View>::__iterator final
: public __join_view_iterator_category<__maybe_const<_Const, _View>> {

template<input_range _View2, bool>
requires view<_View2> && input_range<range_reference_t<_View2>>
friend struct __join_view_iterator;
template<bool>
friend struct __iterator;

template <class>
friend struct std::__segmented_iterator_traits;

static constexpr bool __is_join_view_iterator = true;

private:
using _Parent = __maybe_const<_Const, join_view<_View>>;
using _Base = __maybe_const<_Const, _View>;
Expand Down Expand Up @@ -246,7 +233,7 @@ namespace ranges {
__inner_.reset();
}

_LIBCPP_HIDE_FROM_ABI constexpr __join_view_iterator(_Parent* __parent, _Outer __outer, _Inner __inner)
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent* __parent, _Outer __outer, _Inner __inner)
: __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {}

public:
Expand All @@ -267,17 +254,17 @@ namespace ranges {
range_difference_t<_Base>, range_difference_t<range_reference_t<_Base>>>;

_LIBCPP_HIDE_FROM_ABI
__join_view_iterator() requires default_initializable<_Outer> = default;
__iterator() requires default_initializable<_Outer> = default;

_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator(_Parent& __parent, _Outer __outer)
constexpr __iterator(_Parent& __parent, _Outer __outer)
: __outer_(std::move(__outer))
, __parent_(std::addressof(__parent)) {
__satisfy();
}

_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator(__join_view_iterator<_View, !_Const> __i)
constexpr __iterator(__iterator<!_Const> __i)
requires _Const &&
convertible_to<iterator_t<_View>, _Outer> &&
convertible_to<iterator_t<_InnerRange>, _Inner>
Expand All @@ -298,7 +285,7 @@ namespace ranges {
}

_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator& operator++() {
constexpr __iterator& operator++() {
auto&& __inner = [&]() -> auto&& {
if constexpr (__ref_is_glvalue)
return *__outer_;
Expand All @@ -318,7 +305,7 @@ namespace ranges {
}

_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator operator++(int)
constexpr __iterator operator++(int)
requires __ref_is_glvalue &&
forward_range<_Base> &&
forward_range<range_reference_t<_Base>>
Expand All @@ -329,7 +316,7 @@ namespace ranges {
}

_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator& operator--()
constexpr __iterator& operator--()
requires __ref_is_glvalue &&
bidirectional_range<_Base> &&
bidirectional_range<range_reference_t<_Base>> &&
Expand All @@ -348,7 +335,7 @@ namespace ranges {
}

_LIBCPP_HIDE_FROM_ABI
constexpr __join_view_iterator operator--(int)
constexpr __iterator operator--(int)
requires __ref_is_glvalue &&
bidirectional_range<_Base> &&
bidirectional_range<range_reference_t<_Base>> &&
Expand All @@ -360,7 +347,7 @@ namespace ranges {
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __join_view_iterator& __x, const __join_view_iterator& __y)
friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
requires __ref_is_glvalue &&
equality_comparable<iterator_t<_Base>> &&
equality_comparable<iterator_t<range_reference_t<_Base>>>
Expand All @@ -369,14 +356,14 @@ namespace ranges {
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr decltype(auto) iter_move(const __join_view_iterator& __i)
friend constexpr decltype(auto) iter_move(const __iterator& __i)
noexcept(noexcept(ranges::iter_move(*__i.__inner_)))
{
return ranges::iter_move(*__i.__inner_);
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr void iter_swap(const __join_view_iterator& __x, const __join_view_iterator& __y)
friend constexpr void iter_swap(const __iterator& __x, const __iterator& __y)
noexcept(noexcept(ranges::iter_swap(*__x.__inner_, *__y.__inner_)))
requires indirectly_swappable<_Inner>
{
Expand Down Expand Up @@ -404,12 +391,12 @@ inline namespace __cpo {
} // namespace views
} // namespace ranges

template <class _View, bool _Const>
requires(ranges::common_range<typename ranges::__join_view_iterator<_View, _Const>::_Parent> &&
__is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Outer>::value &&
__is_cpp17_random_access_iterator<typename ranges::__join_view_iterator<_View, _Const>::_Inner>::value)
struct __segmented_iterator_traits<ranges::__join_view_iterator<_View, _Const>> {
using _JoinViewIterator = ranges::__join_view_iterator<_View, _Const>;
template <class _JoinViewIterator>
requires(_JoinViewIterator::__is_join_view_iterator &&
ranges::common_range<typename _JoinViewIterator::_Parent> &&
__is_cpp17_random_access_iterator<typename _JoinViewIterator::_Outer>::value &&
__is_cpp17_random_access_iterator<typename _JoinViewIterator::_Inner>::value)
struct __segmented_iterator_traits<_JoinViewIterator> {

using __segment_iterator =
_LIBCPP_NODEBUG __iterator_with_data<typename _JoinViewIterator::_Outer, typename _JoinViewIterator::_Parent*>;
Expand Down
52 changes: 23 additions & 29 deletions libcxx/include/__ranges/split_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD

namespace ranges {

template <class _View, class _Pattern>
struct __split_view_iterator;

template <class _View, class _Pattern>
struct __split_view_sentinel;

template <forward_range _View, forward_range _Pattern>
requires view<_View> && view<_Pattern> &&
indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to>
Expand All @@ -59,13 +53,13 @@ class split_view : public view_interface<split_view<_View, _Pattern>> {
_Cache __cached_begin_ = _Cache();

template <class, class>
friend struct __split_view_iterator;
friend struct __iterator;

template <class, class>
friend struct __split_view_sentinel;
friend struct __sentinel;

using __iterator = __split_view_iterator<_View, _Pattern>;
using __sentinel = __split_view_sentinel<_View, _Pattern>;
struct __iterator;
struct __sentinel;

_LIBCPP_HIDE_FROM_ABI constexpr subrange<iterator_t<_View>> __find_next(iterator_t<_View> __it) {
auto [__begin, __end] = ranges::search(subrange(__it, ranges::end(__base_)), __pattern_);
Expand Down Expand Up @@ -120,34 +114,35 @@ split_view(_Range&&, _Pattern&&) -> split_view<views::all_t<_Range>, views::all_
template <forward_range _Range>
split_view(_Range&&, range_value_t<_Range>) -> split_view<views::all_t<_Range>, single_view<range_value_t<_Range>>>;

template <class _View, class _Pattern>
struct __split_view_iterator {
template <forward_range _View, forward_range _Pattern>
requires view<_View> && view<_Pattern> &&
indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to>
struct split_view<_View, _Pattern>::__iterator {
private:
split_view<_View, _Pattern>* __parent_ = nullptr;
split_view* __parent_ = nullptr;
_LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_View> __cur_ = iterator_t<_View>();
_LIBCPP_NO_UNIQUE_ADDRESS subrange<iterator_t<_View>> __next_ = subrange<iterator_t<_View>>();
bool __trailing_empty_ = false;

template <class, class>
friend struct __split_view_sentinel;
friend struct __sentinel;

public:
using iterator_concept = forward_iterator_tag;
using iterator_category = input_iterator_tag;
using value_type = subrange<iterator_t<_View>>;
using difference_type = range_difference_t<_View>;

_LIBCPP_HIDE_FROM_ABI __split_view_iterator() = default;
_LIBCPP_HIDE_FROM_ABI __iterator() = default;

_LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator(
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(
split_view<_View, _Pattern>& __parent, iterator_t<_View> __current, subrange<iterator_t<_View>> __next)
: __parent_(std::addressof(__parent)), __cur_(std::move(__current)), __next_(std::move(__next)) {}

_LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_View> base() const { return __cur_; }

_LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return {__cur_, __next_.begin()}; }

_LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator& operator++() {
_LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
__cur_ = __next_.begin();
if (__cur_ != ranges::end(__parent_->__base_)) {
__cur_ = __next_.end();
Expand All @@ -163,36 +158,35 @@ struct __split_view_iterator {
return *this;
}

_LIBCPP_HIDE_FROM_ABI constexpr __split_view_iterator operator++(int) {
_LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) {
auto __tmp = *this;
++*this;
return __tmp;
}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const __split_view_iterator& __x, const __split_view_iterator& __y) {
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
return __x.__cur_ == __y.__cur_ && __x.__trailing_empty_ == __y.__trailing_empty_;
}
};

template <class _View, class _Pattern>
struct __split_view_sentinel {
template <forward_range _View, forward_range _Pattern>
requires view<_View> && view<_Pattern> &&
indirectly_comparable<iterator_t<_View>, iterator_t<_Pattern>, ranges::equal_to>
struct split_view<_View, _Pattern>::__sentinel {
private:
_LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_View> __end_ = sentinel_t<_View>();

_LIBCPP_HIDE_FROM_ABI static constexpr bool
__equals(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) {
_LIBCPP_HIDE_FROM_ABI static constexpr bool __equals(const __iterator& __x, const __sentinel& __y) {
return __x.__cur_ == __y.__end_ && !__x.__trailing_empty_;
}

public:
_LIBCPP_HIDE_FROM_ABI __split_view_sentinel() = default;
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;

_LIBCPP_HIDE_FROM_ABI constexpr explicit __split_view_sentinel(split_view<_View, _Pattern>& __parent)
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(split_view<_View, _Pattern>& __parent)
: __end_(ranges::end(__parent.__base_)) {}

_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const __split_view_iterator<_View, _Pattern>& __x, const __split_view_sentinel& __y) {
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __sentinel& __y) {
return __equals(__x, __y);
}
};
Expand Down
30 changes: 12 additions & 18 deletions libcxx/include/__ranges/take_while_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,11 @@ template <class _View, class _Pred>
concept __take_while_const_is_range =
range<const _View> && indirect_unary_predicate<const _Pred, iterator_t<const _View>>;

template <class, class, bool>
class __take_while_view_sentinel;

template <view _View, class _Pred>
requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>>
class take_while_view : public view_interface<take_while_view<_View, _Pred>> {
template <class, class, bool>
friend class __take_while_view_sentinel;

template <bool _Const>
using __sentinel = __take_while_view_sentinel<_View, _Pred, _Const>;
template <bool>
class __sentinel;

_LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
_LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_;
Expand Down Expand Up @@ -114,37 +108,37 @@ class take_while_view : public view_interface<take_while_view<_View, _Pred>> {
template <class _Range, class _Pred>
take_while_view(_Range&&, _Pred) -> take_while_view<views::all_t<_Range>, _Pred>;

template <class _View, class _Pred, bool _Const>
class __take_while_view_sentinel {
template <view _View, class _Pred>
requires input_range<_View> && is_object_v<_Pred> && indirect_unary_predicate<const _Pred, iterator_t<_View>>
template <bool _Const>
class take_while_view<_View, _Pred>::__sentinel {
using _Base = __maybe_const<_Const, _View>;

sentinel_t<_Base> __end_ = sentinel_t<_Base>();
const _Pred* __pred_ = nullptr;

template <class, class, bool>
friend class __take_while_view_sentinel;
friend class __sentinel<!_Const>;

public:
_LIBCPP_HIDE_FROM_ABI __take_while_view_sentinel() = default;
_LIBCPP_HIDE_FROM_ABI __sentinel() = default;

_LIBCPP_HIDE_FROM_ABI constexpr explicit __take_while_view_sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
_LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end, const _Pred* __pred)
: __end_(std::move(__end)), __pred_(__pred) {}

_LIBCPP_HIDE_FROM_ABI constexpr __take_while_view_sentinel(__take_while_view_sentinel<_View, _Pred, !_Const> __s)
_LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __s)
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
: __end_(std::move(__s.__end_)), __pred_(__s.__pred_) {}

_LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; }

_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const iterator_t<_Base>& __x, const __take_while_view_sentinel& __y) {
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const iterator_t<_Base>& __x, const __sentinel& __y) {
return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x);
}

template <bool _OtherConst = !_Const>
requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __take_while_view_sentinel& __y) {
operator==(const iterator_t<__maybe_const<_OtherConst, _View>>& __x, const __sentinel& __y) {
return __x == __y.__end_ || !std::invoke(*__y.__pred_, *__x);
}
};
Expand Down
127 changes: 51 additions & 76 deletions libcxx/include/__ranges/transform_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,31 +57,11 @@ concept __transform_view_constraints =
regular_invocable<_Fn&, range_reference_t<_View>> &&
__can_reference<invoke_result_t<_Fn&, range_reference_t<_View>>>;

template <input_range _View, copy_constructible _Function, bool _IsConst>
requires __transform_view_constraints<_View, _Function>
class __transform_view_iterator;

template <input_range _View, copy_constructible _Function, bool _IsConst>
requires __transform_view_constraints<_View, _Function>
class __transform_view_sentinel;

template<input_range _View, copy_constructible _Fn>
requires __transform_view_constraints<_View, _Fn>
class transform_view : public view_interface<transform_view<_View, _Fn>> {

template <bool _IsConst>
using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>;

template <bool _IsConst>
using __sentinel = __transform_view_sentinel<_View, _Fn, _IsConst>;

template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_iterator;

template <input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_sentinel;
template<bool> class __iterator;
template<bool> class __sentinel;

_LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Fn> __func_;
_LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
Expand Down Expand Up @@ -176,23 +156,22 @@ struct __transform_view_iterator_category_base<_View, _Fn> {
>;
};

template<input_range _View, copy_constructible _Fn, bool _Const>
template<input_range _View, copy_constructible _Fn>
requires __transform_view_constraints<_View, _Fn>
class __transform_view_iterator
template<bool _Const>
class transform_view<_View, _Fn>::__iterator
: public __transform_view_iterator_category_base<_View, _Fn> {

using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>;
using _Parent = __maybe_const<_Const, transform_view>;
using _Base = __maybe_const<_Const, _View>;

_Parent *__parent_ = nullptr;

template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_iterator;
template<bool>
friend class transform_view<_View, _Fn>::__iterator;

template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_sentinel;
template<bool>
friend class transform_view<_View, _Fn>::__sentinel;

public:
iterator_t<_Base> __current_ = iterator_t<_Base>();
Expand All @@ -202,17 +181,17 @@ class __transform_view_iterator
using difference_type = range_difference_t<_Base>;

_LIBCPP_HIDE_FROM_ABI
__transform_view_iterator() requires default_initializable<iterator_t<_Base>> = default;
__iterator() requires default_initializable<iterator_t<_Base>> = default;

_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator(_Parent& __parent, iterator_t<_Base> __current)
constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current)
: __parent_(std::addressof(__parent)), __current_(std::move(__current)) {}

// Note: `__i` should always be `__transform_view_iterator<false>`, but directly using
// `__transform_view_iterator<false>` is ill-formed when `_Const` is false
// Note: `__i` should always be `__iterator<false>`, but directly using
// `__iterator<false>` is ill-formed when `_Const` is false
// (see http://wg21.link/class.copy.ctor#5).
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator(__transform_view_iterator<_View, _Fn, !_Const> __i)
constexpr __iterator(__iterator<!_Const> __i)
requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
: __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {}

Expand All @@ -234,7 +213,7 @@ class __transform_view_iterator
}

_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator& operator++() {
constexpr __iterator& operator++() {
++__current_;
return *this;
}
Expand All @@ -243,7 +222,7 @@ class __transform_view_iterator
constexpr void operator++(int) { ++__current_; }

_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator operator++(int)
constexpr __iterator operator++(int)
requires forward_range<_Base>
{
auto __tmp = *this;
Expand All @@ -252,15 +231,15 @@ class __transform_view_iterator
}

_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator& operator--()
constexpr __iterator& operator--()
requires bidirectional_range<_Base>
{
--__current_;
return *this;
}

_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator operator--(int)
constexpr __iterator operator--(int)
requires bidirectional_range<_Base>
{
auto __tmp = *this;
Expand All @@ -269,15 +248,15 @@ class __transform_view_iterator
}

_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator& operator+=(difference_type __n)
constexpr __iterator& operator+=(difference_type __n)
requires random_access_range<_Base>
{
__current_ += __n;
return *this;
}

_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_iterator& operator-=(difference_type __n)
constexpr __iterator& operator-=(difference_type __n)
requires random_access_range<_Base>
{
__current_ -= __n;
Expand All @@ -293,77 +272,77 @@ class __transform_view_iterator
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
requires equality_comparable<iterator_t<_Base>>
{
return __x.__current_ == __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ < __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ > __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator<=(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ <= __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator>=(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base>
{
return __x.__current_ >= __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr auto operator<=>(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>>
{
return __x.__current_ <=> __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr __transform_view_iterator operator+(__transform_view_iterator __i, difference_type __n)
friend constexpr __iterator operator+(__iterator __i, difference_type __n)
requires random_access_range<_Base>
{
return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n};
return __iterator{*__i.__parent_, __i.__current_ + __n};
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr __transform_view_iterator operator+(difference_type __n, __transform_view_iterator __i)
friend constexpr __iterator operator+(difference_type __n, __iterator __i)
requires random_access_range<_Base>
{
return __transform_view_iterator{*__i.__parent_, __i.__current_ + __n};
return __iterator{*__i.__parent_, __i.__current_ + __n};
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr __transform_view_iterator operator-(__transform_view_iterator __i, difference_type __n)
friend constexpr __iterator operator-(__iterator __i, difference_type __n)
requires random_access_range<_Base>
{
return __transform_view_iterator{*__i.__parent_, __i.__current_ - __n};
return __iterator{*__i.__parent_, __i.__current_ - __n};
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr difference_type operator-(const __transform_view_iterator& __x, const __transform_view_iterator& __y)
friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
{
return __x.__current_ - __y.__current_;
}

_LIBCPP_HIDE_FROM_ABI
friend constexpr decltype(auto) iter_move(const __transform_view_iterator& __i)
friend constexpr decltype(auto) iter_move(const __iterator& __i)
noexcept(noexcept(*__i))
{
if constexpr (is_lvalue_reference_v<decltype(*__i)>)
Expand All @@ -373,37 +352,33 @@ class __transform_view_iterator
}
};

template<input_range _View, copy_constructible _Fn, bool _Const>
template<input_range _View, copy_constructible _Fn>
requires __transform_view_constraints<_View, _Fn>
class __transform_view_sentinel {
using _Parent = __maybe_const<_Const, transform_view<_View, _Fn>>;
template<bool _Const>
class transform_view<_View, _Fn>::__sentinel {
using _Parent = __maybe_const<_Const, transform_view>;
using _Base = __maybe_const<_Const, _View>;

template <bool _IsConst>
using __iterator = __transform_view_iterator<_View, _Fn, _IsConst>;

sentinel_t<_Base> __end_ = sentinel_t<_Base>();

template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_iterator;
template<bool>
friend class transform_view<_View, _Fn>::__iterator;

template<input_range _ViewType, copy_constructible _FunctionType, bool _IsConst>
requires __transform_view_constraints<_ViewType, _FunctionType>
friend class __transform_view_sentinel;
template<bool>
friend class transform_view<_View, _Fn>::__sentinel;

public:
_LIBCPP_HIDE_FROM_ABI
__transform_view_sentinel() = default;
__sentinel() = default;

_LIBCPP_HIDE_FROM_ABI
constexpr explicit __transform_view_sentinel(sentinel_t<_Base> __end) : __end_(__end) {}
constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {}

// Note: `__i` should always be `__transform_view_sentinel<false>`, but directly using
// `__transform_view_sentinel<false>` is ill-formed when `_Const` is false
// Note: `__i` should always be `__sentinel<false>`, but directly using
// `__sentinel<false>` is ill-formed when `_Const` is false
// (see http://wg21.link/class.copy.ctor#5).
_LIBCPP_HIDE_FROM_ABI
constexpr __transform_view_sentinel(__transform_view_sentinel<_View, _Fn, !_Const> __i)
constexpr __sentinel(__sentinel<!_Const> __i)
requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
: __end_(std::move(__i.__end_)) {}

Expand All @@ -413,23 +388,23 @@ class __transform_view_sentinel {
template<bool _OtherConst>
requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI
friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) {
friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __x.__current_ == __y.__end_;
}

template<bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI
friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
operator-(const __iterator<_OtherConst>& __x, const __transform_view_sentinel& __y) {
operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __x.__current_ - __y.__end_;
}

template<bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
_LIBCPP_HIDE_FROM_ABI
friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
operator-(const __transform_view_sentinel& __x, const __iterator<_OtherConst>& __y) {
operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) {
return __x.__end_ - __y.__current_;
}
};
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__type_traits/add_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__add_pointer)
#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer)

template <class _Tp>
using __add_pointer_t = __add_pointer(_Tp);
Expand All @@ -39,7 +39,7 @@ template <class _Tp> struct __add_pointer_impl<_Tp, false>
template <class _Tp>
using __add_pointer_t = typename __add_pointer_impl<_Tp>::type;

#endif // __has_builtin(__add_pointer)
#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__add_pointer)

template <class _Tp>
struct add_pointer {
Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__type_traits/remove_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

_LIBCPP_BEGIN_NAMESPACE_STD

#if __has_builtin(__remove_pointer)
#if !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer)
template <class _Tp>
struct remove_pointer {
using type _LIBCPP_NODEBUG = __remove_pointer(_Tp);
Expand All @@ -34,7 +34,7 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_pointer<_Tp* const volat

template <class _Tp>
using __remove_pointer_t = typename remove_pointer<_Tp>::type;
#endif // __has_builtin(__remove_pointer)
#endif // !defined(_LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS) && __has_builtin(__remove_pointer)

#if _LIBCPP_STD_VER > 11
template <class _Tp> using remove_pointer_t = __remove_pointer_t<_Tp>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include <deque>


using DequeIterator = typename std::deque<int>::iterator;
static_assert(std::__is_segmented_iterator<DequeIterator>::value, "");
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//===----------------------------------------------------------------------===//
//
// 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

#include <ranges>
#include <vector>

using JoinView = decltype(std::views::join(std::declval<std::vector<std::vector<int>>&>()));
using JoinIter = std::ranges::iterator_t<JoinView>;
static_assert(std::__is_segmented_iterator<JoinIter>::value);
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//===----------------------------------------------------------------------===//
//
// 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

// ADL call with nested iterators of views should not look up base's view's
// namespace

#include <ranges>
#include <tuple>

#include "test_macros.h"

#ifndef TEST_HAS_NO_LOCALIZATION
#include <istream>
#endif
namespace adl {

struct BaseView : std::ranges::view_base {
int* begin() const;
int* end() const;
};

struct TupleView : std::ranges::view_base {
std::tuple<int>* begin() const;
std::tuple<int>* end() const;
};

struct NestedView : std::ranges::view_base {
BaseView* begin() const;
BaseView* end() const;
};

struct Pred {
bool operator()(const auto&...) const;
};

struct Sentinel {
bool operator==(const auto&) const;
};

struct Value {
friend std::istream& operator>>(std::istream&, Value);
};

void adl_func(const auto&);

} // namespace adl

template <class View>
concept CanFindADLFunc = requires(std::ranges::iterator_t<View> it) { adl_func(it); };

static_assert(!CanFindADLFunc<std::ranges::elements_view<adl::TupleView, 0>>);
static_assert(!CanFindADLFunc<std::ranges::filter_view<adl::BaseView, adl::Pred>>);
static_assert(!CanFindADLFunc<std::ranges::iota_view<int, adl::Sentinel>>);

#ifndef TEST_HAS_NO_LOCALIZATION
static_assert(!CanFindADLFunc<std::ranges::istream_view<adl::Value>>);
#endif

static_assert(!CanFindADLFunc<std::ranges::join_view<adl::NestedView>>);

static_assert(!CanFindADLFunc<std::ranges::lazy_split_view<adl::BaseView, adl::BaseView>>);
using InnerRange =
typename std::ranges::iterator_t<std::ranges::lazy_split_view<adl::BaseView, adl::BaseView>>::value_type;
static_assert(!CanFindADLFunc<InnerRange >);

static_assert(!CanFindADLFunc<std::ranges::split_view<adl::BaseView, adl::BaseView>>);
static_assert(!CanFindADLFunc<std::ranges::transform_view<adl::BaseView, adl::Pred>>);

#if TEST_STD_VER >= 23
static_assert(!CanFindADLFunc<std::ranges::zip_view<adl::BaseView>>);
#endif
106 changes: 106 additions & 0 deletions libcxx/test/std/utilities/meta/meta.trans/objc_support.pass.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

// REQUIRES: objective-c++

// Simple test to check that type traits support Objective-C types.

#include <type_traits>
#include "test_macros.h"

@interface I;
@end

// add_pointer
static_assert(std::is_same<std::add_pointer<id>::type, id*>::value, "");
static_assert(std::is_same<std::add_pointer<I>::type, I*>::value, "");

// add_lvalue_reference
static_assert(std::is_same<std::add_lvalue_reference<id>::type, id&>::value, "");
static_assert(std::is_same<std::add_lvalue_reference<I>::type, I&>::value, "");

// add_rvalue_reference
static_assert(std::is_same<std::add_rvalue_reference<id>::type, id&&>::value, "");
static_assert(std::is_same<std::add_rvalue_reference<I>::type, I&&>::value, "");

// decay
static_assert(std::is_same<std::decay<id>::type, id>::value, "");
static_assert(std::is_same<std::decay<I>::type, I>::value, "");
static_assert(std::is_same<std::decay<id(&)[5]>::type, id*>::value, "");

// __libcpp_is_referenceable
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id*>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id&>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<id&&>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I*>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I&>::value, "");
LIBCPP_STATIC_ASSERT(std::__libcpp_is_referenceable<I&&>::value, "");

// remove_all_extents
static_assert(std::is_same<std::remove_all_extents<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<id[5]>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<id[5][10]>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<I>::type, I>::value, "");

// remove_const
static_assert(std::is_same<std::remove_const<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_const<const id>::type, id>::value, "");
static_assert(std::is_same<std::remove_const<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_const<const I>::type, I>::value, "");

// remove_cv
static_assert(std::is_same<std::remove_cv<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_cv<const volatile id>::type, id>::value, "");
static_assert(std::is_same<std::remove_cv<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_cv<const volatile I>::type, I>::value, "");

#if TEST_STD_VER >= 20
// remove_cvref
static_assert(std::is_same<std::remove_cvref<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_cvref<const volatile id&>::type, id>::value, "");
static_assert(std::is_same<std::remove_cvref<const volatile id&&>::type, id>::value, "");
static_assert(std::is_same<std::remove_cvref<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_cvref<const volatile I&>::type, I>::value, "");
static_assert(std::is_same<std::remove_cvref<const volatile I&&>::type, I>::value, "");
#endif

// remove_extent
static_assert(std::is_same<std::remove_all_extents<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<id[5]>::type, id>::value, "");
static_assert(std::is_same<std::remove_all_extents<I>::type, I>::value, "");

// remove_pointer
static_assert(!std::is_same<std::remove_pointer<id>::type, id>::value, "");
// The result of removing and re-adding pointer to `id` should be still `id`.
static_assert(std::is_same<std::remove_pointer<id>::type*, id>::value, "");
static_assert(std::is_same<std::add_pointer<std::remove_pointer<id>::type>::type, id>::value, "");
static_assert(std::is_same<std::remove_pointer<std::add_pointer<id>::type>::type, id>::value, "");

// remove_reference
static_assert(std::is_same<std::remove_reference<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_reference<id&>::type, id>::value, "");
static_assert(std::is_same<std::remove_reference<const id&>::type, const id>::value, "");
static_assert(std::is_same<std::remove_reference<id&&>::type, id>::value, "");
static_assert(std::is_same<std::remove_reference<const id&&>::type, const id>::value, "");
static_assert(std::is_same<std::remove_reference<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_reference<I&>::type, I>::value, "");
static_assert(std::is_same<std::remove_reference<const I&>::type, const I>::value, "");
static_assert(std::is_same<std::remove_reference<I&&>::type, I>::value, "");
static_assert(std::is_same<std::remove_reference<const I&&>::type, const I>::value, "");

// remove_volatile
static_assert(std::is_same<std::remove_volatile<id>::type, id>::value, "");
static_assert(std::is_same<std::remove_volatile<volatile id>::type, id>::value, "");
static_assert(std::is_same<std::remove_volatile<I>::type, I>::value, "");
static_assert(std::is_same<std::remove_volatile<volatile I>::type, I>::value, "");

int main(int, char**) {
return 0;
}
3 changes: 2 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12454,7 +12454,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG) {
SDValue N00 = N0.getOperand(0);
EVT ExtVT = cast<VTSDNode>(N0->getOperand(1))->getVT();
if (N00.getOpcode() == ISD::TRUNCATE && (!LegalOperations || TLI.isTypeLegal(ExtVT))) {
if (N00.getOpcode() == ISD::TRUNCATE &&
(!LegalTypes || TLI.isTypeLegal(ExtVT))) {
SDValue T = DAG.getNode(ISD::TRUNCATE, DL, ExtVT, N00.getOperand(0));
return DAG.getNode(ISD::SIGN_EXTEND, DL, VT, T);
}
Expand Down
25 changes: 25 additions & 0 deletions llvm/test/CodeGen/AArch64/pr61111.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s

define i62 @f(i1 %0) {
; CHECK-LABEL: f:
; CHECK: // %bb.0:
; CHECK-NEXT: // kill: def $w0 killed $w0 def $x0
; CHECK-NEXT: and x8, x0, #0x1
; CHECK-NEXT: sub x8, x8, #1
; CHECK-NEXT: tst x8, #0x3fffffffffffffff
; CHECK-NEXT: cset w0, ne
; CHECK-NEXT: ret
%2 = zext i1 %0 to i59
%3 = call { i59, i1 } @llvm.umul.with.overflow.i59(i59 %2, i59 -1)
%4 = extractvalue { i59, i1 } %3, 0
%5 = trunc i59 %4 to i21
%6 = trunc i59 %4 to i21
%7 = ashr i21 %5, %6
%8 = sext i21 %7 to i62
%9 = icmp ugt i62 -1, %8
%10 = zext i1 %9 to i62
ret i62 %10
}

declare { i59, i1 } @llvm.umul.with.overflow.i59(i59, i59)