[libcxx-commits] [libcxx] [libc++][ranges] Applied [[nodiscard]] to `adjacent_view` (PR #205206)
Lucas Mellone via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Jun 27 06:15:00 PDT 2026
https://github.com/lknknm updated https://github.com/llvm/llvm-project/pull/205206
>From ac484ba7e5d1d4a952002aff17a9b988383e4ff5 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Tue, 23 Jun 2026 00:30:35 +0200
Subject: [PATCH 01/17] wip: initial nodiscard apply
---
libcxx/include/__ranges/adjacent_view.h | 36 +++++++++++++------------
1 file changed, 19 insertions(+), 17 deletions(-)
diff --git a/libcxx/include/__ranges/adjacent_view.h b/libcxx/include/__ranges/adjacent_view.h
index 40474b85c794f..e3052d48fdac5 100644
--- a/libcxx/include/__ranges/adjacent_view.h
+++ b/libcxx/include/__ranges/adjacent_view.h
@@ -81,26 +81,26 @@ class adjacent_view : public view_interface<adjacent_view<_View, _Np>> {
_LIBCPP_HIDE_FROM_ABI constexpr explicit adjacent_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()
requires(!__simple_view<_View>)
{
return __iterator<false>(ranges::begin(__base_), ranges::end(__base_));
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
requires range<const _View> // LWG4482 This is under-constrained.
{
return __iterator<true>(ranges::begin(__base_), ranges::end(__base_));
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto end()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end()
requires(!__simple_view<_View>)
{
if constexpr (common_range<_View>) {
@@ -110,7 +110,7 @@ class adjacent_view : public view_interface<adjacent_view<_View, _Np>> {
}
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
requires range<const _View> // LWG4482 This is under-constrained.
{
if constexpr (common_range<const _View>) {
@@ -120,7 +120,7 @@ class adjacent_view : public view_interface<adjacent_view<_View, _Np>> {
}
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size()
requires sized_range<_View>
{
using _ST = decltype(ranges::size(__base_));
@@ -130,7 +130,7 @@ class adjacent_view : public view_interface<adjacent_view<_View, _Np>> {
return static_cast<_ST>(__sz);
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
requires sized_range<const _View>
{
using _ST = decltype(ranges::size(__base_));
@@ -143,7 +143,7 @@ class adjacent_view : public view_interface<adjacent_view<_View, _Np>> {
struct __adjacent_view_iter_access {
template <class _Iter>
- _LIBCPP_HIDE_FROM_ABI constexpr static auto& __get_current(_Iter& __it) noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr static auto& __get_current(_Iter& __it) noexcept {
return __it.__current_;
}
};
@@ -157,13 +157,14 @@ class adjacent_view<_View, _Np>::__iterator {
using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _View>;
array<iterator_t<_Base>, _Np> __current_ = array<iterator_t<_Base>, _Np>();
- _LIBCPP_HIDE_FROM_ABI constexpr __iterator(iterator_t<_Base> __first, sentinel_t<_Base> __last) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __iterator(iterator_t<_Base> __first, sentinel_t<_Base> __last) {
__current_[0] = __first;
for (size_t __i = 1; __i < _Np; ++__i) {
__current_[__i] = ranges::next(__current_[__i - 1], 1, __last);
}
}
+ [[nodiscard]]
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(__as_sentinel, iterator_t<_Base> __first, iterator_t<_Base> __last) {
if constexpr (!bidirectional_range<_Base>) {
__current_.fill(__last);
@@ -257,7 +258,7 @@ class adjacent_view<_View, _Np>::__iterator {
return *this;
}
- _LIBCPP_HIDE_FROM_ABI constexpr auto operator[](difference_type __n) const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator[](difference_type __n) const
requires random_access_range<_Base>
{
return std::__tuple_transform([&](auto& __i) -> decltype(auto) { return __i[__n]; }, __current_);
@@ -297,7 +298,7 @@ class adjacent_view<_View, _Np>::__iterator {
return __x.__current_.back() <=> __y.__current_.back();
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __i, difference_type __n)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __i, difference_type __n)
requires random_access_range<_Base>
{
auto __r = __i;
@@ -305,13 +306,13 @@ class adjacent_view<_View, _Np>::__iterator {
return __r;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, const __iterator& __i)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, const __iterator& __i)
requires random_access_range<_Base>
{
return __i + __n;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __i, difference_type __n)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __i, difference_type __n)
requires random_access_range<_Base>
{
auto __r = __i;
@@ -319,7 +320,8 @@ class adjacent_view<_View, _Np>::__iterator {
return __r;
}
- _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type
+ operator-(const __iterator& __x, const __iterator& __y)
requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
{
return __x.__current_.back() - __y.__current_.back();
@@ -389,12 +391,12 @@ template <size_t _Np>
struct __fn : __range_adaptor_closure<__fn<_Np>> {
template <class _Range>
requires(_Np == 0 && forward_range<_Range &&>)
- _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&&) noexcept {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Range&&) noexcept {
return empty_view<tuple<>>{};
}
template <class _Ranges>
- _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ranges&& __range) noexcept(
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()(_Ranges&& __range) noexcept(
noexcept(adjacent_view<views::all_t<_Ranges&&>, _Np>(std::forward<_Ranges>(__range))))
-> decltype(adjacent_view<views::all_t<_Ranges&&>, _Np>(std::forward<_Ranges>(__range))) {
return adjacent_view<views::all_t<_Ranges&&>, _Np>(std::forward<_Ranges>(__range));
>From 0658b8de94319d0f5ab15b0effff5054ced745d9 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Tue, 23 Jun 2026 22:36:30 +0200
Subject: [PATCH 02/17] wip: complete nodiscard to adjacent_view.h; tests
remaining
---
libcxx/include/__ranges/adjacent_view.h | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/libcxx/include/__ranges/adjacent_view.h b/libcxx/include/__ranges/adjacent_view.h
index e3052d48fdac5..efc113b1f4d39 100644
--- a/libcxx/include/__ranges/adjacent_view.h
+++ b/libcxx/include/__ranges/adjacent_view.h
@@ -86,6 +86,7 @@ class adjacent_view : public view_interface<adjacent_view<_View, _Np>> {
{
return __base_;
}
+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
@@ -180,7 +181,7 @@ class adjacent_view<_View, _Np>::__iterator {
_LIBCPP_HIDE_FROM_ABI explicit constexpr __iterator(_Iter&& __i, index_sequence<_Is...>)
: __current_{std::move(__i.__current_[_Is])...} {}
- static consteval auto __get_iterator_concept() {
+ [[nodiscard]] static consteval auto __get_iterator_concept() {
if constexpr (random_access_range<_Base>)
return random_access_iterator_tag{};
else if constexpr (bidirectional_range<_Base>)
@@ -206,7 +207,7 @@ class adjacent_view<_View, _Np>::__iterator {
requires _Const && convertible_to<iterator_t<_View>, iterator_t<const _View>>
: __iterator(std::move(__i), make_index_sequence<_Np>{}) {}
- _LIBCPP_HIDE_FROM_ABI constexpr auto operator*() const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator*() const {
return std::__tuple_transform([](auto& __i) -> decltype(auto) { return *__i; }, __current_);
}
@@ -368,15 +369,15 @@ class adjacent_view<_View, _Np>::__sentinel {
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
- _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
return __x.__current_.back() - __y.__end_;
}
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
- _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
- operator-(const __sentinel& __y, const __iterator<_OtherConst>& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
+ operator-(const __sentinel & __y, const __iterator<_OtherConst>& __x) {
return __y.__end_ - __x.__current_.back();
}
};
>From 5d963629251c787691c3799d62553c33f8497828 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Tue, 23 Jun 2026 23:11:13 +0200
Subject: [PATCH 03/17] add: test file
---
.../range.adjacent/nodiscard.verify.cpp | 11 +++++++++++
1 file changed, 11 insertions(+)
create mode 100644 libcxx/test/std/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
diff --git a/libcxx/test/std/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/std/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..fae42d0e5ccaa
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -0,0 +1,11 @@
+//===----------------------------------------------------------------------===//
+//
+// 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::adjacent_view and std::views::adjacent are marked as [[nodiscard]].
>From 34f7490155246de57581731191026bcab66936a1 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Tue, 23 Jun 2026 23:39:13 +0200
Subject: [PATCH 04/17] move: nodiscard test folder
---
.../range.adjacent/nodiscard.verify.cpp | 35 +++++++++++++++++++
.../range.adjacent/nodiscard.verify.cpp | 11 ------
2 files changed, 35 insertions(+), 11 deletions(-)
create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..fcbbe3605fe31
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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::adjacent_view and std::views::adjacent are marked as [[nodiscard]].
+#include <ranges>
+#include <utility>
+#include <functional>
+
+#include "test_iterators.h"
+
+template<size_t N>
+ requires (N > 0)
+struct NonCommonSimpleView<N> : std::ranges::adjacent_view<NonCommonSimpleView, N> {
+ int* begin();
+ int* begin() const;
+ sized_sentinel<int*> end();
+ sized_sentinel<int*> end() const;
+};
+
+static_assert(!std::ranges::common_range<View>);
+static_assert(
+ std::same_as<std::ranges::iterator_t<NonCommonSimpleView>, std::ranges::iterator_t<const NonCommonSimpleView>>);
+static_assert(
+ std::same_as<std::ranges::sentinel_t<NonCommonSimpleView>, std::ranges::sentinel_t<const NonCommonSimpleView>>);
+
+void test() {
+ auto v = NonCommonSimpleView<2>{} | std::views::transform(std::identity{});
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/std/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
deleted file mode 100644
index fae42d0e5ccaa..0000000000000
--- a/libcxx/test/std/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ /dev/null
@@ -1,11 +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
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++20
-
-// Test the libc++ extension that std::ranges::adjacent_view and std::views::adjacent are marked as [[nodiscard]].
>From 5106b0aaa8a7d1d417b502f3e5c8519e0912e252 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Wed, 24 Jun 2026 20:56:15 +0200
Subject: [PATCH 05/17] fix: view for tests
---
.../range.adjacent/nodiscard.verify.cpp | 26 +++++--------------
1 file changed, 7 insertions(+), 19 deletions(-)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index fcbbe3605fe31..f9eb228cd55ec 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -11,25 +11,13 @@
// Test the libc++ extension that std::ranges::adjacent_view and std::views::adjacent are marked as [[nodiscard]].
#include <ranges>
#include <utility>
-#include <functional>
-
-#include "test_iterators.h"
-
-template<size_t N>
- requires (N > 0)
-struct NonCommonSimpleView<N> : std::ranges::adjacent_view<NonCommonSimpleView, N> {
- int* begin();
- int* begin() const;
- sized_sentinel<int*> end();
- sized_sentinel<int*> end() const;
-};
-
-static_assert(!std::ranges::common_range<View>);
-static_assert(
- std::same_as<std::ranges::iterator_t<NonCommonSimpleView>, std::ranges::iterator_t<const NonCommonSimpleView>>);
-static_assert(
- std::same_as<std::ranges::sentinel_t<NonCommonSimpleView>, std::ranges::sentinel_t<const NonCommonSimpleView>>);
void test() {
- auto v = NonCommonSimpleView<2>{} | std::views::transform(std::identity{});
+ int range[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ auto v = range | std::views::adjacent<2>;
+
+ // 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();
}
>From 7ed49fb8ae31e5cae5d325dc64b9553a841627fb Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Wed, 24 Jun 2026 21:35:49 +0200
Subject: [PATCH 06/17] add: iterator tests. remove mistaken nodiscard from
ctor
---
libcxx/include/__ranges/adjacent_view.h | 7 ++--
.../range.adjacent/nodiscard.verify.cpp | 39 +++++++++++++++++++
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/__ranges/adjacent_view.h b/libcxx/include/__ranges/adjacent_view.h
index efc113b1f4d39..847efcaedf711 100644
--- a/libcxx/include/__ranges/adjacent_view.h
+++ b/libcxx/include/__ranges/adjacent_view.h
@@ -158,14 +158,13 @@ class adjacent_view<_View, _Np>::__iterator {
using _Base _LIBCPP_NODEBUG = __maybe_const<_Const, _View>;
array<iterator_t<_Base>, _Np> __current_ = array<iterator_t<_Base>, _Np>();
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __iterator(iterator_t<_Base> __first, sentinel_t<_Base> __last) {
+ _LIBCPP_HIDE_FROM_ABI constexpr __iterator(iterator_t<_Base> __first, sentinel_t<_Base> __last) {
__current_[0] = __first;
for (size_t __i = 1; __i < _Np; ++__i) {
__current_[__i] = ranges::next(__current_[__i - 1], 1, __last);
}
}
- [[nodiscard]]
_LIBCPP_HIDE_FROM_ABI constexpr __iterator(__as_sentinel, iterator_t<_Base> __first, iterator_t<_Base> __last) {
if constexpr (!bidirectional_range<_Base>) {
__current_.fill(__last);
@@ -376,8 +375,8 @@ class adjacent_view<_View, _Np>::__sentinel {
template <bool _OtherConst>
requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
- operator-(const __sentinel & __y, const __iterator<_OtherConst>& __x) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
+ operator-(const __sentinel& __y, const __iterator<_OtherConst>& __x) {
return __y.__end_ - __x.__current_.back();
}
};
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index f9eb228cd55ec..4e64b32b8fcf7 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -16,8 +16,47 @@ void test() {
int range[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto v = range | std::views::adjacent<2>;
+ // [range.adjacent.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();
+
+ // 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.adjacent.iterator]
+
+ auto it = v.begin();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::ranges::__adjacent_view_iter_access::__get_current(it);
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ *it;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it[0];
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(it)[0];
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it + 0;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 0 + it;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it - 0;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it - it;
}
>From d99e0ed03bdc5841c893d29768fcb4774ee189da Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Wed, 24 Jun 2026 22:27:23 +0200
Subject: [PATCH 07/17] add: sentinel tests
---
.../range.adjacent/nodiscard.verify.cpp | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index 4e64b32b8fcf7..8c4f6d619879f 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -59,4 +59,21 @@ void test() {
it - 0;
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
it - it;
+
+ // [range.adjacent.sentinel]
+
+ auto st = v.end();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it - st;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ st - it;
+
+ auto c_it = std::as_const(v).begin();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ st - c_it;
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ c_it - st;
+
}
>From e3f2651a69c1001b7653d72879c5f95e63f5b30c Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Wed, 24 Jun 2026 22:46:05 +0200
Subject: [PATCH 08/17] add: CPO tests
---
.../range.adaptors/range.adjacent/nodiscard.verify.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index 8c4f6d619879f..3c3a2aa2cef0e 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -76,4 +76,11 @@ void test() {
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
c_it - st;
+ // [range.adjacent.overview]
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::adjacent<0>(range);
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::views::adjacent<2>(range);
}
>From ebbcbffcbc754d4551e11673f8b92f80a508d045 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Wed, 24 Jun 2026 22:50:18 +0200
Subject: [PATCH 09/17] fix: clang-format
---
.../ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index 3c3a2aa2cef0e..a9c88fc357a11 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -77,7 +77,7 @@ void test() {
c_it - st;
// [range.adjacent.overview]
-
+
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::views::adjacent<0>(range);
>From 909c2248e2a430dcc7ec951366368240bf8c227a Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 25 Jun 2026 14:26:24 +0200
Subject: [PATCH 10/17] Update
libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
Co-authored-by: A. Jiang <de34 at live.cn>
---
.../ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index a9c88fc357a11..949257f7547bd 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: std-at-least-c++20
+// REQUIRES: std-at-least-c++23
// Test the libc++ extension that std::ranges::adjacent_view and std::views::adjacent are marked as [[nodiscard]].
#include <ranges>
>From 27ba9e49f3086f25612f4b64f4a0e327a6dd0920 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 25 Jun 2026 14:26:34 +0200
Subject: [PATCH 11/17] Update
libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
Co-authored-by: A. Jiang <de34 at live.cn>
---
.../ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index 949257f7547bd..c08d126ff9c43 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -9,6 +9,7 @@
// REQUIRES: std-at-least-c++23
// Test the libc++ extension that std::ranges::adjacent_view and std::views::adjacent are marked as [[nodiscard]].
+
#include <ranges>
#include <utility>
>From 80aca1f254d9ee268a212beb7e606f3b57306212 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Thu, 25 Jun 2026 19:30:07 +0200
Subject: [PATCH 12/17] remove: nodiscard from __get_current
---
libcxx/include/__ranges/adjacent_view.h | 2 +-
.../ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp | 3 ---
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/libcxx/include/__ranges/adjacent_view.h b/libcxx/include/__ranges/adjacent_view.h
index 847efcaedf711..8bab32d6f5811 100644
--- a/libcxx/include/__ranges/adjacent_view.h
+++ b/libcxx/include/__ranges/adjacent_view.h
@@ -144,7 +144,7 @@ class adjacent_view : public view_interface<adjacent_view<_View, _Np>> {
struct __adjacent_view_iter_access {
template <class _Iter>
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr static auto& __get_current(_Iter& __it) noexcept {
+ _LIBCPP_HIDE_FROM_ABI constexpr static auto& __get_current(_Iter& __it) noexcept {
return __it.__current_;
}
};
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index c08d126ff9c43..6838bb868c741 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -43,9 +43,6 @@ void test() {
auto it = v.begin();
- // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
- std::ranges::__adjacent_view_iter_access::__get_current(it);
-
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
*it;
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
>From 15b96e804e37f08205e7c863d0f2227b6292a334 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <sxswt at protonmail.com>
Date: Thu, 25 Jun 2026 20:19:15 +0200
Subject: [PATCH 13/17] add: non-common non-simple view
---
.../range.adjacent/nodiscard.verify.cpp | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index 6838bb868c741..aa768f7048027 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -13,9 +13,19 @@
#include <ranges>
#include <utility>
+struct View : std::ranges::view_interface<View> {
+ int* begin();
+ const int* begin() const;
+ volatile int* end();
+ const volatile int* 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() {
int range[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
- auto v = range | std::views::adjacent<2>;
+ auto v = View{} | std::views::adjacent<2>;
// [range.adjacent.view]
>From 1efa498fc98a7e651c49707acc609a04e24dd592 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 25 Jun 2026 23:42:06 +0200
Subject: [PATCH 14/17] Apply suggestions from code review
Co-authored-by: Hristo Hristov <zingam at outlook.com>
---
libcxx/include/__ranges/adjacent_view.h | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libcxx/include/__ranges/adjacent_view.h b/libcxx/include/__ranges/adjacent_view.h
index 8bab32d6f5811..7bb873cba82d4 100644
--- a/libcxx/include/__ranges/adjacent_view.h
+++ b/libcxx/include/__ranges/adjacent_view.h
@@ -88,7 +88,6 @@ class adjacent_view : public view_interface<adjacent_view<_View, _Np>> {
}
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
-
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
requires(!__simple_view<_View>)
{
@@ -180,7 +179,7 @@ class adjacent_view<_View, _Np>::__iterator {
_LIBCPP_HIDE_FROM_ABI explicit constexpr __iterator(_Iter&& __i, index_sequence<_Is...>)
: __current_{std::move(__i.__current_[_Is])...} {}
- [[nodiscard]] static consteval auto __get_iterator_concept() {
+ static consteval auto __get_iterator_concept() {
if constexpr (random_access_range<_Base>)
return random_access_iterator_tag{};
else if constexpr (bidirectional_range<_Base>)
>From 49376cd394313246c3aae38a2a3e6600768bafc0 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Thu, 25 Jun 2026 23:58:58 +0200
Subject: [PATCH 15/17] fix: minor clang-format issue
---
libcxx/include/__ranges/adjacent_view.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__ranges/adjacent_view.h b/libcxx/include/__ranges/adjacent_view.h
index 7bb873cba82d4..ac1366adb4efc 100644
--- a/libcxx/include/__ranges/adjacent_view.h
+++ b/libcxx/include/__ranges/adjacent_view.h
@@ -179,7 +179,7 @@ class adjacent_view<_View, _Np>::__iterator {
_LIBCPP_HIDE_FROM_ABI explicit constexpr __iterator(_Iter&& __i, index_sequence<_Is...>)
: __current_{std::move(__i.__current_[_Is])...} {}
- static consteval auto __get_iterator_concept() {
+ static consteval auto __get_iterator_concept() {
if constexpr (random_access_range<_Base>)
return random_access_iterator_tag{};
else if constexpr (bidirectional_range<_Base>)
>From 9decffed3663adc6385063fd659c89cd26526890 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Fri, 26 Jun 2026 10:07:49 +0200
Subject: [PATCH 16/17] fix: remove std::as_const(it)[0] test
---
.../ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index aa768f7048027..84bece7705c47 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -58,8 +58,6 @@ void test() {
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
it[0];
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
- std::as_const(it)[0];
- // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
it + 0;
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
0 + it;
>From e72b5fecbe36a18b78682af25b4cc9fbbac804c3 Mon Sep 17 00:00:00 2001
From: Lucas Mellone <github.snugness349 at passinbox.com>
Date: Sat, 27 Jun 2026 15:14:40 +0200
Subject: [PATCH 17/17] Apply suggestion from @Zingam
Co-authored-by: Hristo Hristov <zingam at outlook.com>
---
.../range.adaptors/range.adjacent/nodiscard.verify.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
index 84bece7705c47..73b2895ceddb3 100644
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adjacent/nodiscard.verify.cpp
@@ -52,11 +52,12 @@ void test() {
// [range.adjacent.iterator]
auto it = v.begin();
+ auto c_it = std::as_const(v).begin();
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
- *it;
+ *c_it;
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
- it[0];
+ c_it[0];
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
it + 0;
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
More information about the libcxx-commits
mailing list