[libcxx-commits] [libcxx] [libc++][ranges] Applied [[nodiscard]] to `lazy_split` (PR #208036)
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jul 8 21:13:27 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Lucas Mellone (lknknm)
<details>
<summary>Changes</summary>
[[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.lazy.split
Towards https://github.com/llvm/llvm-project/issues/172124
---
Full diff: https://github.com/llvm/llvm-project/pull/208036.diff
2 Files Affected:
- (modified) libcxx/include/__ranges/lazy_split_view.h (+17-13)
- (added) libcxx/test/libcxx/ranges/range.adaptors/range.lazy.split/nodiscard.verify.cpp (+79)
``````````diff
diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h
index 938dca24cc4fc..27a9d5e77abf1 100644
--- a/libcxx/include/__ranges/lazy_split_view.h
+++ b/libcxx/include/__ranges/lazy_split_view.h
@@ -95,14 +95,14 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
_LIBCPP_HIDE_FROM_ABI constexpr explicit lazy_split_view(_Range&& __r, range_value_t<_Range> __e)
: __base_(views::all(std::forward<_Range>(__r))), __pattern_(views::single(std::move(__e))) {}
- _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>) {
return __outer_iterator < __simple_view<_View> && __simple_view < _Pattern >> {*this, ranges::begin(__base_)};
} else {
@@ -111,19 +111,19 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
}
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
requires forward_range<_View> && forward_range<const _View>
{
return __outer_iterator<true>{*this, ranges::begin(__base_)};
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto end()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end()
requires forward_range<_View> && common_range<_View>
{
return __outer_iterator < __simple_view<_View> && __simple_view < _Pattern >> {*this, ranges::end(__base_)};
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto end() const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const {
if constexpr (forward_range<_View> && forward_range<const _View> && common_range<const _View>) {
return __outer_iterator<true>{*this, ranges::end(__base_)};
} else {
@@ -188,8 +188,10 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
_LIBCPP_HIDE_FROM_ABI value_type() = default;
_LIBCPP_HIDE_FROM_ABI constexpr explicit value_type(__outer_iterator __i) : __i_(std::move(__i)) {}
- _LIBCPP_HIDE_FROM_ABI constexpr __inner_iterator<_Const> begin() const { return __inner_iterator<_Const>{__i_}; }
- _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __inner_iterator<_Const> begin() const {
+ return __inner_iterator<_Const>{__i_};
+ }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr default_sentinel_t end() const noexcept { return default_sentinel; }
};
_LIBCPP_HIDE_FROM_ABI __outer_iterator() = default;
@@ -206,7 +208,7 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
: __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {}
- _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return value_type{*this}; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr value_type operator*() const { return value_type{*this}; }
_LIBCPP_HIDE_FROM_ABI constexpr __outer_iterator& operator++() {
const auto __end = ranges::end(__parent_->__base_);
@@ -342,14 +344,16 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
_LIBCPP_HIDE_FROM_ABI constexpr explicit __inner_iterator(__outer_iterator<_Const> __i) : __i_(std::move(__i)) {}
- _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __i_.__current(); }
- _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() &&
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept {
+ return __i_.__current();
+ }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() &&
requires forward_range<_View>
{
return std::move(__i_.__current());
}
- _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__i_.__current(); }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__i_.__current(); }
_LIBCPP_HIDE_FROM_ABI constexpr __inner_iterator& operator++() {
__incremented_ = true;
@@ -385,7 +389,7 @@ class lazy_split_view : public view_interface<lazy_split_view<_View, _Pattern>>
return __x.__is_done();
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr decltype(auto)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr decltype(auto)
iter_move(const __inner_iterator& __i) noexcept(noexcept(ranges::iter_move(__i.__outer_current()))) {
return ranges::iter_move(__i.__outer_current());
}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.lazy.split/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.lazy.split/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..aa33b8ce42331
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.lazy.split/nodiscard.verify.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// 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::lazy_split_view and std::views::lazy_split are marked as [[nodiscard]].
+
+#include <ranges>
+#include <string>
+#include <utility>
+
+void test() {
+ std::string str = "the quick brown fox";
+ char pattern = ' ';
+
+ auto v = std::views::lazy_split(str, pattern);
+
+ // [range.lazy.split.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();
+
+ // [range.lazy.split.outer]
+
+ auto outer_it = as_const(v).begin();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ *outer_it;
+
+ // [range.lazy.split.outer.value]
+
+ auto value = *outer_it;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ value.begin();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ value.end();
+
+ // [range.lazy.split.outer.inner]
+
+ auto inner_it = value.begin();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ inner_it.base();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::move(inner_it).base();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ *inner_it;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ iter_move(inner_it);
+
+ // [range.lazy.split.overview]
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::lazy_split(str, pattern);
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::lazy_split(pattern);
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/208036
More information about the libcxx-commits
mailing list