[libcxx-commits] [libcxx] [libc++][ranges] Applied `[[nodiscard]]` to `reverse_view` (PR #205186)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jun 22 14:10:56 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Hristo Hristov (H-G-Hristov)
<details>
<summary>Changes</summary>
Towards #<!-- -->172124
#References:
- https://wg21.link/range.reverse
- https://libcxx.llvm.org/CodingGuidelines.html#apply-nodiscard-where-relevant
---
Full diff: https://github.com/llvm/llvm-project/pull/205186.diff
3 Files Affected:
- (modified) libcxx/include/__ranges/reverse_view.h (+8-8)
- (removed) libcxx/test/libcxx/ranges/range.adaptors/range.reverse/adaptor.nodiscard.verify.cpp (-21)
- (added) libcxx/test/libcxx/ranges/range.adaptors/range.reverse/nodiscard.verify.cpp (+99)
``````````diff
diff --git a/libcxx/include/__ranges/reverse_view.h b/libcxx/include/__ranges/reverse_view.h
index c36ba77dd8f6d..b016cc231f2b5 100644
--- a/libcxx/include/__ranges/reverse_view.h
+++ b/libcxx/include/__ranges/reverse_view.h
@@ -59,13 +59,13 @@ class reverse_view : public view_interface<reverse_view<_View>> {
_LIBCPP_HIDE_FROM_ABI constexpr explicit reverse_view(_View __view) : __base_(std::move(__view)) {}
- _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
requires copy_constructible<_View>
{
return __base_;
}
- _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
_LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> begin() {
if constexpr (_UseCache)
@@ -78,35 +78,35 @@ class reverse_view : public view_interface<reverse_view<_View>> {
return __tmp;
}
- _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> begin()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> begin()
requires common_range<_View>
{
return std::make_reverse_iterator(ranges::end(__base_));
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
requires common_range<const _View>
{
return std::make_reverse_iterator(ranges::end(__base_));
}
- _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> end() {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator<iterator_t<_View>> end() {
return std::make_reverse_iterator(ranges::begin(__base_));
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
requires common_range<const _View>
{
return std::make_reverse_iterator(ranges::begin(__base_));
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size()
requires sized_range<_View>
{
return ranges::size(__base_);
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
requires sized_range<const _View>
{
return ranges::size(__base_);
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.reverse/adaptor.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.reverse/adaptor.nodiscard.verify.cpp
deleted file mode 100644
index 2f7eb94611928..0000000000000
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.reverse/adaptor.nodiscard.verify.cpp
+++ /dev/null
@@ -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::reverse is marked as [[nodiscard]].
-
-#include <ranges>
-
-void test() {
- int range[] = {1, 2, 3};
-
- std::views::reverse(range); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- range | std::views::reverse; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- std::views::all | std::views::reverse; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.reverse/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.reverse/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..6dfa2f5d17c60
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.reverse/nodiscard.verify.cpp
@@ -0,0 +1,99 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// Check that functions are marked [[nodiscard]]
+
+#include <ranges>
+#include <utility>
+
+#include "test_iterators.h"
+
+void test() {
+ int range[] = {19, 28, 29, 49, 82, 94};
+ auto v = std::views::reverse(range);
+
+ // [range.reverse.view]
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.base();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::move(v).base();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.begin();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(v).begin();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.end();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(v).end();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.size();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(v).size();
+
+ // [range.reverse.overview]
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::reverse(std::views::reverse(range));
+
+ struct BidirRange : std::ranges::view_base {
+ int* begin_;
+ int* end_;
+
+ constexpr BidirRange(int* b, int* e) : begin_(b), end_(e) {}
+
+ constexpr bidirectional_iterator<int*> begin() { return bidirectional_iterator<int*>{begin_}; }
+ constexpr bidirectional_iterator<const int*> begin() const { return bidirectional_iterator<const int*>{begin_}; }
+ constexpr bidirectional_iterator<int*> end() { return bidirectional_iterator<int*>{end_}; }
+ constexpr bidirectional_iterator<const int*> end() const { return bidirectional_iterator<const int*>{end_}; }
+ };
+ static_assert(std::ranges::bidirectional_range<BidirRange>);
+ static_assert(std::ranges::common_range<BidirRange>);
+ static_assert(std::ranges::view<BidirRange>);
+ static_assert(std::copyable<BidirRange>);
+
+ { // views::reverse(x) is equivalent to subrange{end, begin, size} if x is a
+ // sized subrange over reverse iterators
+ using It = bidirectional_iterator<int*>;
+ using Subrange = std::ranges::subrange<It, It, std::ranges::subrange_kind::sized>;
+
+ using ReverseIt = std::reverse_iterator<It>;
+ using ReverseSubrange = std::ranges::subrange<ReverseIt, ReverseIt, std::ranges::subrange_kind::sized>;
+
+ BidirRange view(range, range + 6);
+ ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */ 6);
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::reverse(subrange);
+ }
+ { // views::reverse(x) is equivalent to subrange{end, begin} if x is an
+ // unsized subrange over reverse iterators
+ using It = bidirectional_iterator<int*>;
+ using Subrange = std::ranges::subrange<It, It, std::ranges::subrange_kind::unsized>;
+
+ using ReverseIt = std::reverse_iterator<It>;
+ using ReverseSubrange = std::ranges::subrange<ReverseIt, ReverseIt, std::ranges::subrange_kind::unsized>;
+
+ BidirRange view(range, range + 6);
+ ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::reverse(subrange);
+ }
+ { // Otherwise, views::reverse(x) is equivalent to ranges::reverse_view{x}
+ BidirRange view(range, range + 6);
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::reverse(view);
+ }
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/205186
More information about the libcxx-commits
mailing list