[libc++][ranges] Updated [[nodiscard]] implementation for subrange and join_with_view (#176936)
Added or removed `[[nodiscard]]` according to the guidelines and updated the tests. - https://libcxx.llvm.org/CodingGuidelines.html - https://wg21.link/range.subrange - https://wg21.link/range.join.with.view Towards #172124
This commit is contained in:
parent
84882630c1
commit
b232970172
@ -372,7 +372,7 @@ public:
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
|
||||
requires __ref_is_glvalue && forward_range<_Base> && equality_comparable<_InnerIter>
|
||||
{
|
||||
return __x.__outer_it_ == __y.__outer_it_ && __x.__inner_it_ == __y.__inner_it_;
|
||||
@ -420,8 +420,7 @@ public:
|
||||
|
||||
template <bool _OtherConst>
|
||||
requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr bool
|
||||
operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
|
||||
return __get_outer_of(__x) == __y.__end_;
|
||||
}
|
||||
};
|
||||
|
||||
@ -131,7 +131,7 @@ public:
|
||||
return _Pair(__begin_, __end_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() const
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() const
|
||||
requires copyable<_Iter>
|
||||
{
|
||||
return __begin_;
|
||||
@ -143,11 +143,11 @@ public:
|
||||
return std::move(__begin_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Sent end() const { return __end_; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Sent end() const { return __end_; }
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __begin_ == __end_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const
|
||||
requires(_Kind == subrange_kind::sized)
|
||||
{
|
||||
if constexpr (_StoreSize)
|
||||
@ -214,7 +214,7 @@ subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>)
|
||||
|
||||
template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
|
||||
requires((_Index == 0 && copyable<_Iter>) || _Index == 1)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) {
|
||||
if constexpr (_Index == 0)
|
||||
return __subrange.begin();
|
||||
else
|
||||
@ -223,7 +223,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __
|
||||
|
||||
template <size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
|
||||
requires(_Index < 2)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) {
|
||||
if constexpr (_Index == 0)
|
||||
return __subrange.begin();
|
||||
else
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
|
||||
// Test that functions are marked [[nodiscard]].
|
||||
|
||||
#include <array>
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
|
||||
@ -23,77 +22,37 @@ void test() {
|
||||
|
||||
std::ranges::join_with_view view(range, pattern);
|
||||
|
||||
// clang-format off
|
||||
view.base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(view).base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move(std::as_const(view)).base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move(view).base(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
// clang-format on
|
||||
// [range.join.with.view]
|
||||
|
||||
// clang-format off
|
||||
view.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(view).begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
// clang-format on
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(view).base();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move(view).base();
|
||||
|
||||
// clang-format off
|
||||
view.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(view).end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void test_iterator() {
|
||||
char range[3][2] = {{'x', 'x'}, {'y', 'y'}, {'z', 'z'}};
|
||||
char pattern[2] = {',', ' '};
|
||||
|
||||
std::ranges::join_with_view view(range, pattern);
|
||||
|
||||
// clang-format off
|
||||
*view.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
*std::as_const(view).begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
(view.begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
(std::as_const(view).begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
(view.begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
(std::as_const(view).begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
// clang-format on
|
||||
|
||||
// clang-format off
|
||||
iter_move(view.begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
iter_move(std::as_const(view).begin()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void test_sentinel() {
|
||||
std::array<test_range<cpp20_input_iterator>, 0> range;
|
||||
std::array<int, 0> pattern;
|
||||
|
||||
std::ranges::join_with_view view(range, pattern);
|
||||
static_assert(!std::ranges::common_range<decltype(view)>);
|
||||
|
||||
// clang-format off
|
||||
(view.begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
(std::as_const(view).begin() == view.end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
(view.begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
(std::as_const(view).begin() == std::as_const(view).end()); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
void test_overview() {
|
||||
int range[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
|
||||
int pattern_base[2] = {-1, -1};
|
||||
auto pattern = std::views::all(pattern_base);
|
||||
|
||||
// clang-format off
|
||||
std::views::join_with(pattern); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::views::join_with(range, pattern); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
range | std::views::join_with(pattern); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::views::reverse | std::views::join_with(pattern); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
|
||||
std::views::join_with(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::views::join_with(range, 0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
range | std::views::join_with(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::views::reverse | std::views::join_with(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
// clang-format on
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
view.begin();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(view).begin();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
view.end();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(view).end();
|
||||
|
||||
// [range.join.with.iterator]
|
||||
|
||||
auto cIt = std::as_const(view).begin();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
*cIt;
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
iter_move(cIt);
|
||||
|
||||
// [range.join.with.overview]
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::views::join_with(range, pattern);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::views::join_with(pattern);
|
||||
}
|
||||
|
||||
@ -0,0 +1,75 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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: std-at-least-c++20
|
||||
|
||||
// Test that functions are marked [[nodiscard]].
|
||||
|
||||
#include <ranges>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
struct MoveOnlyIterator {
|
||||
using iterator_concept = std::input_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using value_type = int;
|
||||
|
||||
MoveOnlyIterator() = default;
|
||||
|
||||
MoveOnlyIterator(MoveOnlyIterator&&) = default;
|
||||
MoveOnlyIterator& operator=(MoveOnlyIterator&&) = default;
|
||||
|
||||
MoveOnlyIterator(const MoveOnlyIterator&) = delete;
|
||||
MoveOnlyIterator& operator=(const MoveOnlyIterator&) = delete;
|
||||
|
||||
int operator*() const;
|
||||
|
||||
MoveOnlyIterator& operator++();
|
||||
|
||||
void operator++(int);
|
||||
|
||||
friend bool operator==(const MoveOnlyIterator&, std::default_sentinel_t);
|
||||
};
|
||||
static_assert(std::input_iterator<MoveOnlyIterator>);
|
||||
static_assert(!std::copyable<MoveOnlyIterator>);
|
||||
|
||||
void test() {
|
||||
std::vector<int> range;
|
||||
std::ranges::subrange subrange{range.begin(), range.end()};
|
||||
|
||||
MoveOnlyIterator it;
|
||||
auto moveOnlySubrange = std::ranges::subrange(std::move(it), std::default_sentinel);
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(subrange).begin();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move(moveOnlySubrange).begin();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(subrange).end();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(subrange).empty();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(subrange).size();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(subrange).next();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move(subrange).next();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::as_const(subrange).prev();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move(subrange).prev();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<0>(std::as_const(subrange));
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<0>(std::move(subrange));
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user