[libcxx-commits] [libcxx] [libc++] Support file offsets larger than 2GB in basic_filebuf on 32-bit AIX and 32-bit glibc Linux (PR #215892)

Jake Egan via libcxx-commits libcxx-commits at lists.llvm.org
Wed Aug 19 11:41:16 PDT 2026


https://github.com/jakeegan updated https://github.com/llvm/llvm-project/pull/215892

>From 66dc8c61e1dc71c55d0b5209a25d5cf7487fd25a Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Wed, 12 Aug 2026 15:55:22 -0400
Subject: [PATCH 01/16] [libc++][AIX] Support file offsets larger than 2GB in
 basic_filebuf on 32-bit

---
 libcxx/include/fstream                           | 16 +++++++++++++++-
 .../ifstream.members/offset_range.pass.cpp       |  6 +++---
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 0023191166c3b..f170a353ae52e 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -432,6 +432,7 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI static int __fseek(FILE* __file, pos_type __offset, int __whence);
   _LIBCPP_HIDE_FROM_ABI static pos_type __ftell(FILE* __file);
+  _LIBCPP_HIDE_FROM_ABI static FILE* __fopen(const char* __name, const char* __mode);
 
   _LIBCPP_EXPORTED_FROM_ABI friend FILE* __get_ostream_file(ostream&);
 
@@ -779,6 +780,15 @@ const wchar_t* basic_filebuf<_CharT, _Traits>::__make_mdwstring(ios_base::openmo
 }
 #    endif
 
+template <class _CharT, class _Traits>
+FILE* basic_filebuf<_CharT, _Traits>::__fopen(const char* __name, const char* __mode) {
+#   if defined(_AIX) && !defined(__64BIT__)
+  return fopen64(__name, __mode);
+#   else
+  return std::fopen(__name, __mode);
+#   endif
+}
+
 template <class _CharT, class _Traits>
 basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
   if (__file_)
@@ -787,7 +797,7 @@ basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char*
   if (!__mdstr)
     return nullptr;
 
-  return __adopt_file(std::fopen(__s, __mdstr), __mode);
+  return __adopt_file(__fopen(__s, __mdstr), __mode);
 }
 
 template <class _CharT, class _Traits>
