[libcxx-commits] [libcxx] [libc++][ranges] Applied [[nodiscard]] to `join_view` (PR #206838)
Lucas Mellone via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Jul 4 14:42:57 PDT 2026
https://github.com/lknknm updated https://github.com/llvm/llvm-project/pull/206838
>From 9f551657103ada7b335b878b39f7ecc7517701ef Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Tue, 30 Jun 2026 23:26:43 +0200
Subject: [PATCH 1/4] initial: nodiscard to join_view
---
libcxx/include/__ranges/join_view.h | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h
index 364f056d8d2cf..39c1d462695f0 100644
--- a/libcxx/include/__ranges/join_view.h
+++ b/libcxx/include/__ranges/join_view.h
@@ -100,15 +100,15 @@ class join_view : public view_interface<join_view<_View>> {
_LIBCPP_HIDE_FROM_ABI constexpr explicit join_view(_View __base) : __base_(std::move(__base)) {}
- _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 auto begin() {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() {
if constexpr (forward_range<_View>) {
constexpr bool __use_const = __simple_view<_View> && is_reference_v<range_reference_t<_View>>;
return __iterator<__use_const>{*this, ranges::begin(__base_)};
@@ -119,14 +119,14 @@ class join_view : public view_interface<join_view<_View>> {
}
template <class _V2 = _View>
- _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
requires forward_range<const _V2> && is_reference_v<range_reference_t<const _V2>> &&
input_range<range_reference_t<const _V2>>
{
return __iterator<true>{*this, ranges::begin(__base_)};
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto end() {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() {
if constexpr (forward_range<_View> && is_reference_v<_InnerRange> && forward_range<_InnerRange> &&
common_range<_View> && common_range<_InnerRange>)
return __iterator<__simple_view<_View>>{*this, ranges::end(__base_)};
@@ -135,7 +135,7 @@ class join_view : public view_interface<join_view<_View>> {
}
template <class _V2 = _View>
- _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
requires forward_range<const _V2> && is_reference_v<range_reference_t<const _V2>> &&
input_range<range_reference_t<const _V2>>
{
>From ac3a329c6283a20369a12c9e308ac91ceb3d1b23 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Wed, 1 Jul 2026 21:29:55 +0200
Subject: [PATCH 2/4] wip: initial tests proposal
---
libcxx/include/__ranges/join_view.h | 4 +-
.../range.join/nodiscard.verify.cpp | 63 +++++++++++++++++++
2 files changed, 65 insertions(+), 2 deletions(-)
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.join/nodiscard.verify.cpp
diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h
index 39c1d462695f0..c379b63975e4f 100644
--- a/libcxx/include/__ranges/join_view.h
+++ b/libcxx/include/__ranges/join_view.h
@@ -276,7 +276,7 @@ struct join_view<_View>::__iterator final : public __join_view_iterator_category
requires _Const && convertible_to<iterator_t<_View>, _Outer> && convertible_to<iterator_t<_InnerRange>, _Inner>
: __outer_(std::move(__i.__outer_)), __inner_(std::move(__i.__inner_)), __parent_(__i.__parent_) {}
- _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return **__inner_; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return **__inner_; }
_LIBCPP_HIDE_FROM_ABI constexpr _Inner operator->() const
requires __has_arrow<_Inner> && copyable<_Inner>
@@ -340,7 +340,7 @@ struct join_view<_View>::__iterator final : public __join_view_iterator_category
}
_LIBCPP_HIDE_FROM_ABI friend constexpr decltype(auto)
- iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__inner_))) {
+ [[nodiscard]] iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__inner_))) {
return ranges::iter_move(*__i.__inner_);
}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.join/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.join/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..6512d45a0b3ad
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.join/nodiscard.verify.cpp
@@ -0,0 +1,63 @@
+
+//===----------------------------------------------------------------------===//
+//
+// 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 the libc++ extension that std::ranges::join_view and std::views::view are marked as [[nodiscard]].
+
+#include <functional>
+#include <ranges>
+#include <string>
+#include <utility>
+#include <vector>
+
+struct InnerView : std::ranges::view_interface<InnerView> {
+ int* begin();
+ const int* begin() const;
+ volatile int* end();
+ const volatile int* end() const;
+};
+
+struct View : std::ranges::view_interface<View> {
+ InnerView* begin();
+ const InnerView* begin() const;
+ volatile InnerView* end();
+ const volatile InnerView* end() const;
+};
+static_assert(!std::ranges::common_range<View>);
+static_assert(!std::same_as<std::ranges::iterator_t<View>, std::ranges::iterator_t<const View>>);
+static_assert(!std::same_as<std::ranges::sentinel_t<View>, std::ranges::sentinel_t<const View>>);
+
+void test() {
+ auto v = View{} | std::views::join;
+
+ // [range.join.view]
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(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();
+
+ // [range.join.overview]
+
+ std::vector<std::string> ss{"hello", " ", "world", "!"};
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::join(ss);
+}
>From 0027333c05ad2d482a36d48a181f1b87a34bbcb1 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 4 Jul 2026 23:37:51 +0200
Subject: [PATCH 3/4] add: range.join.iterator nodiscard.verify tests
---
.../range.adaptors/range.join/nodiscard.verify.cpp | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.join/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.join/nodiscard.verify.cpp
index 6512d45a0b3ad..6a7a93cbe5e81 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.join/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.join/nodiscard.verify.cpp
@@ -54,6 +54,16 @@ void test() {
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::as_const(v).end();
+ // [range.join.iterator]
+
+ auto c_it = std::as_const(v).begin();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ *c_it;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ iter_move(c_it);
+
// [range.join.overview]
std::vector<std::string> ss{"hello", " ", "world", "!"};
>From 53193297ec56209e02e4cc128f3e213cfda80a24 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 4 Jul 2026 23:42:42 +0200
Subject: [PATCH 4/4] fix: nodiscard correction
---
libcxx/include/__ranges/join_view.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h
index c379b63975e4f..f80b75c839d4a 100644
--- a/libcxx/include/__ranges/join_view.h
+++ b/libcxx/include/__ranges/join_view.h
@@ -339,8 +339,8 @@ struct join_view<_View>::__iterator final : public __join_view_iterator_category
return __x.__outer_ == __y.__outer_ && __x.__inner_ == __y.__inner_;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr decltype(auto)
- [[nodiscard]] iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__inner_))) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr decltype(auto)
+ iter_move(const __iterator& __i) noexcept(noexcept(ranges::iter_move(*__i.__inner_))) {
return ranges::iter_move(*__i.__inner_);
}
More information about the libcxx-commits
mailing list