Skip to content

[libcxx][test] Do not assume array::iterator is a pointer #100603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <algorithm>
#include <array>
#include <cassert>
#include <memory>
#include <ranges>
#include <vector>

Expand Down Expand Up @@ -61,7 +62,8 @@ template <class It, class Sent = It>
constexpr void test_iterators() {
using ValueT = std::iter_value_t<It>;
auto make_range = [](auto& a) {
return std::ranges::subrange(It(std::ranges::begin(a)), Sent(It(std::ranges::end(a))));
return std::ranges::subrange(
It(std::to_address(std::ranges::begin(a))), Sent(It(std::to_address(std::ranges::end(a)))));
};
{ // simple test
{
Expand Down Expand Up @@ -91,7 +93,7 @@ constexpr void test_iterators() {
std::array<ValueT, 0> a = {};

auto ret = std::ranges::find_last(make_range(a), 1).begin();
assert(ret == It(a.begin()));
assert(ret == It(a.data()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,14 @@ constexpr void test_iterator_classes() {
{
std::array<int, 0> a = {};

auto ret = std::ranges::find_last_if(it(a.data()), sent(it(a.data())), [](auto&&) { return true; }).begin();
assert(ret == it(a.data()));
auto ret = std::ranges::find_last_if(it(a.begin()), sent(it(a.end())), [](auto&&) { return true; }).begin();
assert(ret == it(a.end()));
}
{
std::array<int, 0> a = {};

auto ret = std::ranges::find_last_if(make_range<it, sent>(a), [](auto&&) { return true; }).begin();
assert(ret == it(a.begin()));
assert(ret == it(a.end()));
}
}

Expand Down Expand Up @@ -183,8 +183,17 @@ struct NonConstComparable {
friend constexpr bool operator==(NonConstComparable&, const NonConstComparable&) { return true; }
};

// TODO: this should really use `std::const_iterator`
template <class T>
using add_const_to_ptr_t = std::add_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>;
struct add_const_to_ptr {
using type = T;
};
template <class T>
struct add_const_to_ptr<T*> {
using type = const T*;
};
template <class T>
using add_const_to_ptr_t = typename add_const_to_ptr<T>::type;

constexpr bool test() {
test_iterator_classes<std::type_identity_t, std::type_identity_t>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,14 @@ constexpr void test_iterator_classes() {
{
std::array<int, 0> a = {};

auto ret = std::ranges::find_last_if_not(it(a.data()), sent(it(a.data())), [](auto&&) { return false; }).begin();
assert(ret == it(a.data()));
auto ret = std::ranges::find_last_if_not(it(a.begin()), sent(it(a.end())), [](auto&&) { return false; }).begin();
assert(ret == it(a.end()));
}
{
std::array<int, 0> a = {};

auto ret = std::ranges::find_last_if_not(make_range<it, sent>(a), [](auto&&) { return false; }).begin();
assert(ret == it(a.begin()));
assert(ret == it(a.end()));
}
}

Expand Down Expand Up @@ -183,8 +183,17 @@ struct NonConstComparable {
friend constexpr bool operator!=(NonConstComparable&, const NonConstComparable&) { return false; }
};

// TODO: this should really use `std::const_iterator`
template <class T>
using add_const_to_ptr_t = std::add_pointer_t<std::add_const_t<std::remove_pointer_t<T>>>;
struct add_const_to_ptr {
using type = T;
};
template <class T>
struct add_const_to_ptr<T*> {
using type = const T*;
};
template <class T>
using add_const_to_ptr_t = typename add_const_to_ptr<T>::type;

constexpr bool test() {
test_iterator_classes<std::type_identity_t, std::type_identity_t>();
Expand Down
118 changes: 74 additions & 44 deletions libcxx/test/support/test_iterators.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,62 +339,92 @@ cpp20_random_access_iterator(It) -> cpp20_random_access_iterator<It>;

static_assert(std::random_access_iterator<cpp20_random_access_iterator<int*>>);

template <class It>
class contiguous_iterator
{
static_assert(std::is_pointer_v<It>, "Things probably break in this case");
template <std::contiguous_iterator It>
class contiguous_iterator {
It it_;

It it_;
template <std::contiguous_iterator U>
friend class contiguous_iterator;

template <class U> friend class contiguous_iterator;
public:
typedef std::contiguous_iterator_tag iterator_category;
typedef typename std::iterator_traits<It>::value_type value_type;
typedef typename std::iterator_traits<It>::difference_type difference_type;
typedef It pointer;
typedef typename std::iterator_traits<It>::reference reference;
typedef typename std::remove_pointer<It>::type element_type;
using iterator_category = std::contiguous_iterator_tag;
using value_type = typename std::iterator_traits<It>::value_type;
using difference_type = typename std::iterator_traits<It>::difference_type;
using pointer = typename std::iterator_traits<It>::pointer;
using reference = typename std::iterator_traits<It>::reference;
using element_type = value_type;

TEST_CONSTEXPR_CXX14 It base() const {return it_;}
constexpr It base() const { return it_; }

TEST_CONSTEXPR_CXX14 contiguous_iterator() : it_() {}
TEST_CONSTEXPR_CXX14 explicit contiguous_iterator(It it) : it_(it) {}
constexpr contiguous_iterator() : it_() {}
constexpr explicit contiguous_iterator(It it) : it_(it) {}

template <class U>
TEST_CONSTEXPR_CXX14 contiguous_iterator(const contiguous_iterator<U>& u) : it_(u.it_) {}
template <class U>
constexpr contiguous_iterator(const contiguous_iterator<U>& u) : it_(u.it_) {}

template <class U, class = typename std::enable_if<std::is_default_constructible<U>::value>::type>
constexpr contiguous_iterator(contiguous_iterator<U>&& u) : it_(u.it_) { u.it_ = U(); }
template <class U, class = typename std::enable_if<std::is_default_constructible<U>::value>::type>
constexpr contiguous_iterator(contiguous_iterator<U>&& u) : it_(u.it_) {
u.it_ = U();
}

TEST_CONSTEXPR reference operator*() const {return *it_;}
TEST_CONSTEXPR pointer operator->() const {return it_;}
TEST_CONSTEXPR reference operator[](difference_type n) const {return it_[n];}

TEST_CONSTEXPR_CXX14 contiguous_iterator& operator++() {++it_; return *this;}
TEST_CONSTEXPR_CXX14 contiguous_iterator& operator--() {--it_; return *this;}
TEST_CONSTEXPR_CXX14 contiguous_iterator operator++(int) {return contiguous_iterator(it_++);}
TEST_CONSTEXPR_CXX14 contiguous_iterator operator--(int) {return contiguous_iterator(it_--);}

TEST_CONSTEXPR_CXX14 contiguous_iterator& operator+=(difference_type n) {it_ += n; return *this;}
TEST_CONSTEXPR_CXX14 contiguous_iterator& operator-=(difference_type n) {it_ -= n; return *this;}
friend TEST_CONSTEXPR_CXX14 contiguous_iterator operator+(contiguous_iterator x, difference_type n) {x += n; return x;}
friend TEST_CONSTEXPR_CXX14 contiguous_iterator operator+(difference_type n, contiguous_iterator x) {x += n; return x;}
friend TEST_CONSTEXPR_CXX14 contiguous_iterator operator-(contiguous_iterator x, difference_type n) {x -= n; return x;}
friend TEST_CONSTEXPR difference_type operator-(contiguous_iterator x, contiguous_iterator y) {return x.it_ - y.it_;}

friend TEST_CONSTEXPR bool operator==(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ == y.it_;}
friend TEST_CONSTEXPR bool operator!=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ != y.it_;}
friend TEST_CONSTEXPR bool operator< (const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ < y.it_;}
friend TEST_CONSTEXPR bool operator<=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ <= y.it_;}
friend TEST_CONSTEXPR bool operator> (const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ > y.it_;}
friend TEST_CONSTEXPR bool operator>=(const contiguous_iterator& x, const contiguous_iterator& y) {return x.it_ >= y.it_;}
constexpr reference operator*() const { return *it_; }
constexpr pointer operator->() const { return it_; }
constexpr reference operator[](difference_type n) const { return it_[n]; }

constexpr contiguous_iterator& operator++() {
++it_;
return *this;
}
constexpr contiguous_iterator& operator--() {
--it_;
return *this;
}
constexpr contiguous_iterator operator++(int) { return contiguous_iterator(it_++); }
constexpr contiguous_iterator operator--(int) { return contiguous_iterator(it_--); }

constexpr contiguous_iterator& operator+=(difference_type n) {
it_ += n;
return *this;
}
constexpr contiguous_iterator& operator-=(difference_type n) {
it_ -= n;
return *this;
}
friend constexpr contiguous_iterator operator+(contiguous_iterator x, difference_type n) {
x += n;
return x;
}
friend constexpr contiguous_iterator operator+(difference_type n, contiguous_iterator x) {
x += n;
return x;
}
friend constexpr contiguous_iterator operator-(contiguous_iterator x, difference_type n) {
x -= n;
return x;
}
friend constexpr difference_type operator-(contiguous_iterator x, contiguous_iterator y) { return x.it_ - y.it_; }

friend constexpr bool operator==(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ == y.it_;
}
friend constexpr bool operator!=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ != y.it_;
}
friend constexpr bool operator<(const contiguous_iterator& x, const contiguous_iterator& y) { return x.it_ < y.it_; }
friend constexpr bool operator<=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ <= y.it_;
}
friend constexpr bool operator>(const contiguous_iterator& x, const contiguous_iterator& y) { return x.it_ > y.it_; }
friend constexpr bool operator>=(const contiguous_iterator& x, const contiguous_iterator& y) {
return x.it_ >= y.it_;
}

// Note no operator<=>, use three_way_contiguous_iterator for testing operator<=>

friend TEST_CONSTEXPR It base(const contiguous_iterator& i) { return i.it_; }
friend constexpr It base(const contiguous_iterator& i) { return i.it_; }

template <class T>
void operator,(T const &) = delete;
template <class T>
void operator,(T const&) = delete;
};
template <class It>
contiguous_iterator(It) -> contiguous_iterator<It>;
Expand Down
Loading