Skip to content

[libcxx] Use _ftelli64/_fseeki64 on Windows #123128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 29, 2025
Merged

Conversation

mstorsjo
Copy link
Member

This allows using the full 64 bit range for file offsets.

This should fix the issue reported downstream at
mstorsjo/llvm-mingw#462.

@mstorsjo mstorsjo requested a review from philnik777 January 15, 2025 22:22
@mstorsjo mstorsjo requested a review from a team as a code owner January 15, 2025 22:22
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jan 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 15, 2025

@llvm/pr-subscribers-libcxx

Author: Martin Storsjö (mstorsjo)

Changes

This allows using the full 64 bit range for file offsets.

This should fix the issue reported downstream at
mstorsjo/llvm-mingw#462.


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

2 Files Affected:

  • (modified) libcxx/include/fstream (+9-2)
  • (modified) libcxx/test/std/input.output/file.streams/fstreams/ifstream.members/offset_range.pass.cpp (-6)
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index f0e9425e0a53d9..b6f7f0439c566a 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -936,7 +936,11 @@ basic_filebuf<_CharT, _Traits>::seekoff(off_type __off, ios_base::seekdir __way,
   default:
     return pos_type(off_type(-1));
   }
-#    if !_LIBCPP_HAS_OFF_T_FUNCTIONS
+#    if defined(_LIBCPP_MSVCRT_LIKE)
+  if (_fseeki64(__file_, __width > 0 ? __width * __off : 0, __whence))
+    return pos_type(off_type(-1));
+  pos_type __r = _ftelli64(__file_);
+#    elif !_LIBCPP_HAS_OFF_T_FUNCTIONS
   if (fseek(__file_, __width > 0 ? __width * __off : 0, __whence))
     return pos_type(off_type(-1));
   pos_type __r = ftell(__file_);
