[libcxx-commits] [libcxx] [libc++][ranges] Applied `[[nodiscard]]` to `view_interface` (PR #174360)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jan 4 22:14:12 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libcxx
Author: Hristo Hristov (H-G-Hristov)
<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/view.interface
Towards #<!-- -->172124
---
Full diff: https://github.com/llvm/llvm-project/pull/174360.diff
2 Files Affected:
- (modified) libcxx/include/__ranges/view_interface.h (+10-10)
- (added) libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp (+74)
``````````diff
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..872c9fa515891
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// 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() noexcept;
+ int* end() noexcept;
+ const int* begin() const noexcept;
+ const int* end() const noexcept;
+};
+
+template <>
+inline constexpr bool std::ranges::enable_view<View> = true;
+
+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}];
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/174360
More information about the libcxx-commits
mailing list