[libcxx-commits] [libcxx] [libc++][ranges] Applied `[[nodiscard]]` to `view_interface` (PR #174360)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jan 4 22:31:46 PST 2026
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/174360
>From 701e3332534e18f47518120474d1245bb008f748 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 25 Dec 2025 20:54:02 +0200
Subject: [PATCH] [libc++][ranges] Applied `[[nodiscard]]` to `view_interface`
`[[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/view.interface
Towards #172124
---
libcxx/include/__ranges/view_interface.h | 20 +++---
.../view.interface/nodiscard.verify.cpp | 71 +++++++++++++++++++
2 files changed, 81 insertions(+), 10 deletions(-)
create mode 100644 libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
diff --git a/libcxx/include/__ranges/view_interface.h b/libcxx/include/__ranges/view_interface.h
index 3bcfbaf3a2f9e..37b2c9e2c1a75 100644
--- a/libcxx/include/__ranges/view_interface.h
+++ b/libcxx/include/__ranges/view_interface.h
@@ -87,35 +87,35 @@ class view_interface {
}
template <class _D2 = _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr auto data()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto data()
requires contiguous_iterator<iterator_t<_D2>>
{
return std::to_address(ranges::begin(__derived()));
}
template <class _D2 = _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>>
{
return std::to_address(ranges::begin(__derived()));
}
template <class _D2 = _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size()
requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
{
return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived()));
}
template <class _D2 = _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
{
return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived()));
}
template <class _D2 = _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front()
requires forward_range<_D2>
{
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
@@ -124,7 +124,7 @@ class view_interface {
}
template <class _D2 = _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front() const
requires forward_range<const _D2>
{
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
@@ -133,7 +133,7 @@ class view_interface {
}
template <class _D2 = _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back()
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back()
requires bidirectional_range<_D2> && common_range<_D2>
{
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
@@ -142,7 +142,7 @@ class view_interface {
}
template <class _D2 = _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back() const
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back() const
requires bidirectional_range<const _D2> && common_range<const _D2>
{
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
@@ -151,12 +151,12 @@ class view_interface {
}
template <random_access_range _RARange = _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) {
return ranges::begin(__derived())[__index];
}
template <random_access_range _RARange = const _Derived>
- _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const {
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const {
return ranges::begin(__derived())[__index];
}
};
diff --git a/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..a79189b6e391d
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <cstddef>
+#include <ranges>
+#include <utility>
+
+struct View : std::ranges::view_interface<View> {
+ int* begin();
+ int* end();
+ const int* begin() const;
+ const int* end() const;
+};
+
+static_assert(std::ranges::sized_range<View>);
+static_assert(std::ranges::sized_range<const View>);
+static_assert(std::contiguous_iterator<std::ranges::iterator_t<View>>);
+static_assert(std::contiguous_iterator<std::ranges::iterator_t<const View>>);
+static_assert(std::ranges::forward_range<View>);
+static_assert(std::ranges::forward_range<const View>);
+static_assert(std::sized_sentinel_for<std::ranges::sentinel_t<View>, std::ranges::iterator_t<View>>);
+static_assert(std::sized_sentinel_for<std::ranges::sentinel_t<const View>, std::ranges::iterator_t<const View>>);
+static_assert(std::ranges::bidirectional_range<View>);
+static_assert(std::ranges::bidirectional_range<const View>);
+static_assert(std::ranges::common_range<View>);
+static_assert(std::ranges::common_range<const View>);
+
+void test() {
+ View v;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.empty();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(v).empty();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.data();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(v).data();
+
+ // 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();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.front();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(v).front();
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.back();
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(v).back();
+
+ using Diff = std::ranges::range_difference_t<View>;
+
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v[Diff{0}];
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(v)[Diff{0}];
+}
More information about the libcxx-commits
mailing list