[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