Skip to content

Commit 8630f6c

Browse files
some updates
1 parent 865f6d9 commit 8630f6c

File tree

3 files changed

+124
-27
lines changed

3 files changed

+124
-27
lines changed

a.log

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
-- Testing: 1 tests, 1 workers --
2+
PASS: llvm-libc++-shared.cfg.in :: libcxx/ranges/range.adaptors/range.concat/iterator.valueless_by_exception.pass.cpp (1 of 1)
3+
4+
Testing Time: 4.15s
5+
6+
Total Discovered Tests: 1
7+
Passed: 1 (100.00%)

libcxx/include/__ranges/concat_view.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ class concat_view<_Views...>::__iterator {
336336

337337
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i)
338338
requires _Const && (convertible_to<iterator_t<_Views>, iterator_t<const _Views>> && ...)
339-
: __it_([&__src = __i.it_]<size_t... _Indices>(size_t __idx, index_sequence<_Indices...>) -> __base_iter {
339+
: __it_([&__src = __i.__it_]<size_t... _Indices>(size_t __idx, index_sequence<_Indices...>) -> __base_iter {
340340
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
341341
!__src.valueless_by_exception(), "Trying to convert from a valueless iterator of concat_view.");
342342
using __src_lref = decltype((__src));
@@ -345,7 +345,7 @@ class concat_view<_Views...>::__iterator {
345345
return __base_iter(in_place_index<_Indices>, std::__unchecked_get<_Indices>(std::move(__src_var)));
346346
}...};
347347
return __vtable[__idx](__src);
348-
}(__i.index(), make_index_sequence<variant_size_v<__base_iter>>{})),
348+
}(__i.__it_.index(), make_index_sequence<variant_size_v<__base_iter>>{})),
349349
__parent_(__i.parent_) {}
350350

