[libcxx-commits] [libcxx] [libc++][ranges] Applied `[[nodiscard]]` to `all`, `owning_view`, `ref_view` (PR #173708)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Fri Dec 26 22:02:43 PST 2025


https://github.com/H-G-Hristov created https://github.com/llvm/llvm-project/pull/173708

`[[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.all

Towards #172124

>From 32fdde61d67889c803c45ef1e3aaf82519ecf38b Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 27 Dec 2025 08:02:16 +0200
Subject: [PATCH] [libc++][ranges] Applied `[[nodiscard]]` to `all`,
 `owning_view`, `ref_view`

`[[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.all

Towards #172124
---
 libcxx/include/__ranges/owning_view.h         | 30 +++----
 libcxx/include/__ranges/ref_view.h            | 12 +--
 .../range.all/all.nodiscard.verify.cpp        | 21 -----
 .../range.all/nodiscard.verify.cpp            | 83 +++++++++++++++++++
 4 files changed, 104 insertions(+), 42 deletions(-)
 delete mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.all/all.nodiscard.verify.cpp
 create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.all/nodiscard.verify.cpp

diff --git a/libcxx/include/__ranges/owning_view.h b/libcxx/include/__ranges/owning_view.h
index 254bdb4329119..1ab81afee774a 100644
--- a/libcxx/include/__ranges/owning_view.h
+++ b/libcxx/include/__ranges/owning_view.h
@@ -49,52 +49,52 @@ class owning_view : public view_interface<owning_view<_Rp>> {
   _LIBCPP_HIDE_FROM_ABI owning_view(owning_view&&)            = default;
   _LIBCPP_HIDE_FROM_ABI owning_view& operator=(owning_view&&) = default;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _Rp& base() & noexcept { return __r_; }
-  _LIBCPP_HIDE_FROM_ABI constexpr const _Rp& base() const& noexcept { return __r_; }
-  _LIBCPP_HIDE_FROM_ABI constexpr _Rp&& base() && noexcept { return std::move(__r_); }
-  _LIBCPP_HIDE_FROM_ABI constexpr const _Rp&& base() const&& noexcept { return std::move(__r_); }
-
-  _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Rp> begin() { return ranges::begin(__r_); }
-  _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Rp> end() { return ranges::end(__r_); }
-  _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Rp& base() & noexcept { return __r_; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Rp& base() const& noexcept { return __r_; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Rp&& base() && noexcept { return std::move(__r_); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Rp&& base() const&& noexcept { return std::move(__r_); }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Rp> begin() { return ranges::begin(__r_); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Rp> end() { return ranges::end(__r_); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
     requires range<const _Rp>
   {
     return ranges::begin(__r_);
   }
-  _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
     requires range<const _Rp>
   {
     return ranges::end(__r_);
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
     requires requires { ranges::empty(__r_); }
   {
     return ranges::empty(__r_);
   }
-  _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
     requires requires { ranges::empty(__r_); }
   {
     return ranges::empty(__r_);
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size()
     requires sized_range<_Rp>
   {
     return ranges::size(__r_);
   }
-  _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
     requires sized_range<const _Rp>
   {
     return ranges::size(__r_);
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr auto data()
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto data()
     requires contiguous_range<_Rp>
   {
     return ranges::data(__r_);
   }
-  _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
     requires contiguous_range<const _Rp>
   {
     return ranges::data(__r_);
diff --git a/libcxx/include/__ranges/ref_view.h b/libcxx/include/__ranges/ref_view.h
index 5329d778dd30d..109a10cec299e 100644
--- a/libcxx/include/__ranges/ref_view.h
+++ b/libcxx/include/__ranges/ref_view.h
@@ -51,24 +51,24 @@ class ref_view : public view_interface<ref_view<_Range>> {
   _LIBCPP_HIDE_FROM_ABI constexpr ref_view(_Tp&& __t)
       : __range_(std::addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) {}
 
-  _LIBCPP_HIDE_FROM_ABI constexpr _Range& base() const { return *__range_; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Range& base() const { return *__range_; }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Range> begin() const { return ranges::begin(*__range_); }
-  _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Range> end() const { return ranges::end(*__range_); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Range> begin() const { return ranges::begin(*__range_); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Range> end() const { return ranges::end(*__range_); }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
     requires requires { ranges::empty(*__range_); }
   {
     return ranges::empty(*__range_);
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
     requires sized_range<_Range>
   {
     return ranges::size(*__range_);
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto data() const
     requires contiguous_range<_Range>
   {
     return ranges::data(*__range_);
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.all/all.nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.all/all.nodiscard.verify.cpp
deleted file mode 100644
index 43b9ebf60f2a0..0000000000000
--- a/libcxx/test/libcxx/ranges/range.adaptors/range.all/all.nodiscard.verify.cpp
+++ /dev/null
@@ -1,21 +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
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// Test the libc++ extension that std::views::all is marked as [[nodiscard]].
-
-#include <ranges>
-
-void test() {
-  int range[] = {1, 2, 3};
-
-  std::views::all(range); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-  range | std::views::all; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::views::all | std::views::all; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-}
diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.all/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.all/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..eaa739ca87c13
--- /dev/null
+++ b/libcxx/test/libcxx/ranges/range.adaptors/range.all/nodiscard.verify.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 that functions are marked as [[nodiscard]].
+
+#include <ranges>
+#include <vector>
+#include <utility>
+
+void test() {
+  std::vector<int> range;
+
+  { // [range.all.general]
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::views::all(range);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    range | std::views::all;
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::views::all | std::views::all;
+  }
+
+  { // [range.owning.view]
+    std::ranges::owning_view v{std::ranges::subrange(range)};
+
+    // 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::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}}
+    std::move(std::as_const(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}}
+    v.end();
+    // 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}}
+    std::as_const(v).end();
+
+    // 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.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.data();
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::as_const(v).data();
+  }
+
+  { // [range.ref.view]
+    std::ranges::ref_view v{range};
+
+    // 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}}
+    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}}
+    v.size();
+
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    v.data();
+  }
+}



More information about the libcxx-commits mailing list