@@ -1067,6 +1077,8 @@ int basic_filebuf<_CharT, _Traits>::__fseek(FILE* __file, pos_type __offset, int
   return _fseeki64(__file, __offset, __whence);
 #    elif _LIBCPP_LIBC_NEWLIB
   return fseek(__file, __offset, __whence);
+#    elif defined(_AIX) && !defined(__64BIT__)
+  return fseeko64(__file, __offset, __whence);
 #    else
   return ::fseeko(__file, __offset, __whence);
 #    endif
@@ -1078,6 +1090,8 @@ typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>
   return _ftelli64(__file);
 #    elif _LIBCPP_LIBC_NEWLIB
   return ftell(__file);
+#    elif defined(_AIX) && !defined(__64BIT__)
+  return ftello64(__file);
 #    else
   return ftello(__file);
 #    endif
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
index d176059ff87bf..7a11378541c1d 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
@@ -18,10 +18,10 @@
 //
 // XFAIL: target={{i686|arm.*}}-{{.+}}-android{{.*}}
 
-// By default, off_t is typically a 32-bit integer on ARMv7 Linux systems and
-// 32-bit AIX, meaning it can represent file sizes up to 2GB (2^31 bytes) only.
+// By default, off_t is typically a 32-bit integer on ARMv7 Linux systems,
+// meaning it can represent file sizes up to 2GB (2^31 bytes) only.
 //
-// UNSUPPORTED: target=armv7-unknown-linux-gnueabihf, target=powerpc-{{.+}}-aix{{.*}}
+// UNSUPPORTED: target=armv7-unknown-linux-gnueabihf
 
 #include <fstream>
 #include <iostream>

>From 1d78235e18f43900abaca22b64b7586e21b64ac1 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Wed, 12 Aug 2026 16:39:50 -0400
Subject: [PATCH 02/16] Fix formatting

---
 libcxx/include/fstream | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index f170a353ae52e..a47b899857e4e 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -782,11 +782,11 @@ const wchar_t* basic_filebuf<_CharT, _Traits>::__make_mdwstring(ios_base::openmo
 
 template <class _CharT, class _Traits>
 FILE* basic_filebuf<_CharT, _Traits>::__fopen(const char* __name, const char* __mode) {
-#   if defined(_AIX) && !defined(__64BIT__)
+#    if defined(_AIX) && !defined(__64BIT__)
   return fopen64(__name, __mode);
-#   else
+#    else
   return std::fopen(__name, __mode);
-#   endif
+#    endif
 }
 
 template <class _CharT, class _Traits>

>From 388377c7de8650e4579f27d56ddfe5787eff68ee Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Thu, 13 Aug 2026 15:00:07 -0400
Subject: [PATCH 03/16] Address some comments

---
 libcxx/include/fstream | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index a47b899857e4e..948c3b59fd155 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -217,6 +217,14 @@ typedef basic_fstream<wchar_t> wfstream;
 #      pragma GCC system_header
 #    endif
 
+#if defined(_AIX)
+// On AIX, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them here.
+// They are not POSIX-reserved names, so we use __asm__ to guard them against a user #define.
+extern "C" FILE* __libcpp_aix_fopen64(const char*, const char*) __asm__("fopen64");
+extern "C" long long __libcpp_aix_ftello64(FILE*) __asm__("ftello64");
+extern "C" int __libcpp_aix_fseeko64(FILE*, long long, int) __asm__("fseeko64");
+#endif
+
 _LIBCPP_PUSH_MACROS
 #    include <__undef_macros>
 
@@ -782,8 +790,8 @@ const wchar_t* basic_filebuf<_CharT, _Traits>::__make_mdwstring(ios_base::openmo
 
 template <class _CharT, class _Traits>
 FILE* basic_filebuf<_CharT, _Traits>::__fopen(const char* __name, const char* __mode) {
-#    if defined(_AIX) && !defined(__64BIT__)
-  return fopen64(__name, __mode);
+#    if defined(_AIX)
+  return __libcpp_aix_fopen64(__name, __mode);
 #    else
   return std::fopen(__name, __mode);
 #    endif
@@ -1077,8 +1085,8 @@ int basic_filebuf<_CharT, _Traits>::__fseek(FILE* __file, pos_type __offset, int
   return _fseeki64(__file, __offset, __whence);
 #    elif _LIBCPP_LIBC_NEWLIB
   return fseek(__file, __offset, __whence);
-#    elif defined(_AIX) && !defined(__64BIT__)
-  return fseeko64(__file, __offset, __whence);
+#    elif defined(_AIX)
+  return __libcpp_aix_fseeko64(__file, __offset, __whence);
 #    else
   return ::fseeko(__file, __offset, __whence);
 #    endif
@@ -1090,8 +1098,8 @@ typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>
   return _ftelli64(__file);
 #    elif _LIBCPP_LIBC_NEWLIB
   return ftell(__file);
-#    elif defined(_AIX) && !defined(__64BIT__)
-  return ftello64(__file);
+#    elif defined(_AIX)
+  return __libcpp_aix_ftello64(__file);
 #    else
   return ftello(__file);
 #    endif

>From befa51c9456fdf9cc99de26b31df78559c470274 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Thu, 13 Aug 2026 15:02:53 -0400
Subject: [PATCH 04/16] Fix formatting

---
 libcxx/include/fstream | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 948c3b59fd155..95d8b1212d54f 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -217,13 +217,13 @@ typedef basic_fstream<wchar_t> wfstream;
 #      pragma GCC system_header
 #    endif
 
-#if defined(_AIX)
+#    if defined(_AIX)
 // On AIX, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them here.
 // They are not POSIX-reserved names, so we use __asm__ to guard them against a user #define.
 extern "C" FILE* __libcpp_aix_fopen64(const char*, const char*) __asm__("fopen64");
 extern "C" long long __libcpp_aix_ftello64(FILE*) __asm__("ftello64");
 extern "C" int __libcpp_aix_fseeko64(FILE*, long long, int) __asm__("fseeko64");
-#endif
+#    endif
 
 _LIBCPP_PUSH_MACROS
 #    include <__undef_macros>

>From 515442a987ec1f83a3459daab75efd6d3d43c1bb Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Thu, 13 Aug 2026 15:40:58 -0400
Subject: [PATCH 05/16] Try fixing glibc on Linux

---
 libcxx/include/fstream                        | 28 +++++++++++--------
 .../ifstream.members/offset_range.pass.cpp    |  5 ----
 2 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 95d8b1212d54f..0503c13f0d6d4 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -217,12 +217,18 @@ typedef basic_fstream<wchar_t> wfstream;
 #      pragma GCC system_header
 #    endif
 
-#    if defined(_AIX)
-// On AIX, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them here.
+#    if defined(_AIX) || ((defined(__linux__) && defined(__GLIBC__))
+#      define _LIBCPP_HAS_LARGEFILE_API 1
+#    else
+#      define _LIBCPP_HAS_LARGEFILE_API 0
+#    endif
+
+#    if _LIBCPP_HAS_LARGEFILE_API
+// On AIX and glibc on Linux, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them here.
 // They are not POSIX-reserved names, so we use __asm__ to guard them against a user #define.
-extern "C" FILE* __libcpp_aix_fopen64(const char*, const char*) __asm__("fopen64");
-extern "C" long long __libcpp_aix_ftello64(FILE*) __asm__("ftello64");
-extern "C" int __libcpp_aix_fseeko64(FILE*, long long, int) __asm__("fseeko64");
+extern "C" FILE* __libcpp_fopen64(const char*, const char*) __asm__("fopen64");
+extern "C" long long __libcpp_ftello64(FILE*) __asm__("ftello64");
+extern "C" int __libcpp_fseeko64(FILE*, long long, int) __asm__("fseeko64");
 #    endif
 
 _LIBCPP_PUSH_MACROS
@@ -790,8 +796,8 @@ const wchar_t* basic_filebuf<_CharT, _Traits>::__make_mdwstring(ios_base::openmo
 
 template <class _CharT, class _Traits>
 FILE* basic_filebuf<_CharT, _Traits>::__fopen(const char* __name, const char* __mode) {
-#    if defined(_AIX)
-  return __libcpp_aix_fopen64(__name, __mode);
+#    if _LIBCPP_HAS_LARGEFILE_API
+  return __libcpp_fopen64(__name, __mode);
 #    else
   return std::fopen(__name, __mode);
 #    endif
@@ -1085,8 +1091,8 @@ int basic_filebuf<_CharT, _Traits>::__fseek(FILE* __file, pos_type __offset, int
   return _fseeki64(__file, __offset, __whence);
 #    elif _LIBCPP_LIBC_NEWLIB
   return fseek(__file, __offset, __whence);
-#    elif defined(_AIX)
-  return __libcpp_aix_fseeko64(__file, __offset, __whence);
+#    elif _LIBCPP_HAS_LARGEFILE_API
+  return __libcpp_fseeko64(__file, __offset, __whence);
 #    else
   return ::fseeko(__file, __offset, __whence);
 #    endif
@@ -1098,8 +1104,8 @@ typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>
   return _ftelli64(__file);
 #    elif _LIBCPP_LIBC_NEWLIB
   return ftell(__file);
-#    elif defined(_AIX)
-  return __libcpp_aix_ftello64(__file);
+#    elif _LIBCPP_HAS_LARGEFILE_API
+  return __libcpp_ftello64(__file);
 #    else
   return ftello(__file);
 #    endif
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
index 7a11378541c1d..9a9824bd5287f 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp
@@ -18,11 +18,6 @@
 //
 // XFAIL: target={{i686|arm.*}}-{{.+}}-android{{.*}}
 
-// By default, off_t is typically a 32-bit integer on ARMv7 Linux systems,
-// meaning it can represent file sizes up to 2GB (2^31 bytes) only.
-//
-// UNSUPPORTED: target=armv7-unknown-linux-gnueabihf
-
 #include <fstream>
 #include <iostream>
 #include <cassert>

>From 87cb0e9221354871c0bf0b9fc77e2f957164c47c Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Thu, 13 Aug 2026 15:44:58 -0400
Subject: [PATCH 06/16] Fix formatting

---
 libcxx/include/fstream | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 0503c13f0d6d4..ca1fa9299b301 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -224,8 +224,8 @@ typedef basic_fstream<wchar_t> wfstream;
 #    endif
 
 #    if _LIBCPP_HAS_LARGEFILE_API
-// On AIX and glibc on Linux, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them here.
-// They are not POSIX-reserved names, so we use __asm__ to guard them against a user #define.
+// On AIX and glibc on Linux, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them
+// here. They are not POSIX-reserved names, so we use __asm__ to guard them against a user #define.
 extern "C" FILE* __libcpp_fopen64(const char*, const char*) __asm__("fopen64");
 extern "C" long long __libcpp_ftello64(FILE*) __asm__("ftello64");
 extern "C" int __libcpp_fseeko64(FILE*, long long, int) __asm__("fseeko64");

>From 75df5b718048b47c200dcffa63166cad725d5d1d Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Thu, 13 Aug 2026 15:47:31 -0400
Subject: [PATCH 07/16] Remove extra (

---
 libcxx/include/fstream | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index ca1fa9299b301..d9bccae1f4aef 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -217,7 +217,7 @@ typedef basic_fstream<wchar_t> wfstream;
 #      pragma GCC system_header
 #    endif
 
-#    if defined(_AIX) || ((defined(__linux__) && defined(__GLIBC__))
+#    if defined(_AIX) || (defined(__linux__) && defined(__GLIBC__))
 #      define _LIBCPP_HAS_LARGEFILE_API 1
 #    else
 #      define _LIBCPP_HAS_LARGEFILE_API 0

>From 6d81cfc2547f17f6eb6a7da7d8c02328e5c57471 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Thu, 13 Aug 2026 18:28:50 -0400
Subject: [PATCH 08/16] Address comments

---
 libcxx/docs/ReleaseNotes/24.rst |  2 ++
 libcxx/include/fstream          | 22 ++++++++++------------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index e9a36ae94392f..a41347f544c50 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -51,6 +51,8 @@ Implemented Papers
 Improvements and New Features
 -----------------------------
 
+- ``basic_filebuf`` now supports files larger than 2GB on 32-bit AIX and 32-bit glib Linux targets.
+
 Deprecations and Removals
 -------------------------
 
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index d9bccae1f4aef..44da8ffa8730e 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -241,6 +241,14 @@ _LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
 _LIBCPP_EXPORTED_FROM_ABI void* __filebuf_windows_native_handle(FILE* __file) noexcept;
 #    endif
 
+_LIBCPP_HIDE_FROM_ABI inline FILE* __fopen(const char* __name, const char* __mode) {
+#    if _LIBCPP_HAS_LARGEFILE_API
+  return ::__libcpp_fopen64(__name, __mode);
+#    else
+  return std::fopen(__name, __mode);
+#    endif
+}
+
 template <class _CharT, class _Traits>
 class basic_filebuf : public basic_streambuf<_CharT, _Traits> {
 public:
@@ -446,7 +454,6 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI static int __fseek(FILE* __file, pos_type __offset, int __whence);
   _LIBCPP_HIDE_FROM_ABI static pos_type __ftell(FILE* __file);
-  _LIBCPP_HIDE_FROM_ABI static FILE* __fopen(const char* __name, const char* __mode);
 
   _LIBCPP_EXPORTED_FROM_ABI friend FILE* __get_ostream_file(ostream&);
 
@@ -794,15 +801,6 @@ const wchar_t* basic_filebuf<_CharT, _Traits>::__make_mdwstring(ios_base::openmo
 }
 #    endif
 
-template <class _CharT, class _Traits>
-FILE* basic_filebuf<_CharT, _Traits>::__fopen(const char* __name, const char* __mode) {
-#    if _LIBCPP_HAS_LARGEFILE_API
-  return __libcpp_fopen64(__name, __mode);
-#    else
-  return std::fopen(__name, __mode);
-#    endif
-}
-
 template <class _CharT, class _Traits>
 basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
   if (__file_)
@@ -1092,7 +1090,7 @@ int basic_filebuf<_CharT, _Traits>::__fseek(FILE* __file, pos_type __offset, int
 #    elif _LIBCPP_LIBC_NEWLIB
   return fseek(__file, __offset, __whence);
 #    elif _LIBCPP_HAS_LARGEFILE_API
-  return __libcpp_fseeko64(__file, __offset, __whence);
+  return ::__libcpp_fseeko64(__file, __offset, __whence);
 #    else
   return ::fseeko(__file, __offset, __whence);
 #    endif
@@ -1105,7 +1103,7 @@ typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>
 #    elif _LIBCPP_LIBC_NEWLIB
   return ftell(__file);
 #    elif _LIBCPP_HAS_LARGEFILE_API
-  return __libcpp_ftello64(__file);
+  return ::__libcpp_ftello64(__file);
 #    else
   return ftello(__file);
 #    endif

>From e9dedb87af50c0bc5a15d06ef4ca89f8887a6b31 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Thu, 13 Aug 2026 18:37:07 -0400
Subject: [PATCH 09/16] typo fix

---
 libcxx/docs/ReleaseNotes/24.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index a41347f544c50..b8b3777201540 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -51,7 +51,7 @@ Implemented Papers
 Improvements and New Features
 -----------------------------
 
-- ``basic_filebuf`` now supports files larger than 2GB on 32-bit AIX and 32-bit glib Linux targets.
+- ``basic_filebuf`` now supports files larger than 2GB on 32-bit AIX and 32-bit glibc Linux targets.
 
 Deprecations and Removals
 -------------------------

>From 982c0bd1ce5c60db8be199938f6d0dde1818e2fd Mon Sep 17 00:00:00 2001
From: Jake Egan <Jake.egan at ibm.com>
Date: Thu, 13 Aug 2026 20:58:14 -0400
Subject: [PATCH 10/16] Add std::

Co-authored-by: Hubert Tong <hubert.reinterpretcast at gmail.com>
---
 libcxx/include/fstream | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 44da8ffa8730e..adc7c11ded91d 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -809,7 +809,7 @@ basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char*
   if (!__mdstr)
     return nullptr;
 
-  return __adopt_file(__fopen(__s, __mdstr), __mode);
+  return __adopt_file(std::__fopen(__s, __mdstr), __mode);
 }
 
 template <class _CharT, class _Traits>

>From 670d0ff1267ae915e749a5ad82226a2336eddded Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 18 Aug 2026 16:13:55 -0400
Subject: [PATCH 11/16] Address comments

---
 libcxx/include/fstream | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index adc7c11ded91d..8adee16faf224 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -217,14 +217,8 @@ typedef basic_fstream<wchar_t> wfstream;
 #      pragma GCC system_header
 #    endif
 
-#    if defined(_AIX) || (defined(__linux__) && defined(__GLIBC__))
-#      define _LIBCPP_HAS_LARGEFILE_API 1
-#    else
-#      define _LIBCPP_HAS_LARGEFILE_API 0
-#    endif
-
-#    if _LIBCPP_HAS_LARGEFILE_API
-// On AIX and glibc on Linux, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them
+#    if _AIX
+// On AIX, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them
 // here. They are not POSIX-reserved names, so we use __asm__ to guard them against a user #define.
 extern "C" FILE* __libcpp_fopen64(const char*, const char*) __asm__("fopen64");
 extern "C" long long __libcpp_ftello64(FILE*) __asm__("ftello64");
@@ -241,14 +235,6 @@ _LIBCPP_BEGIN_EXPLICIT_ABI_ANNOTATIONS
 _LIBCPP_EXPORTED_FROM_ABI void* __filebuf_windows_native_handle(FILE* __file) noexcept;
 #    endif
 
-_LIBCPP_HIDE_FROM_ABI inline FILE* __fopen(const char* __name, const char* __mode) {
-#    if _LIBCPP_HAS_LARGEFILE_API
-  return ::__libcpp_fopen64(__name, __mode);
-#    else
-  return std::fopen(__name, __mode);
-#    endif
-}
-
 template <class _CharT, class _Traits>
 class basic_filebuf : public basic_streambuf<_CharT, _Traits> {
 public:
@@ -454,6 +440,7 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI static int __fseek(FILE* __file, pos_type __offset, int __whence);
   _LIBCPP_HIDE_FROM_ABI static pos_type __ftell(FILE* __file);
+  _LIBCPP_HIDE_FROM_ABI static FILE* __fopen(const char* __name, const char* __mode);
 
   _LIBCPP_EXPORTED_FROM_ABI friend FILE* __get_ostream_file(ostream&);
 
@@ -801,6 +788,17 @@ const wchar_t* basic_filebuf<_CharT, _Traits>::__make_mdwstring(ios_base::openmo
 }
 #    endif
 
+template <class _CharT, class _Traits>
+FILE* basic_filebuf<_CharT, _Traits>::__fopen(const char* __name, const char* __mode) {
+#    if defined(_AIX)
+  return ::__libcpp_fopen64(__name, __mode);
+#    elif defined(__GLIBC__)
+  return ::fopen64(__name, __mode);
+#    else
+  return std::fopen(__name, __mode);
+#    endif
+}
+
 template <class _CharT, class _Traits>
 basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) {
   if (__file_)
@@ -1089,8 +1087,10 @@ int basic_filebuf<_CharT, _Traits>::__fseek(FILE* __file, pos_type __offset, int
   return _fseeki64(__file, __offset, __whence);
 #    elif _LIBCPP_LIBC_NEWLIB
   return fseek(__file, __offset, __whence);
-#    elif _LIBCPP_HAS_LARGEFILE_API
+#    elif defined(_AIX)
   return ::__libcpp_fseeko64(__file, __offset, __whence);
+#    elif defined(__GLIBC__)
+  return ::fseeko64(__file, __offset, __whence);
 #    else
   return ::fseeko(__file, __offset, __whence);
 #    endif
@@ -1102,8 +1102,10 @@ typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>
   return _ftelli64(__file);
 #    elif _LIBCPP_LIBC_NEWLIB
   return ftell(__file);
-#    elif _LIBCPP_HAS_LARGEFILE_API
+#    elif defined(_AIX)
   return ::__libcpp_ftello64(__file);
+#   elif defined(__GLIBC__)
+  return ::ftello64(__file);
 #    else
   return ftello(__file);
 #    endif

>From 09ffdd64a0789137eed4e5abe7946a3da315579f Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 18 Aug 2026 16:17:17 -0400
Subject: [PATCH 12/16] Remove std::

---
 libcxx/include/fstream | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 8adee16faf224..3c80996364906 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -807,7 +807,7 @@ basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char*
   if (!__mdstr)
     return nullptr;
 
-  return __adopt_file(std::__fopen(__s, __mdstr), __mode);
+  return __adopt_file(__fopen(__s, __mdstr), __mode);
 }
 
 template <class _CharT, class _Traits>

>From 7a976957584e7579520061787782ef0ca5421d8f Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 18 Aug 2026 16:17:59 -0400
Subject: [PATCH 13/16] Added defined for macro

---
 libcxx/include/fstream | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 3c80996364906..d36bb1f265d81 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -217,7 +217,7 @@ typedef basic_fstream<wchar_t> wfstream;
 #      pragma GCC system_header
 #    endif
 
-#    if _AIX
+#    if defined(_AIX)
 // On AIX, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them
 // here. They are not POSIX-reserved names, so we use __asm__ to guard them against a user #define.
 extern "C" FILE* __libcpp_fopen64(const char*, const char*) __asm__("fopen64");

>From b112f591b0467703f1b99f97fcf2f462584fd04f Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 18 Aug 2026 16:26:09 -0400
Subject: [PATCH 14/16] Fix formatting

---
 libcxx/include/fstream | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index d36bb1f265d81..ed2995d6f7c62 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -1104,7 +1104,7 @@ typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>
   return ftell(__file);
 #    elif defined(_AIX)
   return ::__libcpp_ftello64(__file);
-#   elif defined(__GLIBC__)
+#    elif defined(__GLIBC__)
   return ::ftello64(__file);
 #    else
   return ftello(__file);

>From 8de351bb98dd782c24fba5ffbff55185b65a44cd Mon Sep 17 00:00:00 2001
From: Jake Egan <Jake.egan at ibm.com>
Date: Tue, 18 Aug 2026 19:38:15 -0400
Subject: [PATCH 15/16] Update libcxx/docs/ReleaseNotes/24.rst

Co-authored-by: Hubert Tong <hubert.reinterpretcast at gmail.com>
---
 libcxx/docs/ReleaseNotes/24.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index b8b3777201540..61d534c2dfc4a 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -51,7 +51,7 @@ Implemented Papers
 Improvements and New Features
 -----------------------------
 
-- ``basic_filebuf`` now supports files larger than 2GB on 32-bit AIX and 32-bit glibc Linux targets.
+- ``basic_filebuf`` now supports files larger than 2GB on 32-bit AIX and 32-bit glibc targets.
 
 Deprecations and Removals
 -------------------------

>From 324c5de3266ba5f30932f5c3cb5492c0792684ac Mon Sep 17 00:00:00 2001
From: Jake Egan <Jake.egan at ibm.com>
Date: Wed, 19 Aug 2026 14:40:58 -0400
Subject: [PATCH 16/16] Update libcxx/include/fstream

Co-authored-by: Nikolas Klauser <nikolasklauser at berlin.de>
---
 libcxx/include/fstream | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index ed2995d6f7c62..f1792b12e229c 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -219,7 +219,7 @@ typedef basic_fstream<wchar_t> wfstream;
 
 #    if defined(_AIX)
 // On AIX, fopen64/fseeko64/ftello64 are not guaranteed to always be declared, so we declare them
-// here. They are not POSIX-reserved names, so we use __asm__ to guard them against a user #define.
+// here. We use `__asm__` to avoid colliding with the declaration in the header in any way.
 extern "C" FILE* __libcpp_fopen64(const char*, const char*) __asm__("fopen64");
 extern "C" long long __libcpp_ftello64(FILE*) __asm__("ftello64");
 extern "C" int __libcpp_fseeko64(FILE*, long long, int) __asm__("fseeko64");



More information about the libcxx-commits mailing list