[libcxx-commits] [libcxx] [AIX][libc++] fopen() does not support the 'x' (exclusive/noreplace) mode suffix. (PR #206498)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jul 6 02:26:18 PDT 2026
https://github.com/Himadhith updated https://github.com/llvm/llvm-project/pull/206498
>From eac8181d96f0ed0ff110d7cf7602551199913a6b 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/7] 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 7b84bf6609086..f979db89db794 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -664,6 +664,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;
@@ -674,6 +683,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 9c8dfa79291faa95c5a036e5d6b2ac43d199aee1 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/7] 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 f979db89db794..b71baabff2524 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -672,6 +672,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 d324a675f05f851656c4fb10ac6eaf5120ebb08e 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/7] 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 b71baabff2524..91259a39f4000 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -673,7 +673,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:
>From 450f6694bddb62f12cc9a666b3c1c300a90f725c Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Wed, 1 Jul 2026 13:49:31 -0400
Subject: [PATCH 4/7] add warning as fprintf
---
libcxx/include/fstream | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 91259a39f4000..92baa4670b363 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -672,12 +672,6 @@ 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__)
-# 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:
case ios_base::out | ios_base::trunc | ios_base::noreplace:
@@ -780,9 +774,13 @@ basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const wchar
if (__file_)
return nullptr;
const wchar_t* __mdstr = __make_mdwstring(__mode);
- if (!__mdstr)
+ if (!__mdstr){
+# if defined(_AIX) || defined(__TOS_AIX__)
+ if (__mode & ios_base::noreplace)
+ fprintf(stderr, "warning: fstream::open() with noreplace is not supported on AIX; returning failure\n");
+# endif
return nullptr;
-
+}
return __do_open(_wfopen(__s, __mdstr), __mode);
}
# endif
>From eb0c8a9711dd9ed86e21ec217adb49f8cc7e3ec3 Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Thu, 2 Jul 2026 19:30:10 +0530
Subject: [PATCH 5/7] fix formatting
---
libcxx/include/fstream | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 92baa4670b363..216082cfb8283 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -774,13 +774,13 @@ basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const wchar
if (__file_)
return nullptr;
const wchar_t* __mdstr = __make_mdwstring(__mode);
- if (!__mdstr){
-# if defined(_AIX) || defined(__TOS_AIX__)
+ if (!__mdstr) {
+# if defined(_AIX) || defined(__TOS_AIX__)
if (__mode & ios_base::noreplace)
fprintf(stderr, "warning: fstream::open() with noreplace is not supported on AIX; returning failure\n");
-# endif
+# endif
return nullptr;
-}
+ }
return __do_open(_wfopen(__s, __mdstr), __mode);
}
# endif
>From 9f7f1e7bc05bf06350f2846f8f736366133b1b8b Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Thu, 2 Jul 2026 19:37:48 +0530
Subject: [PATCH 6/7] add the remaining test files
---
.../fstreams/fstream.cons/pointer.pass.cpp | 24 +++++++++++++++---
.../fstream.members/open_pointer.pass.cpp | 24 +++++++++++++++---
.../fstreams/ofstream.cons/pointer.pass.cpp | 24 +++++++++++++++---
.../ofstream.members/open_pointer.pass.cpp | 25 ++++++++++++++++---
4 files changed, 81 insertions(+), 16 deletions(-)
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp
index 2e0ebcd684d79..a677b16e76479 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp
@@ -16,8 +16,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>
@@ -91,14 +89,23 @@ int main(int, char**)
{
std::fstream f(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());
}
{
std::remove(tmp.c_str());
std::fstream f(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
}
}
@@ -108,14 +115,23 @@ int main(int, char**)
{
std::wfstream f(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());
}
{
std::remove(tmp.c_str());
std::wfstream f(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
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/open_pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/open_pointer.pass.cpp
index 0d83d681b1dfc..92c0cf1aa0c00 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/open_pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/open_pointer.pass.cpp
@@ -16,8 +16,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"
@@ -74,7 +72,10 @@ int main(int, char**)
{
std::fstream 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());
}
{
@@ -82,7 +83,13 @@ int main(int, char**)
std::fstream 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
}
}
@@ -93,7 +100,10 @@ int main(int, char**)
{
std::wfstream 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());
}
{
@@ -101,7 +111,13 @@ int main(int, char**)
std::wfstream 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
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
index fbb03f1e85841..4fae51f38adbd 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
@@ -16,8 +16,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 <ios>
@@ -145,14 +143,23 @@ int main(int, char**)
{
std::ofstream f(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());
}
{
std::remove(tmp.c_str());
std::ofstream f(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
}
}
@@ -162,14 +169,23 @@ int main(int, char**)
{
std::wofstream f(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());
}
{
std::remove(tmp.c_str());
std::wofstream f(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
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/open_pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/open_pointer.pass.cpp
index 73a474277a933..493af1bda9c98 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/open_pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/open_pointer.pass.cpp
@@ -16,8 +16,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"
@@ -82,7 +80,10 @@ int main(int, char**)
{
std::ofstream 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());
}
{
@@ -90,7 +91,13 @@ int main(int, char**)
std::ofstream 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
}
}
@@ -101,14 +108,24 @@ int main(int, char**)
{
std::wofstream 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());
}
+
{
std::remove(tmp.c_str());
std::wofstream 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 fbd3444c18db75dab76c1eb9b8ee8dbcdf421bc0 Mon Sep 17 00:00:00 2001
From: himadhith <himadhith.v at ibm.com>
Date: Mon, 6 Jul 2026 12:15:37 +0530
Subject: [PATCH 7/7] review changes
---
libcxx/include/fstream | 21 +++++++++++--------
.../filebuf.members/open_pointer.pass.cpp | 18 ++++------------
.../fstreams/fstream.cons/pointer.pass.cpp | 18 ++++------------
.../fstream.members/open_pointer.pass.cpp | 18 ++++------------
.../fstreams/ofstream.cons/pointer.pass.cpp | 18 ++++------------
.../ofstream.members/open_pointer.pass.cpp | 18 ++++------------
6 files changed, 32 insertions(+), 79 deletions(-)
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 216082cfb8283..cfbdabdbba3f1 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -258,6 +258,8 @@ public:
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
basic_filebuf* open(const char* __s, ios_base::openmode __mode);
# if _LIBCPP_HAS_OPEN_WITH_WCHAR
+ _LIBCPP_DIAGNOSE_WARNING((__mode & ios_base::noreplace) && defined(_AIX),
+ "fstream::open() with noreplace is not supported on AIX; open() will return failure")
basic_filebuf* open(const wchar_t* __s, ios_base::openmode __mode);
# endif
_LIBCPP_HIDE_FROM_ABI basic_filebuf* open(const string& __s, ios_base::openmode __mode);
@@ -671,8 +673,8 @@ const char* basic_filebuf<_CharT, _Traits>::__make_mdstring(ios_base::openmode _
// 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__)
+// _AIX is defined on AIX by all supported compilers.
+# if !defined(_AIX)
case ios_base::out | ios_base::noreplace:
case ios_base::out | ios_base::trunc | ios_base::noreplace:
return "wx" _LIBCPP_FOPEN_CLOEXEC_MODE;
@@ -683,7 +685,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 // !defined(_AIX)
# endif // _LIBCPP_STD_VER >= 23
default:
return nullptr;
@@ -774,13 +776,8 @@ basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const wchar
if (__file_)
return nullptr;
const wchar_t* __mdstr = __make_mdwstring(__mode);
- if (!__mdstr) {
-# if defined(_AIX) || defined(__TOS_AIX__)
- if (__mode & ios_base::noreplace)
- fprintf(stderr, "warning: fstream::open() with noreplace is not supported on AIX; returning failure\n");
-# endif
+ if (!__mdstr)
return nullptr;
- }
return __do_open(_wfopen(__s, __mdstr), __mode);
}
# endif
@@ -1222,6 +1219,8 @@ public:
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
void open(const char* __s, ios_base::openmode __mode = ios_base::in);
# if _LIBCPP_HAS_OPEN_WITH_WCHAR
+ _LIBCPP_DIAGNOSE_WARNING((__mode & ios_base::noreplace) && defined(_AIX),
+ "fstream::open() with noreplace is not supported on AIX; open() will return failure")
void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in);
# endif
void open(const string& __s, ios_base::openmode __mode = ios_base::in);
@@ -1380,6 +1379,8 @@ public:
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
void open(const char* __s, ios_base::openmode __mode = ios_base::out);
# if _LIBCPP_HAS_OPEN_WITH_WCHAR
+ _LIBCPP_DIAGNOSE_WARNING((__mode & ios_base::noreplace) && defined(_AIX),
+ "fstream::open() with noreplace is not supported on AIX; open() will return failure")
void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::out);
# endif
void open(const string& __s, ios_base::openmode __mode = ios_base::out);
@@ -1544,6 +1545,8 @@ public:
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool is_open() const;
_LIBCPP_HIDE_FROM_ABI void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
# if _LIBCPP_HAS_OPEN_WITH_WCHAR
+ _LIBCPP_DIAGNOSE_WARNING((__mode & ios_base::noreplace) && defined(_AIX),
+ "fstream::open() with noreplace is not supported on AIX; open() will return failure")
void open(const wchar_t* __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
# endif
_LIBCPP_HIDE_FROM_ABI void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out);
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 627a65cac3f2f..37cfd985d1c11 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
@@ -73,10 +73,7 @@ int main(int, char**)
{
std::filebuf f;
f.open(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
@@ -84,9 +81,7 @@ 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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
@@ -101,10 +96,7 @@ int main(int, char**)
{
std::wfilebuf f;
f.open(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
@@ -112,9 +104,7 @@ 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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp
index a677b16e76479..2a297ca87903e 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.cons/pointer.pass.cpp
@@ -89,19 +89,14 @@ int main(int, char**)
{
std::fstream f(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
std::remove(tmp.c_str());
std::fstream f(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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
@@ -115,19 +110,14 @@ int main(int, char**)
{
std::wfstream f(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
std::remove(tmp.c_str());
std::wfstream f(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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/open_pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/open_pointer.pass.cpp
index 92c0cf1aa0c00..9178788b60354 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/open_pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/fstream.members/open_pointer.pass.cpp
@@ -72,10 +72,7 @@ int main(int, char**)
{
std::fstream f;
f.open(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
@@ -83,9 +80,7 @@ int main(int, char**)
std::fstream 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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
@@ -100,10 +95,7 @@ int main(int, char**)
{
std::wfstream f;
f.open(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
@@ -111,9 +103,7 @@ int main(int, char**)
std::wfstream 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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
index 4fae51f38adbd..31a944236d1d0 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.cons/pointer.pass.cpp
@@ -143,19 +143,14 @@ int main(int, char**)
{
std::ofstream f(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
std::remove(tmp.c_str());
std::ofstream f(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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
@@ -169,19 +164,14 @@ int main(int, char**)
{
std::wofstream f(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
std::remove(tmp.c_str());
std::wofstream f(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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/open_pointer.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/open_pointer.pass.cpp
index 493af1bda9c98..0b77f012b345d 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/open_pointer.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/ofstream.members/open_pointer.pass.cpp
@@ -80,10 +80,7 @@ int main(int, char**)
{
std::ofstream f;
f.open(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
@@ -91,9 +88,7 @@ int main(int, char**)
std::ofstream 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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
@@ -108,10 +103,7 @@ int main(int, char**)
{
std::wofstream f;
f.open(tmp.c_str(), mode);
- // 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());
+ assert(!f.is_open()); // since it already exists
}
{
@@ -119,9 +111,7 @@ int main(int, char**)
std::wofstream 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.
+# if defined(_AIX)
assert(!f.is_open());
# else
assert(f.is_open()); // since it doesn't exist
More information about the libcxx-commits
mailing list