[libc++][ranges] Applied [[nodiscard]] to owning_view, ref_view (#173708)

`[[nodiscard]]` should be applied to functions where discarding the
return value is most likely a correctness issue.

- https://libcxx.llvm.org/CodingGuidelines.html
- https://wg21.link/range.all

Towards #172124
This commit is contained in:
Hristo Hristov 2025-12-29 18:45:24 +02:00 committed by GitHub
parent 4c0360753e
commit ed539afe49
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 103 additions and 41 deletions

View File

@ -49,52 +49,52 @@ public:
_LIBCPP_HIDE_FROM_ABI owning_view(owning_view&&) = default;
_LIBCPP_HIDE_FROM_ABI owning_view& operator=(owning_view&&) = default;
_LIBCPP_HIDE_FROM_ABI constexpr _Rp& base() & noexcept { return __r_; }
_LIBCPP_HIDE_FROM_ABI constexpr const _Rp& base() const& noexcept { return __r_; }
_LIBCPP_HIDE_FROM_ABI constexpr _Rp&& base() && noexcept { return std::move(__r_); }
_LIBCPP_HIDE_FROM_ABI constexpr const _Rp&& base() const&& noexcept { return std::move(__r_); }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Rp& base() & noexcept { return __r_; }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Rp& base() const& noexcept { return __r_; }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Rp&& base() && noexcept { return std::move(__r_); }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Rp&& base() const&& noexcept { return std::move(__r_); }
_LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Rp> begin() { return ranges::begin(__r_); }
_LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Rp> end() { return ranges::end(__r_); }
_LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Rp> begin() { return ranges::begin(__r_); }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Rp> end() { return ranges::end(__r_); }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
requires range<const _Rp>
{
return ranges::begin(__r_);
}
_LIBCPP_HIDE_FROM_ABI constexpr auto end() const
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
requires range<const _Rp>
{
return ranges::end(__r_);
}
_LIBCPP_HIDE_FROM_ABI constexpr bool empty()
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
requires requires { ranges::empty(__r_); }
{
return ranges::empty(__r_);
}
_LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
requires requires { ranges::empty(__r_); }
{
return ranges::empty(__r_);
}
_LIBCPP_HIDE_FROM_ABI constexpr auto size()
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size()
requires sized_range<_Rp>
{
return ranges::size(__r_);
}
_LIBCPP_HIDE_FROM_ABI constexpr auto size() const
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
requires sized_range<const _Rp>
{
return ranges::size(__r_);
}
_LIBCPP_HIDE_FROM_ABI constexpr auto data()
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto data()
requires contiguous_range<_Rp>
{
return ranges::data(__r_);
}
_LIBCPP_HIDE_FROM_ABI constexpr auto data() const
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
requires contiguous_range<const _Rp>
{
return ranges::data(__r_);

View File

@ -51,24 +51,24 @@ public:
_LIBCPP_HIDE_FROM_ABI constexpr ref_view(_Tp&& __t)
: __range_(std::addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) {}
_LIBCPP_HIDE_FROM_ABI constexpr _Range& base() const { return *__range_; }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Range& base() const { return *__range_; }
_LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Range> begin() const { return ranges::begin(*__range_); }
_LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Range> end() const { return ranges::end(*__range_); }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Range> begin() const { return ranges::begin(*__range_); }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Range> end() const { return ranges::end(*__range_); }
_LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
requires requires { ranges::empty(*__range_); }
{
return ranges::empty(*__range_);
}
_LIBCPP_HIDE_FROM_ABI constexpr auto size() const
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
requires sized_range<_Range>
{
return ranges::size(*__range_);
}
_LIBCPP_HIDE_FROM_ABI constexpr auto data() const
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
requires contiguous_range<_Range>
{
return ranges::data(*__range_);

View File

@ -1,21 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// Test the libc++ extension that std::views::all is marked as [[nodiscard]].
#include <ranges>
void test() {
int range[] = {1, 2, 3};
std::views::all(range); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
range | std::views::all; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::views::all | std::views::all; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
}

View File

@ -0,0 +1,83 @@
//===----------------------------------------------------------------------===//
//
// 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 as [[nodiscard]].
#include <ranges>
#include <vector>
#include <utility>
void test() {
std::vector<int> range;
{ // [range.all.general]
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::views::all(range);
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
range | std::views::all;
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::views::all | std::views::all;
}
{ // [range.owning.view]
std::ranges::owning_view v{std::ranges::subrange(range)};
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.base();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::as_const(v).base();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::move(v).base();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::move(std::as_const(v)).base();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.begin();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.end();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::as_const(v).begin();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::as_const(v).end();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.empty();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::as_const(v).empty();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.size();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::as_const(v).size();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.data();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::as_const(v).data();
}
{ // [range.ref.view]
std::ranges::ref_view v{range};
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.base();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.begin();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.end();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.size();
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
v.data();
}
}