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

Jake Egan via libcxx-commits libcxx-commits at lists.llvm.org
Thu Aug 13 12:48:18 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 1/7] [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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 6/7] 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 7/7] 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



More information about the libcxx-commits mailing list