[libcxx-commits] [libcxx] AIX fopen() does not support the 'x' (exclusive/noreplace) mode suffix. (PR #206498)
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jul 1 09:52:56 PDT 2026
https://github.com/Himadhith updated https://github.com/llvm/llvm-project/pull/206498
>From 6fc88c1fba7be7c7eb5dcb0dddd2ec12e4a75ec8 Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Mon, 29 Jun 2026 18:53:17 +0530
Subject: [PATCH 1/3] AIX fopen() does not support the 'x'
(exclusive/noreplace) mode suffix. Omit the noreplace mode strings in
__make_mdstring() on AIX, causing open() to return nullptr for these modes.
Update the test to expect failure on AIX for all noreplace cases, since the
platform cannot provide atomic exclusive-open semantics.
---
libcxx/include/fstream | 10 ++++++++
.../filebuf.members/open_pointer.pass.cpp | 24 +++++++++++++++----
2 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index b5fb65820628a..2ec5374ce463e 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -634,6 +634,15 @@ const char* basic_filebuf<_CharT, _Traits>::__make_mdstring(ios_base::openmode _
case ios_base::in | ios_base::app | ios_base::binary:
return "a+b" _LIBCPP_FOPEN_CLOEXEC_MODE;
# if _LIBCPP_STD_VER >= 23
+// AIX fopen() does not support the 'x' (exclusive/noreplace) mode suffix, so these
+// cases are omitted on AIX and fall through to default (return nullptr), signalling
+// failure to the caller. This is conformant: C23 (7.21.5.3p5), which C++ relies on
+// by proxy, requires that if the implementation cannot atomically check for the
+// existence of the file and create it, it shall fail rather than perform a
+// non-atomic check and creation. Since AIX cannot provide atomic exclusive-open
+// semantics via fopen(), returning nullptr is the correct behaviour.
+// _AIX is defined by clang on AIX; __TOS_AIX__ is defined by both clang and XLC.
+# if !defined(_AIX) && !defined(__TOS_AIX__)
case ios_base::out | ios_base::noreplace:
case ios_base::out | ios_base::trunc | ios_base::noreplace:
return "wx" _LIBCPP_FOPEN_CLOEXEC_MODE;
@@ -644,6 +653,7 @@ const char* basic_filebuf<_CharT, _Traits>::__make_mdstring(ios_base::openmode _
return "wbx" _LIBCPP_FOPEN_CLOEXEC_MODE;
case ios_base::in | ios_base::out | ios_base::trunc | ios_base::binary | ios_base::noreplace:
return "w+bx" _LIBCPP_FOPEN_CLOEXEC_MODE;
+# endif // !defined(_AIX) && !defined(__TOS_AIX__)
# endif // _LIBCPP_STD_VER >= 23
default:
return nullptr;
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/open_pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/open_pointer.pass.cpp
index 9f617dc1e5a89..f7ab0239a1b18 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/open_pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/open_pointer.pass.cpp
@@ -13,8 +13,6 @@
// In C++23 and later, this test requires support for P2467R1 in the dylib (a3f17ba3febbd546f2342ffc780ac93b694fdc8d)
// XFAIL: (!c++03 && !c++11 && !c++14 && !c++17 && !c++20) && using-built-library-before-llvm-18
-// XFAIL: LIBCXX-AIX-FIXME
-
#include <fstream>
#include <cassert>
#include "test_macros.h"
@@ -75,7 +73,10 @@ int main(int, char**)
{
std::filebuf f;
f.open(tmp.c_str(), mode);
- assert(!f.is_open()); // since it already exists
+ // On AIX, fopen() does not support the 'x' (exclusive) mode suffix so open()
+ // returns nullptr for all noreplace modes. On other platforms, the file already
+ // exists so noreplace causes open() to fail.
+ assert(!f.is_open());
}
{
@@ -83,7 +84,13 @@ int main(int, char**)
std::filebuf f;
f.open(tmp.c_str(), mode);
+#if defined(_AIX) || defined(__TOS_AIX__)
+ // AIX fopen() does not support the 'x' (exclusive) mode suffix;
+ // open() returns nullptr for all noreplace modes regardless of whether the file exists.
+ assert(!f.is_open());
+#else
assert(f.is_open()); // since it doesn't exist
+#endif
}
}
@@ -94,7 +101,10 @@ int main(int, char**)
{
std::wfilebuf f;
f.open(tmp.c_str(), mode);
- assert(!f.is_open()); // since it already exists
+ // On AIX, fopen() does not support the 'x' (exclusive) mode suffix so open()
+ // returns nullptr for all noreplace modes. On other platforms, the file already
+ // exists so noreplace causes open() to fail.
+ assert(!f.is_open());
}
{
@@ -102,7 +112,13 @@ int main(int, char**)
std::wfilebuf f;
f.open(tmp.c_str(), mode);
+#if defined(_AIX) || defined(__TOS_AIX__)
+ // AIX fopen() does not support the 'x' (exclusive) mode suffix;
+ // open() returns nullptr for all noreplace modes regardless of whether the file exists.
+ assert(!f.is_open());
+#else
assert(f.is_open()); // since it doesn't exist
+#endif
}
}
# endif
>From 0715d9900e3781e298cca572f5955eb259d297ac Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Mon, 29 Jun 2026 12:40:23 -0400
Subject: [PATCH 2/3] fix format and add warning
---
libcxx/include/fstream | 3 +++
.../fstreams/filebuf.members/open_pointer.pass.cpp | 12 ++++++------
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 2ec5374ce463e..a5f1e80960054 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -642,6 +642,9 @@ const char* basic_filebuf<_CharT, _Traits>::__make_mdstring(ios_base::openmode _
// non-atomic check and creation. Since AIX cannot provide atomic exclusive-open
// semantics via fopen(), returning nullptr is the correct behaviour.
// _AIX is defined by clang on AIX; __TOS_AIX__ is defined by both clang and XLC.
+# if defined(_AIX) || defined(__TOS_AIX__)
+# warning 'exclusive mode is unsupported on this target'
+# endif
# if !defined(_AIX) && !defined(__TOS_AIX__)
case ios_base::out | ios_base::noreplace:
case ios_base::out | ios_base::trunc | ios_base::noreplace:
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/open_pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/open_pointer.pass.cpp
index f7ab0239a1b18..627a65cac3f2f 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/open_pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/open_pointer.pass.cpp
@@ -84,13 +84,13 @@ int main(int, char**)
std::filebuf f;
f.open(tmp.c_str(), mode);
-#if defined(_AIX) || defined(__TOS_AIX__)
+# if defined(_AIX) || defined(__TOS_AIX__)
// AIX fopen() does not support the 'x' (exclusive) mode suffix;
// open() returns nullptr for all noreplace modes regardless of whether the file exists.
assert(!f.is_open());
-#else
+# else
assert(f.is_open()); // since it doesn't exist
-#endif
+# endif
}
}
@@ -112,13 +112,13 @@ int main(int, char**)
std::wfilebuf f;
f.open(tmp.c_str(), mode);
-#if defined(_AIX) || defined(__TOS_AIX__)
+# if defined(_AIX) || defined(__TOS_AIX__)
// AIX fopen() does not support the 'x' (exclusive) mode suffix;
// open() returns nullptr for all noreplace modes regardless of whether the file exists.
assert(!f.is_open());
-#else
+# else
assert(f.is_open()); // since it doesn't exist
-#endif
+# endif
}
}
# endif
>From 072a5b2b327fe402617bd7b5ccf081931e685289 Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Wed, 1 Jul 2026 12:52:06 -0400
Subject: [PATCH 3/3] fix warnings treated as errors
---
libcxx/include/fstream | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index a5f1e80960054..54f1555c15cbe 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -643,7 +643,10 @@ const char* basic_filebuf<_CharT, _Traits>::__make_mdstring(ios_base::openmode _
// semantics via fopen(), returning nullptr is the correct behaviour.
// _AIX is defined by clang on AIX; __TOS_AIX__ is defined by both clang and XLC.
# if defined(_AIX) || defined(__TOS_AIX__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic warning "-Wcpp"
# warning 'exclusive mode is unsupported on this target'
+# pragma GCC diagnostic pop
# endif
# if !defined(_AIX) && !defined(__TOS_AIX__)
case ios_base::out | ios_base::noreplace:
More information about the libcxx-commits
mailing list