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

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Dec 26 22:03:14 PST 2025


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/range.all

Towards #<!-- -->172124

---
Full diff: https://github.com/llvm/llvm-project/pull/173708.diff


4 Files Affected:

- (modified) libcxx/include/__ranges/owning_view.h (+15-15) 
- (modified) libcxx/include/__ranges/ref_view.h (+6-6) 
- (removed) libcxx/test/libcxx/ranges/range.adaptors/range.all/all.nodiscard.verify.cpp (-21) 
- (added) libcxx/test/libcxx/ranges/range.adaptors/range.all/nodiscard.verify.cpp (+83) 


``````````diff
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();
+  }
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/173708


More information about the libcxx-commits mailing list