Skip to content

Commit

Permalink
<ranges>: Fix truncation warnings and improve overflow check for `r…
Browse files Browse the repository at this point in the history
…epeat_view` (#4255)

Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
  • Loading branch information
frederick-vs-ja and StephanTLavavej authored Jan 17, 2024
1 parent bbd15b3 commit c902810
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 6 deletions.
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);
}

0 comments on commit c902810

Please sign in to comment.