351351
_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const {

libcxx/test/libcxx/ranges/range.adaptors/range.concat/iterator.valueless_by_exception.pass.cpp

Lines changed: 115 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,56 +7,141 @@
77
//===----------------------------------------------------------------------===//
88

99
// REQUIRES: std-at-least-c++26
10-
// UNSUPPORTED: libcpp-hardening-mode=none, no-exceptions
10+
// UNSUPPORTED: no-exceptions
1111

12+
#include <iostream>
1213
#include <ranges>
1314
#include <utility>
15+
#include <vector>
1416

1517
#include "check_assertion.h"
18+
#include "double_move_tracker.h"
19+
#include "test_iterators.h"
1620

1721
int globalArray[8] = {0, 1, 2, 3, 4, 5, 6, 7};
1822

19-
struct ThrowOnCopyView : std::ranges::view_base {
20-
int start_;
21-
int* ptr_;
22-
constexpr explicit ThrowOnCopyView(int* ptr = globalArray, int start = 0) : start_(start), ptr_(ptr) {}
23-
constexpr ThrowOnCopyView(ThrowOnCopyView&&) = default;
24-
constexpr ThrowOnCopyView(const ThrowOnCopyView&) { throw 42; };
25-
constexpr ThrowOnCopyView& operator=(ThrowOnCopyView&&) = default;
26-
constexpr ThrowOnCopyView& operator=(const ThrowOnCopyView&) {
27-
throw 42;
28-
return *this;
29-
};
30-
constexpr int* begin() const { return ptr_ + start_; }
31-
constexpr int* end() const { return ptr_ + 8; }
23+
24+
template <class It, class ItTraits = It >
25+
class ThrowOnMoveIterator
26+
{
27+
typedef std::iterator_traits<ItTraits> Traits;
28+
It it_;
29+
support::double_move_tracker tracker_;
30+
bool moved = false;
31+
32+
template <class U, class T> friend class ThrowOnMoveIterator;
33+
public:
34+
typedef std::input_iterator_tag iterator_category;
35+
typedef typename Traits::value_type value_type;
36+
typedef typename Traits::difference_type difference_type;
37+
typedef It pointer;
38+
typedef typename Traits::reference reference;
39+
40+
constexpr ThrowOnMoveIterator() {}
41+
42+
constexpr ThrowOnMoveIterator(It it) : it_(it) {}
43+
44+
template <class U, class T>
45+
constexpr ThrowOnMoveIterator(const ThrowOnMoveIterator<U, T>& u) : it_(u.it_), tracker_(u.tracker_), moved(u.moved) {}
46+
47+
constexpr ThrowOnMoveIterator(const ThrowOnMoveIterator& other): moved(other.moved){}
48+
49+
constexpr ThrowOnMoveIterator(ThrowOnMoveIterator&& other){
50+
throw std::runtime_error("Move failed in iter");
51+
other.moved = true;
52+
moved = other.moved;
53+
}
54+
55+
ThrowOnMoveIterator& operator=(ThrowOnMoveIterator&& other) {
56+
if (other.moved) {
57+
throw std::runtime_error("Move assignment failed in iter");
58+
}
59+
other.moved = true;
60+
moved = other.moved;
61+
return *this;
62+
}
63+
64+
constexpr reference operator*() const {return *it_;}
65+
66+
constexpr ThrowOnMoveIterator& operator++() {++it_; return *this;}
67+
constexpr ThrowOnMoveIterator operator++(int) {return ThrowOnMoveIterator(it_++);}
68+
69+
friend constexpr bool operator==(const ThrowOnMoveIterator& x, const ThrowOnMoveIterator& y) {return x.it_ == y.it_;}
70+
friend constexpr bool operator!=(const ThrowOnMoveIterator& x, const ThrowOnMoveIterator& y) {return x.it_ != y.it_;}
71+
72+
friend constexpr It base(const ThrowOnMoveIterator& i) { return i.it_; }
73+
74+
template <class T>
75+
void operator,(T const &) = delete;
76+
};
77+
78+
template <class T>
79+
struct BufferView : std::ranges::view_base {
80+
T* buffer_;
81+
std::size_t size_;
82+
83+
template <std::size_t N>
84+
constexpr BufferView(T (&b)[N]) : buffer_(b), size_(N) {}
85+
};
86+
87+
using IntBufferView = BufferView<int>;
88+
89+
template <bool Simple>
90+
struct Common : IntBufferView {
91+
using IntBufferView::IntBufferView;
92+
using Iter = ThrowOnMoveIterator<int*>;
93+
using ConstIter = ThrowOnMoveIterator<const int*>;
94+
using Sent = sentinel_wrapper<Iter>;
95+
using ConstSent = sentinel_wrapper<ConstIter>;
96+
97+
constexpr Iter begin()
98+
requires(!Simple)
99+
{
100+
return Iter{buffer_};
101+
}
102+
constexpr const ConstIter begin() const { return ConstIter{buffer_}; }
103+
constexpr Sent end()
104+
requires(!Simple)
105+
{
106+
return Sent(buffer_ + size_);
107+
}
108+
constexpr ConstSent end() const { return ConstSent(buffer_ + size_); }
32109
};
33110

111+
using SimpleCommon = Common<true>;
112+
using NonSimpleCommon = Common<false>;
113+
34114
int main() {
115+
35116
{
36-
//valueless by exception test constructor
37-
std::ranges::concat_view<ThrowOnCopyView> concatView_2;
38-
std::ranges::iterator_t<std::ranges::concat_view<ThrowOnCopyView>> it1;
39-
std::ranges::iterator_t<std::ranges::concat_view<ThrowOnCopyView>> it2;
117+
int buffer[3] = {1, 2, 3};
118+
int buffer2[3] = {1, 2, 3};
119+
NonSimpleCommon view(buffer);
120+
NonSimpleCommon view2(buffer2);
121+
std::ranges::concat_view v(view, view2);
122+
std::ranges::iterator_t<std::ranges::concat_view<decltype(view), decltype(view2)>> it1;
40123
try {
41-
it1 = concatView_2.begin();
124+
it1 = v.begin();
42125
} catch (...) {
43126
TEST_LIBCPP_ASSERT_FAILURE(
44-
[&] {
45-
it2 = it1;
127+
[=] {
128+
std::ranges::iterator_t<const decltype(v)> it2(v.begin());
46129
(void)it2;
47130
}(),
48131
"valueless by exception");
49132
}
50133
}
51-
134+
/*
52135
{
53136
//valueless by exception test operator==
54-
std::ranges::concat_view<ThrowOnCopyView> concatView_2;
55-
std::ranges::iterator_t<std::ranges::concat_view<ThrowOnCopyView>> it1;
56-
std::ranges::iterator_t<std::ranges::concat_view<ThrowOnCopyView>> it2;
137+
ThrowingRange<int*> throwing{3, 5};
138+
auto concatView_2 = std::views::concat(throwing);
139+
decltype(concatView_2.begin()) it1{};
140+
decltype(concatView_2.begin()) it2{};
57141
try {
58142
it1 = concatView_2.begin();
59143
} catch (...) {
144+
std::cout << "Catch is hit" << std::endl;
60145
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)(it1 == it2); }(), "valueless by exception");
61146
}
62147
}
@@ -68,6 +153,7 @@ int main() {
68153
try {
69154
it1 = concatView_2.begin();
70155
} catch (...) {
156+
std::cout << "Catch is hit" << std::endl;
71157
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)--*it1; }(), "valueless by exception");
72158
}
73159
}
@@ -79,6 +165,7 @@ int main() {
79165
try {
80166
it1 = concatView_2.begin();
81167
} catch (...) {
168+
std::cout << "Catch is hit" << std::endl;
82169
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)*it1; }(), "valueless by exception");
83170
}
84171
}
@@ -90,6 +177,7 @@ int main() {
90177
try {
91178
it1 = concatView_2.begin();
92179
} catch (...) {
180+
std::cout << "Catch is hit" << std::endl;
93181
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)++*it1; }(), "valueless by exception");
94182
}
95183
}
@@ -101,7 +189,9 @@ int main() {
101189
try {
102190
it1 = concatView_2.begin();
103191
} catch (...) {
192+
std::cout << "Catch is hit" << std::endl;
104193
TEST_LIBCPP_ASSERT_FAILURE([&] { (void)(it1 += 1); }(), "valueless by exception");
105194
}
106195
}
196+
*/
107197
}

0 commit comments

Comments
 (0)