[libcxx-commits] [libcxx] [libc++][ios] Applied `[[nodiscard]]` (PR #173520)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Dec 24 18:54:51 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: A. Jiang (frederick-vs-ja)

<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.htm
- https://wg21.link/iostreams.base

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


3 Files Affected:

- (modified) libcxx/include/__ios/fpos.h (+5-5) 
- (modified) libcxx/include/ios (+24-24) 
- (added) libcxx/test/libcxx/input.output/iostreams.base/nodiscard.verify.cpp (+74) 


``````````diff
diff --git a/libcxx/include/__ios/fpos.h b/libcxx/include/__ios/fpos.h
index e5c21b439188c..655158c6f2d89 100644
--- a/libcxx/include/__ios/fpos.h
+++ b/libcxx/include/__ios/fpos.h
@@ -28,9 +28,9 @@ class fpos {
 public:
   _LIBCPP_HIDE_FROM_ABI fpos(streamoff __off = streamoff()) : __st_(), __off_(__off) {}
 
-  _LIBCPP_HIDE_FROM_ABI operator streamoff() const { return __off_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI operator streamoff() const { return __off_; }
 
-  _LIBCPP_HIDE_FROM_ABI _StateT state() const { return __st_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _StateT state() const { return __st_; }
   _LIBCPP_HIDE_FROM_ABI void state(_StateT __st) { __st_ = __st; }
 
   _LIBCPP_HIDE_FROM_ABI fpos& operator+=(streamoff __off) {
@@ -38,7 +38,7 @@ class fpos {
     return *this;
   }
 
-  _LIBCPP_HIDE_FROM_ABI fpos operator+(streamoff __off) const {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI fpos operator+(streamoff __off) const {
     fpos __t(*this);
     __t += __off;
     return __t;
@@ -49,7 +49,7 @@ class fpos {
     return *this;
   }
 
-  _LIBCPP_HIDE_FROM_ABI fpos operator-(streamoff __off) const {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI fpos operator-(streamoff __off) const {
     fpos __t(*this);
     __t -= __off;
     return __t;
@@ -57,7 +57,7 @@ class fpos {
 };
 
 template <class _StateT>
-inline _LIBCPP_HIDE_FROM_ABI streamoff operator-(const fpos<_StateT>& __x, const fpos<_StateT>& __y) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI streamoff operator-(const fpos<_StateT>& __x, const fpos<_StateT>& __y) {
   return streamoff(__x) - streamoff(__y);
 }
 
diff --git a/libcxx/include/ios b/libcxx/include/ios
index 78fc9d610987d..9295935079877 100644
--- a/libcxx/include/ios
+++ b/libcxx/include/ios
@@ -305,25 +305,25 @@ public:
   class _LIBCPP_EXPORTED_FROM_ABI Init;
 
   // 27.5.2.2 fmtflags state:
-  _LIBCPP_HIDE_FROM_ABI fmtflags flags() const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI fmtflags flags() const;
   _LIBCPP_HIDE_FROM_ABI fmtflags flags(fmtflags __fmtfl);
   _LIBCPP_HIDE_FROM_ABI fmtflags setf(fmtflags __fmtfl);
   _LIBCPP_HIDE_FROM_ABI fmtflags setf(fmtflags __fmtfl, fmtflags __mask);
   _LIBCPP_HIDE_FROM_ABI void unsetf(fmtflags __mask);
 
-  _LIBCPP_HIDE_FROM_ABI streamsize precision() const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI streamsize precision() const;
   _LIBCPP_HIDE_FROM_ABI streamsize precision(streamsize __prec);
-  _LIBCPP_HIDE_FROM_ABI streamsize width() const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI streamsize width() const;
   _LIBCPP_HIDE_FROM_ABI streamsize width(streamsize __wide);
 
   // 27.5.2.3 locales:
   locale imbue(const locale& __loc);
-  locale getloc() const;
+  [[__nodiscard__]] locale getloc() const;
 
   // 27.5.2.5 storage:
-  static int xalloc();
-  long& iword(int __index);
-  void*& pword(int __index);
+  [[__nodiscard__]] static int xalloc();
+  [[__nodiscard__]] long& iword(int __index);
+  [[__nodiscard__]] void*& pword(int __index);
 
   // destructor
   virtual ~ios_base();
@@ -425,13 +425,13 @@ template <>
 struct is_error_code_enum<io_errc::__lx> : public true_type {};
 #    endif
 
-_LIBCPP_EXPORTED_FROM_ABI const error_category& iostream_category() _NOEXCEPT;
+[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI const error_category& iostream_category() _NOEXCEPT;
 
-inline _LIBCPP_HIDE_FROM_ABI error_code make_error_code(io_errc __e) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI error_code make_error_code(io_errc __e) _NOEXCEPT {
   return error_code(static_cast<int>(__e), iostream_category());
 }
 
-inline _LIBCPP_HIDE_FROM_ABI error_condition make_error_condition(io_errc __e) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI error_condition make_error_condition(io_errc __e) _NOEXCEPT {
   return error_condition(static_cast<int>(__e), iostream_category());
 }
 
@@ -575,21 +575,21 @@ public:
 #    ifdef _LIBCPP_CXX03_LANG
   // Preserve the ability to compare with literal 0,
   // and implicitly convert to bool, but not implicitly convert to int.
-  _LIBCPP_HIDE_FROM_ABI operator void*() const { return fail() ? nullptr : (void*)this; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI operator void*() const { return fail() ? nullptr : (void*)this; }
 #    else
-  _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return !fail(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return !fail(); }
 #    endif
 
-  _LIBCPP_HIDE_FROM_ABI bool operator!() const { return fail(); }
-  _LIBCPP_HIDE_FROM_ABI iostate rdstate() const { return ios_base::rdstate(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool operator!() const { return fail(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iostate rdstate() const { return ios_base::rdstate(); }
   _LIBCPP_HIDE_FROM_ABI void clear(iostate __state = goodbit) { ios_base::clear(__state); }
   _LIBCPP_HIDE_FROM_ABI void setstate(iostate __state) { ios_base::setstate(__state); }
-  _LIBCPP_HIDE_FROM_ABI bool good() const { return ios_base::good(); }
-  _LIBCPP_HIDE_FROM_ABI bool eof() const { return ios_base::eof(); }
-  _LIBCPP_HIDE_FROM_ABI bool fail() const { return ios_base::fail(); }
-  _LIBCPP_HIDE_FROM_ABI bool bad() const { return ios_base::bad(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool good() const { return ios_base::good(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool eof() const { return ios_base::eof(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool fail() const { return ios_base::fail(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool bad() const { return ios_base::bad(); }
 
-  _LIBCPP_HIDE_FROM_ABI iostate exceptions() const { return ios_base::exceptions(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI iostate exceptions() const { return ios_base::exceptions(); }
   _LIBCPP_HIDE_FROM_ABI void exceptions(iostate __iostate) { ios_base::exceptions(__iostate); }
 
   // 27.5.4.1 Constructor/destructor:
@@ -597,21 +597,21 @@ public:
   ~basic_ios() override;
 
   // 27.5.4.2 Members:
-  _LIBCPP_HIDE_FROM_ABI basic_ostream<char_type, traits_type>* tie() const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_ostream<char_type, traits_type>* tie() const;
   _LIBCPP_HIDE_FROM_ABI basic_ostream<char_type, traits_type>* tie(basic_ostream<char_type, traits_type>* __tiestr);
 
-  _LIBCPP_HIDE_FROM_ABI basic_streambuf<char_type, traits_type>* rdbuf() const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI basic_streambuf<char_type, traits_type>* rdbuf() const;
   _LIBCPP_HIDE_FROM_ABI basic_streambuf<char_type, traits_type>* rdbuf(basic_streambuf<char_type, traits_type>* __sb);
 
   basic_ios& copyfmt(const basic_ios& __rhs);
 
-  _LIBCPP_HIDE_FROM_ABI char_type fill() const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI char_type fill() const;
   _LIBCPP_HIDE_FROM_ABI char_type fill(char_type __ch);
 
   _LIBCPP_HIDE_FROM_ABI locale imbue(const locale& __loc);
 
-  _LIBCPP_HIDE_FROM_ABI char narrow(char_type __c, char __dfault) const;
-  _LIBCPP_HIDE_FROM_ABI char_type widen(char __c) const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI char narrow(char_type __c, char __dfault) const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI char_type widen(char __c) const;
 
 protected:
   _LIBCPP_HIDE_FROM_ABI basic_ios() {
diff --git a/libcxx/test/libcxx/input.output/iostreams.base/nodiscard.verify.cpp b/libcxx/test/libcxx/input.output/iostreams.base/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..22245a8530f4a
--- /dev/null
+++ b/libcxx/test/libcxx/input.output/iostreams.base/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
+//
+//===----------------------------------------------------------------------===//
+
+// <ios>
+
+// Check that functions are marked [[nodiscard]]
+
+#include <cwchar>
+#include <ios>
+
+#include "test_macros.h"
+
+void test() {
+  class test_stream : public std::ios {
+  public:
+    test_stream() { init(0); }
+  };
+  test_stream stream;
+
+  {
+    std::ios_base& ref = stream;
+
+    ref.flags();     // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.precision(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.width();     // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.getloc();    // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    std::ios_base::xalloc();
+    ref.iword(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.pword(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  {
+    std::ios& ref = stream;
+
+#if TEST_STD_VER >= 11
+    ref.operator bool(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#else
+    ref.operator void*(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+    !ref;             // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.rdstate();    // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.good();       // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.eof();        // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.fail();       // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.bad();        // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.exceptions(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+    ref.tie();   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.rdbuf(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+    ref.fill(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ref.narrow('\0', '\0');
+    ref.widen('\0'); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  {
+    std::fpos<std::mbstate_t> pos;
+
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    pos.operator std::streamoff();
+    pos.state(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    pos + std::streamoff(0);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    pos - std::streamoff(0);
+    pos - pos; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+}

``````````

</details>


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


More information about the libcxx-commits mailing list