@@ -954,7 +958,10 @@ typename basic_filebuf<_CharT, _Traits>::pos_type
 basic_filebuf<_CharT, _Traits>::seekpos(pos_type __sp, ios_base::openmode) {
   if (__file_ == nullptr || sync())
     return pos_type(off_type(-1));
-#    if !_LIBCPP_HAS_OFF_T_FUNCTIONS
+#    if defined(_LIBCPP_MSVCRT_LIKE)
+  if (_fseeki64(__file_, __sp, SEEK_SET))
+    return pos_type(off_type(-1));
+#    elif !_LIBCPP_HAS_OFF_T_FUNCTIONS
   if (fseek(__file_, __sp, SEEK_SET))
     return pos_type(off_type(-1));
 #    else
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 5afd4465db31e0..ca6c609c7be312 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
@@ -11,12 +11,6 @@
 // Test that we can seek using offsets larger than 32 bit, and that we can
 // retrieve file offsets larger than 32 bit.
 
-// On MSVC targets, we only use the 32 bit fseek/ftell functions. For MinGW
-// targets, we use fseeko/ftello, but the user needs to define
-// _FILE_OFFSET_BITS=64 to make them 64 bit.
-//
-// XFAIL: target={{.*}}-windows{{.*}}
-
 // On 32 bit Android platforms, off_t is 32 bit by default. By defining
 // _FILE_OFFSET_BITS=64, one gets a 64 bit off_t, but the corresponding
 // 64 bit ftello/fseeko functions are only available since Android API 24 (7.0).

@mstorsjo
Copy link
Member Author

If doing this, I guess we should do the same change in include/__cxx03 too? Otherwise the test would fail on Windows if targeting C++03; we don't have that test config in CI though (all the C++03 tests are for other platforms), so it won't be caught.

@@ -936,7 +936,11 @@ basic_filebuf<_CharT, _Traits>::seekoff(off_type __off, ios_base::seekdir __way,
default:
return pos_type(off_type(-1));
}
# if !_LIBCPP_HAS_OFF_T_FUNCTIONS
# if defined(_LIBCPP_MSVCRT_LIKE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better if we refactor this to have an internal fseek instead of duplicating this multiple times. We also have something very similar in sync(), which you don't modify here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I factorized this into __fseek and __ftell now and use them in these both locations, and in sync() which I had missed.

@philnik777
Copy link
Contributor

If doing this, I guess we should do the same change in include/__cxx03 too? Otherwise the test would fail on Windows if targeting C++03; we don't have that test config in CI though (all the C++03 tests are for other platforms), so it won't be caught.

For now there should just be an // UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME in the test if it doesn't work with the frozen headers.

@mstorsjo
Copy link
Member Author

If doing this, I guess we should do the same change in include/__cxx03 too? Otherwise the test would fail on Windows if targeting C++03; we don't have that test config in CI though (all the C++03 tests are for other platforms), so it won't be caught.

For now there should just be an // UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME in the test if it doesn't work with the frozen headers.

Well the test does work with the frozen headers, but we don't get the 64 bit range on Windows until we apply the same fix as here, on the frozen headers.

@philnik777
Copy link
Contributor

If doing this, I guess we should do the same change in include/__cxx03 too? Otherwise the test would fail on Windows if targeting C++03; we don't have that test config in CI though (all the C++03 tests are for other platforms), so it won't be caught.

For now there should just be an // UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME in the test if it doesn't work with the frozen headers.

Well the test does work with the frozen headers, but we don't get the 64 bit range on Windows until we apply the same fix as here, on the frozen headers.

I meant "fails with the frozen headers".

@mstorsjo
Copy link
Member Author

If doing this, I guess we should do the same change in include/__cxx03 too? Otherwise the test would fail on Windows if targeting C++03; we don't have that test config in CI though (all the C++03 tests are for other platforms), so it won't be caught.

For now there should just be an // UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME in the test if it doesn't work with the frozen headers.

Well the test does work with the frozen headers, but we don't get the 64 bit range on Windows until we apply the same fix as here, on the frozen headers.

I meant "fails with the frozen headers".

Right, although that would also exclude the test from running in C++03 mode with frozen headers on other OSes (where it works just fine). As we don't have CI coverage for that case combination (C++03 frozen headers on Windows), I think I'd rather either just let it slip (and fix the frozen headers later) or consider adding such a test configuration.

Copy link

github-actions bot commented Jan 28, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Comment on lines +365 to +360
_LIBCPP_HIDE_FROM_ABI static int __fseek(FILE* __file, pos_type __offset, int __whence);
_LIBCPP_HIDE_FROM_ABI static pos_type __ftell(FILE* __file);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can just make these free functions. (I'd just define them at the top of the file). It would also be good to remove the !defined(_LIBCPP_MSVCRT) from the definition of _LIBCPP_HAS_OFF_T_FUNCTIONS and probably just inline _LIBCPP_HAS_OFF_T_FUNCTIONS as a whole, since at that point it's just equivalent do defind(_NEWLIB_VERSION).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept the functions in the class, as they use pos_type, but I updated the PR to remove the unnecessary intermediate define _LIBCPP_HAS_OFF_T_FUNCTIONS.

Copy link
Contributor

@philnik777 philnik777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with green CI

@mstorsjo mstorsjo merged commit 86e20b0 into llvm:main Jan 29, 2025
78 checks passed
@mstorsjo mstorsjo added this to the LLVM 20.X Release milestone Jan 29, 2025
@mstorsjo mstorsjo deleted the libcxx-tellg branch January 29, 2025 13:26
@mstorsjo
Copy link
Member Author

/cherry-pick 86e20b0

@llvmbot
Copy link
Member

llvmbot commented Jan 29, 2025

/pull-request #124922

swift-ci pushed a commit to swiftlang/llvm-project that referenced this pull request Feb 1, 2025
This allows using the full 64 bit range for file offsets.

This should fix the issue reported downstream at
mstorsjo/llvm-mingw#462.

(cherry picked from commit 86e20b0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
Development

Successfully merging this pull request may close these issues.

3 participants