[libcxx-commits] [libcxx] [libc++] Added `[[nodiscard]]` to `fstream.native_handle`, `span.at` and `in/out_ptr` (PR #167097)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Sat Nov 8 09:03:12 PST 2025


https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/167097

>From ea08a3c757dadff14d847c9a8b7b2df54eb0f717 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 8 Nov 2025 07:55:22 +0200
Subject: [PATCH] [libc++] Added `[[nodiscard]]` to `fstream.native_handle`,
 `span.at` and `in/out_ptr`

...according to Coding Guidelines: `[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue.

At the time of impelentation the ``nodiscard` policy has not been established yet. I did it as a batch as the changes are trivial and minimal.
---
 libcxx/include/__memory/inout_ptr.h           |  2 +-
 libcxx/include/__memory/out_ptr.h             |  2 +-
 libcxx/include/fstream                        | 14 +++++---
 libcxx/include/span                           |  4 +--
 .../views/views.span/nodiscard.verify.cpp     | 30 ++++++++++++++++
 .../fstreams/nodiscard.verify.cpp             | 34 +++++++++++++++++++
 .../smartptr/adapt/nodiscard.verify.cpp       | 23 +++++++++++++
 7 files changed, 101 insertions(+), 8 deletions(-)
 create mode 100644 libcxx/test/libcxx/containers/views/views.span/nodiscard.verify.cpp
 create mode 100644 libcxx/test/libcxx/input.output/file.streams/fstreams/nodiscard.verify.cpp
 create mode 100644 libcxx/test/libcxx/utilities/smartptr/adapt/nodiscard.verify.cpp

diff --git a/libcxx/include/__memory/inout_ptr.h b/libcxx/include/__memory/inout_ptr.h
index ef345fe469bca..0fa685afb2ee6 100644
--- a/libcxx/include/__memory/inout_ptr.h
+++ b/libcxx/include/__memory/inout_ptr.h
@@ -96,7 +96,7 @@ class inout_ptr_t {
 };
 
 template <class _Pointer = void, class _Smart, class... _Args>
-_LIBCPP_HIDE_FROM_ABI auto inout_ptr(_Smart& __s, _Args&&... __args) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto inout_ptr(_Smart& __s, _Args&&... __args) {
   using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>;
   return std::inout_ptr_t<_Smart, _Ptr, _Args&&...>(__s, std::forward<_Args>(__args)...);
 }
diff --git a/libcxx/include/__memory/out_ptr.h b/libcxx/include/__memory/out_ptr.h
index e498e3307b9d6..23a77f6a0f7e9 100644
--- a/libcxx/include/__memory/out_ptr.h
+++ b/libcxx/include/__memory/out_ptr.h
@@ -88,7 +88,7 @@ class out_ptr_t {
 };
 
 template <class _Pointer = void, class _Smart, class... _Args>
-_LIBCPP_HIDE_FROM_ABI auto out_ptr(_Smart& __s, _Args&&... __args) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto out_ptr(_Smart& __s, _Args&&... __args) {
   using _Ptr = conditional_t<is_void_v<_Pointer>, __pointer_of_t<_Smart>, _Pointer>;
   return std::out_ptr_t<_Smart, _Ptr, _Args&&...>(__s, std::forward<_Args>(__args)...);
 }
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 1f88d134fe061..2371e460ddf9e 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -269,7 +269,7 @@ public:
   _LIBCPP_HIDE_FROM_ABI basic_filebuf* __open(int __fd, ios_base::openmode __mode);
   basic_filebuf* close();
 #    if _LIBCPP_STD_VER >= 26
-  _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
     _LIBCPP_ASSERT_UNCATEGORIZED(this->is_open(), "File must be opened");
 #      if defined(_LIBCPP_WIN32API)
     return std::__filebuf_windows_native_handle(__file_);
@@ -1165,7 +1165,9 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const;
 #    if _LIBCPP_STD_VER >= 26
-  _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept { return rdbuf()->native_handle(); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
+    return rdbuf()->native_handle();
+  }
 #    endif
   _LIBCPP_HIDE_FROM_ABI bool is_open() const;
   void open(const char* __s, ios_base::openmode __mode = ios_base::in);
@@ -1321,7 +1323,9 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const;
 #    if _LIBCPP_STD_VER >= 26
-  _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept { return rdbuf()->native_handle(); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
+    return rdbuf()->native_handle();
+  }
 #    endif
   _LIBCPP_HIDE_FROM_ABI bool is_open() const;
   void open(const char* __s, ios_base::openmode __mode = ios_base::out);
@@ -1483,7 +1487,9 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI basic_filebuf<char_type, traits_type>* rdbuf() const;
 #    if _LIBCPP_STD_VER >= 26
-  _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept { return rdbuf()->native_handle(); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() const noexcept {
+    return rdbuf()->native_handle();
+  }
 #    endif
   _LIBCPP_HIDE_FROM_ABI bool is_open() const;
   _LIBCPP_HIDE_FROM_ABI void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
diff --git a/libcxx/include/span b/libcxx/include/span
index 3d4f9e4ba7831..68fa3d5987310 100644
--- a/libcxx/include/span
+++ b/libcxx/include/span
@@ -362,7 +362,7 @@ public:
   }
 
 #    if _LIBCPP_STD_VER >= 26
-  _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
     if (__index >= size())
       std::__throw_out_of_range("span");
     return __data_[__index];
@@ -527,7 +527,7 @@ public:
   }
 
 #    if _LIBCPP_STD_VER >= 26
-  _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
     if (__index >= size())
       std::__throw_out_of_range("span");
     return __data_[__index];
diff --git a/libcxx/test/libcxx/containers/views/views.span/nodiscard.verify.cpp b/libcxx/test/libcxx/containers/views/views.span/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..6deec90aa0f00
--- /dev/null
+++ b/libcxx/test/libcxx/containers/views/views.span/nodiscard.verify.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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++26
+
+// <span>
+
+// Check that functions are marked [[nodiscard]]
+
+#include <array>
+#include <span>
+#include <vector>
+
+void test() {
+  { // Test with static extent
+    std::array arr{94, 92};
+    std::span sp{arr};
+    sp.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  { // Test with dynamic extent
+    std::vector vec{94, 92};
+    std::span sp{vec};
+    sp.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+}
diff --git a/libcxx/test/libcxx/input.output/file.streams/fstreams/nodiscard.verify.cpp b/libcxx/test/libcxx/input.output/file.streams/fstreams/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..4aeef4141693c
--- /dev/null
+++ b/libcxx/test/libcxx/input.output/file.streams/fstreams/nodiscard.verify.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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++26
+
+// <fstream>
+
+// Check that functions are marked [[nodiscard]]
+
+#include <fstream>
+
+void test() {
+  {
+    std::filebuf fb;
+    fb.native_handle(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  {
+    std::fstream fs;
+    fs.native_handle(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  {
+    std::ifstream fs;
+    fs.native_handle(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  {
+    std::ofstream fs;
+    fs.native_handle(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+}
diff --git a/libcxx/test/libcxx/utilities/smartptr/adapt/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/smartptr/adapt/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..c026594f58d71
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/smartptr/adapt/nodiscard.verify.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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++23
+
+// <memory>
+
+// Check that functions are marked [[nodiscard]]
+
+#include <memory>
+
+void test() {
+  std::unique_ptr<int> uPtr;
+  // [inout.ptr]
+  std::inout_ptr(uPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  // [out.ptr]
+  std::out_ptr(uPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+}



More information about the libcxx-commits mailing list