Skip to content
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

<ranges>: Fix truncation warnings and improve overflow check for repeat_view #4255

Merged
merged 6 commits into from
Jan 17, 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
16 changes: 14 additions & 2 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,12 @@ namespace ranges {

constexpr _Iterator& operator+=(difference_type _Off) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (sizeof(difference_type) > sizeof(_Index_type)) {
_STL_VERIFY(static_cast<_Index_type>(_Off) == _Off,
_Off > 0 ? "cannot advance repeat_view iterator past end (integer overflow)"
: "cannot advance repeat_view iterator before begin (integer overflow)");
}

if (_Off > 0) {
_STL_VERIFY(_Current <= (numeric_limits<_Index_type>::max)() - static_cast<_Index_type>(_Off),
"cannot advance repeat_view iterator past end (integer overflow)");
Expand All @@ -1557,11 +1563,17 @@ namespace ranges {
_STL_VERIFY(_Current + _Off >= 0, "cannot subtract below 0");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
_Current += _Off;
_Current += static_cast<_Index_type>(_Off);
return *this;
}
constexpr _Iterator& operator-=(difference_type _Off) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
if constexpr (sizeof(difference_type) > sizeof(_Index_type)) {
_STL_VERIFY(static_cast<_Index_type>(_Off) == _Off,
_Off < 0 ? "cannot advance repeat_view iterator past end (integer overflow)"
: "cannot advance repeat_view iterator before begin (integer overflow)");
}

if (_Off < 0) {
_STL_VERIFY(_Current <= (numeric_limits<_Index_type>::max)() + static_cast<_Index_type>(_Off),
"cannot advance repeat_view iterator past end (integer overflow)");
Expand All @@ -1574,7 +1586,7 @@ namespace ranges {
_STL_VERIFY(_Current - _Off >= 0, "cannot subtract below 0");
}
#endif // _CONTAINER_DEBUG_LEVEL > 0
_Current -= _Off;
_Current -= static_cast<_Index_type>(_Off);
return *this;
}
_NODISCARD constexpr const _Ty& operator[](difference_type _Idx) const noexcept {
Expand Down
4 changes: 0 additions & 4 deletions tests/libcxx/expected_results.txt
Original file line number Diff line number Diff line change
Expand Up @@ -525,10 +525,6 @@ std/time/time.clock/time.clock.file/ostream.pass.cpp FAIL
# LLVM-74727: [libc++] Should formatting year{-99} with %C produce "-1" or "-01"?
std/time/time.syn/formatter.year.pass.cpp:2 FAIL

# GH-4251: <ranges>: repeat_view<T, unsigned int> emits truncation warnings
std/ranges/range.factories/range.repeat.view/iterator/minus.pass.cpp:0 FAIL
std/ranges/range.factories/range.repeat.view/iterator/minus.pass.cpp:1 FAIL

# GH-4268: <sstream>, <syncstream>: Buffer types assume that allocated pointers are not modified by users
std/input.output/string.streams/stringbuf/stringbuf.members/str.pass.cpp FAIL
std/input.output/string.streams/stringbuf/stringbuf.members/view.pass.cpp FAIL
Expand Down
33 changes: 33 additions & 0 deletions tests/std/tests/P2474R2_views_repeat/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,18 @@ struct tuple_tester {
forward_tester z;
};


template <class IntLike>
constexpr void test_iterator_arithmetic() {
auto rv = views::repeat(0, IntLike{20u});
auto first = rv.begin();
auto last = rv.end();
assert(last - first == 20);
first += 2;
last -= 3;
assert(last - first == 15);
}

constexpr bool test() {
using namespace string_literals;

Expand Down Expand Up @@ -323,6 +335,27 @@ constexpr bool test() {
assert(to_copy.x == 1);
assert(to_move.x == 2);
}

// GH-4251: <ranges>: repeat_view<T, unsigned int> emits truncation warnings
test_iterator_arithmetic<unsigned char>();
test_iterator_arithmetic<unsigned short>();
test_iterator_arithmetic<unsigned int>();
test_iterator_arithmetic<unsigned long>();
test_iterator_arithmetic<unsigned long long>();
test_iterator_arithmetic<signed char>();
test_iterator_arithmetic<short>();
test_iterator_arithmetic<int>();
test_iterator_arithmetic<long>();
test_iterator_arithmetic<long long>();
test_iterator_arithmetic<char>();
#ifdef __cpp_char8_t
test_iterator_arithmetic<char8_t>();
#endif // defined(__cpp_char8_t)
test_iterator_arithmetic<char16_t>();
test_iterator_arithmetic<char32_t>();
test_iterator_arithmetic<wchar_t>();
test_iterator_arithmetic<_Signed128>();

return true;
}

Expand Down
58 changes: 58 additions & 0 deletions tests/std/tests/P2474R2_views_repeat_death/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,51 @@ void test_iter_add_neg_overflow() {
it += -1; // integer overflow
}

template <class I>
using iota_diff_t = ranges::range_difference_t<ranges::iota_view<I>>;

template <class U>
constexpr iota_diff_t<U> positive_huge_diff{iota_diff_t<U>{static_cast<U>(-1)} + 1};

template <class U>
constexpr iota_diff_t<U> negative_huge_diff{-iota_diff_t<U>{static_cast<U>(-1)} - 1};

template <class U>
void test_iter_add_pos_huge() {
auto rv = views::repeat(0, U{20u});
auto first = rv.begin();

using difference_type = ranges::range_difference_t<decltype(rv)>;
first += static_cast<difference_type>(positive_huge_diff<U>);
}

template <class U>
void test_iter_add_neg_huge() {
auto rv = views::repeat(0, U{20u});
auto first = rv.begin();

using difference_type = ranges::range_difference_t<decltype(rv)>;
first += static_cast<difference_type>(negative_huge_diff<U>);
}

template <class U>
void test_iter_sub_pos_huge() {
auto rv = views::repeat(0, U{20u});
auto first = rv.begin();

using difference_type = ranges::range_difference_t<decltype(rv)>;
first -= static_cast<difference_type>(positive_huge_diff<U>);
}

template <class U>
void test_iter_sub_neg_huge() {
auto rv = views::repeat(0, U{20u});
auto first = rv.begin();

using difference_type = ranges::range_difference_t<decltype(rv)>;
first -= static_cast<difference_type>(negative_huge_diff<U>);
}

int main(int argc, char* argv[]) {
std_testing::death_test_executive exec;

Expand All @@ -96,6 +141,19 @@ int main(int argc, char* argv[]) {
test_iter_add_zero,
test_iter_add_pos_overflow,
test_iter_add_neg_overflow,
// GH-4251: <ranges>: repeat_view<T, unsigned int> emits truncation warnings
test_iter_add_pos_huge<unsigned short>,
test_iter_add_pos_huge<unsigned int>,
test_iter_add_pos_huge<unsigned long long>,
test_iter_add_neg_huge<unsigned short>,
test_iter_add_neg_huge<unsigned int>,
test_iter_add_neg_huge<unsigned long long>,
test_iter_sub_pos_huge<unsigned short>,
test_iter_sub_pos_huge<unsigned int>,
test_iter_sub_pos_huge<unsigned long long>,
test_iter_sub_neg_huge<unsigned short>,
test_iter_sub_neg_huge<unsigned int>,
test_iter_sub_neg_huge<unsigned long long>,
});
return exec.run(argc, argv);
}