Futhermore string and generic_string method as marked as deprecated
in C++26 mode.
This implements the P2319R5 "Prevent path presentation problem" paper,
with the rename of system_encoded_string from LWG4512,
"The system_encoded_string() and generic_system_encoded_string() member
functions of std::filesystem::path are misnamed".
The wording defines the display_string and generic_display_string
int terms of call of format with format string "{}" and "{:g}"
respectively. This patch inlines the effects of above, by either
returning native() or generic_string<value_type>() direclty
(if value_type is char), or string constructed __unicode::_Utf_view
of above (when value_type is wchar_t).
As we currently assume that char encoding is always UTF-8, the outputs
of (generic_)native_encoded string and (generic_)display_string
are equivalent. However, the former may be adjusted in future.
libstdc++-v3/ChangeLog:
* include/bits/fs_path.h (path::string, path::generic_string):
Add deprected attribute in C++26 via _GLIBCXX26_DEPRECATED_SUGGEST.
(path::display_string, path::native_encoded_string)
(path::generic_display_string, path::generic_native_encoded_string)
[__glibcxx_format_path >= 202506L]: Define.
* include/bits/version.def (format_path): Bump to 202506.
* include/bits/version.h: Regenerate.
* testsuite/util/testsuite_fs.h (__gnu_test::compare_paths):
Ignored deprecated declarations warning.
* testsuite/27_io/filesystem/filesystem_error/cons.cc:
Disable -Wdeprecated-declarations warning with pragmas.
* testsuite/27_io/filesystem/operations/canonical.cc: Likewise.
* testsuite/27_io/filesystem/operations/copy_file.cc: Likewise.
* testsuite/27_io/filesystem/path/concat/strings.cc: Likwise.
* testsuite/27_io/filesystem/path/itr/traversal.cc: Likewise.
* testsuite/27_io/filesystem/operations/temp_directory_path.cc:
Likewise.
* testsuite/27_io/filesystem/path/decompose/root_directory.cc:
Likewise.
* testsuite/27_io/filesystem/path/generic/generic_string.cc:
Likewise.
* testsuite/27_io/print/1.cc: Likewise.
* testsuite/27_io/print/2.cc: Likewise.
* testsuite/27_io/print/3.cc: Likewise.
* testsuite/27_io/filesystem/path/append/source.cc:
Add dg-warning for deprecated functions use.
* testsuite/27_io/filesystem/path/decompose/stem.cc: Likewise.
* testsuite/27_io/filesystem/path/native/string-char8_t.cc:
Likewise.
* testsuite/27_io/filesystem/path/generic/display_native_string.cc:
New test.
* testsuite/27_io/filesystem/path/native/display_native_string.cc:
New test.
---
I used dg-warning when there was one/two calls to update, and
addign it didn't make lines excessivelly long. The display_native_string
test make sure that warning appear.
Tested on x86_64-linux. *filesystem/path* also tested on MinGW and WINE
locally. OK for trunk?
libstdc++-v3/include/bits/fs_path.h | 45 +++++++++++++
libstdc++-v3/include/bits/version.def | 3 +-
libstdc++-v3/include/bits/version.h | 4 +-
.../27_io/filesystem/filesystem_error/cons.cc | 2 +
.../27_io/filesystem/operations/canonical.cc | 2 +
.../27_io/filesystem/operations/copy_file.cc | 2 +
.../operations/temp_directory_path.cc | 2 +
.../27_io/filesystem/path/append/source.cc | 2 +-
.../27_io/filesystem/path/concat/strings.cc | 2 +
.../path/decompose/root_directory.cc | 2 +
.../27_io/filesystem/path/decompose/stem.cc | 2 +-
.../path/generic/display_native_string.cc | 66 +++++++++++++++++++
.../filesystem/path/generic/generic_string.cc | 2 +
.../27_io/filesystem/path/itr/traversal.cc | 2 +
.../path/native/display_native_string.cc | 66 +++++++++++++++++++
.../filesystem/path/native/string-char8_t.cc | 2 +-
libstdc++-v3/testsuite/27_io/print/1.cc | 4 +-
libstdc++-v3/testsuite/27_io/print/2.cc | 2 +
libstdc++-v3/testsuite/27_io/print/3.cc | 2 +
libstdc++-v3/testsuite/util/testsuite_fs.h | 4 +-
20 files changed, 210 insertions(+), 8 deletions(-)
create mode 100644
libstdc++-v3/testsuite/27_io/filesystem/path/generic/display_native_string.cc
create mode 100644
libstdc++-v3/testsuite/27_io/filesystem/path/native/display_native_string.cc
diff --git a/libstdc++-v3/include/bits/fs_path.h
b/libstdc++-v3/include/bits/fs_path.h
index 8d007800029..2f59f87fe6e 100644
--- a/libstdc++-v3/include/bits/fs_path.h
+++ b/libstdc++-v3/include/bits/fs_path.h
@@ -462,7 +462,12 @@ namespace __detail
std::basic_string<_CharT, _Traits, _Allocator>
string(const _Allocator& __a = _Allocator()) const;
+ _GLIBCXX26_DEPRECATED_SUGGEST("display_string' or 'native_encoded_string")
std::string string() const;
+#if __glibcxx_format_path >= 202506L // C++ >= 26 && HOSTED
+ std::string display_string() const;
+ std::string native_encoded_string() const;
+#endif
#if _GLIBCXX_USE_WCHAR_T
std::wstring wstring() const;
#endif
@@ -481,7 +486,12 @@ namespace __detail
std::basic_string<_CharT, _Traits, _Allocator>
generic_string(const _Allocator& __a = _Allocator()) const;
+ _GLIBCXX26_DEPRECATED_SUGGEST("generic_display_string' or
'generic_native_encoded_string")
std::string generic_string() const;
+#if __glibcxx_format_path >= 202506L // C++ >= 26 && HOSTED
+ std::string generic_display_string() const;
+ std::string generic_native_encoded_string() const;
+#endif
#if _GLIBCXX_USE_WCHAR_T
std::wstring generic_wstring() const;
#endif
@@ -1173,6 +1183,23 @@ namespace __detail
inline std::string
path::string() const { return string<char>(); }
+#if __glibcxx_format_path >= 202506L // C++ >= 26 && HOSTED
+ inline std::string
+ path::display_string() const
+ {
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+ return std::string(from_range,
+ __unicode::_Utf_view<char, wstring_view>(native()));
+#else
+ return native();
+#endif
+ }
+
+ inline std::string
+ path::native_encoded_string() const
+ { return string<char>(); }
+#endif
+
#if _GLIBCXX_USE_WCHAR_T
inline std::wstring
path::wstring() const { return string<wchar_t>(); }
@@ -1251,6 +1278,24 @@ namespace __detail
path::generic_string() const
{ return generic_string<char>(); }
+#if __glibcxx_format_path >= 202506L // C++ >= 26 && HOSTED
+ inline std::string
+ path::generic_display_string() const
+ {
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+ string_type __str = generic_string<wchar_t>();
+ return std::string(from_range,
+ __unicode::_Utf_view<char, wstring_view>(__str));
+#else
+ return generic_string<char>();
+#endif
+ }
+
+ inline std::string
+ path::generic_native_encoded_string() const
+ { return generic_string<char>(); }
+#endif
+
#if _GLIBCXX_USE_WCHAR_T
inline std::wstring
path::generic_wstring() const
diff --git a/libstdc++-v3/include/bits/version.def
b/libstdc++-v3/include/bits/version.def
index 2f32a8bda98..cd584a761ef 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1585,8 +1585,9 @@ ftms = {
ftms = {
name = format_path;
// 202403 P2845R8 Formatting of std::filesystem::path
+ // 202506 P2319R5 Prevent path presentation problems
values = {
- v = 202403;
+ v = 202506;
cxxmin = 26;
hosted = yes;
};
diff --git a/libstdc++-v3/include/bits/version.h
b/libstdc++-v3/include/bits/version.h
index 517b9020ec6..8ea45e226f4 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1738,9 +1738,9 @@
#if !defined(__cpp_lib_format_path)
# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
-# define __glibcxx_format_path 202403L
+# define __glibcxx_format_path 202506L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_format_path)
-# define __cpp_lib_format_path 202403L
+# define __cpp_lib_format_path 202506L
# endif
# endif
#endif /* !defined(__cpp_lib_format_path) */
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/filesystem_error/cons.cc
b/libstdc++-v3/testsuite/27_io/filesystem/filesystem_error/cons.cc
index 3a4be9fbd3a..a064bc679be 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/filesystem_error/cons.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/filesystem_error/cons.cc
@@ -21,6 +21,8 @@
#include <filesystem>
#include <testsuite_hooks.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
using std::filesystem::filesystem_error;
bool contains(std::string_view what_str, std::string_view expected)
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/canonical.cc
b/libstdc++-v3/testsuite/27_io/filesystem/operations/canonical.cc
index a915b291c37..884b6da438a 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/operations/canonical.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/canonical.cc
@@ -22,6 +22,8 @@
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
namespace fs = std::filesystem;
using __gnu_test::compare_paths;
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_file.cc
b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_file.cc
index 41cd8243502..7d54243c922 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_file.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_file.cc
@@ -25,6 +25,8 @@
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
void
test01()
{
diff --git
a/libstdc++-v3/testsuite/27_io/filesystem/operations/temp_directory_path.cc
b/libstdc++-v3/testsuite/27_io/filesystem/operations/temp_directory_path.cc
index aa4ce752701..34113854949 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/operations/temp_directory_path.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/temp_directory_path.cc
@@ -24,6 +24,8 @@
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
void
clean_env()
{
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/append/source.cc
b/libstdc++-v3/testsuite/27_io/filesystem/path/append/source.cc
index d579c9bb840..ba7adf6ffdc 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/append/source.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/append/source.cc
@@ -96,7 +96,7 @@ test03()
{
test(p, q.c_str());
if constexpr (!std::is_same_v<path::value_type, char>)
- test(p, q.string().c_str());
+ test(p, q.string().c_str()); // { dg-warning "deprecated" "" { target
c++26 } }
}
}
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/concat/strings.cc
b/libstdc++-v3/testsuite/27_io/filesystem/path/concat/strings.cc
index 3e1e20b4800..7501454e155 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/concat/strings.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/concat/strings.cc
@@ -24,6 +24,8 @@
#include <testsuite_iterators.h>
#include <testsuite_fs.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
using std::filesystem::path;
using __gnu_test::compare_paths;
diff --git
a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc
b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc
index 4a1bdb091fc..49433701c42 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/root_directory.cc
@@ -23,6 +23,8 @@
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
using std::filesystem::path;
void
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/stem.cc
b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/stem.cc
index 0ce9dd7d6d6..2139fde734b 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/stem.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/decompose/stem.cc
@@ -33,7 +33,7 @@ test01()
path p = "foo.bar.baz.tar";
std::vector<std::string> v;
for (; !p.extension().empty(); p = p.stem())
- v.push_back(p.extension().string());
+ v.push_back(p.extension().string()); // { dg-warning "deprecated" "" {
target c++26 } }
VERIFY( v.at(0) == ".tar" );
VERIFY( v.at(1) == ".baz" );
VERIFY( v.at(2) == ".bar" );
diff --git
a/libstdc++-v3/testsuite/27_io/filesystem/path/generic/display_native_string.cc
b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/display_native_string.cc
new file mode 100644
index 00000000000..6652713d580
--- /dev/null
+++
b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/display_native_string.cc
@@ -0,0 +1,66 @@
+// { dg-do run { target c++26 } }
+
+#include <filesystem>
+#include <testsuite_fs.h>
+#include <testsuite_hooks.h>
+
+using std::filesystem::path;
+
+#define WIDEN(S) ::std::__format::_Widen<CharT>(S, L##S)
+
+template<typename CharT>
+void
+test_display_and_native()
+{
+ std::string res;
+ path p;
+ auto verify_both = [&res](const path& p, std::string_view expected)
+ {
+ res = p.generic_display_string();
+ VERIFY( res == expected );
+ res = p.generic_native_encoded_string();
+ VERIFY( res == expected );
+ };
+
+ verify_both(WIDEN("/usr/include"), "/usr/include");
+ verify_both(WIDEN("foo///bar"), "foo/bar");
+ for (path p : __gnu_test::test_paths)
+ verify_both(p, p.generic_string()); // { dg-warning "deprecated" }
+
+ verify_both(
+
WIDEN("\u0428\u0447\u0443\u0447\u044B\u043D\u0448\u0447\u044B\u043D\u0430"),
+ "\u0428\u0447\u0443\u0447\u044B\u043D\u0448\u0447\u044B\u043D\u0430" );
+
+ if constexpr (path::preferred_separator == L'\\')
+ verify_both(WIDEN("C:\\foo\\bar"), "C:/foo/bar");
+}
+
+void
+test_display_invalid()
+{
+ std::string res;
+ auto verify_native_error = [&res](const path& p, std::string_view expected)
+ {
+ res = p.generic_display_string();
+ VERIFY( res == expected );
+ try { p.generic_native_encoded_string(); }
+ catch (const std::filesystem::filesystem_error&) {}
+ };
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ if constexpr (std::is_same_v<path::value_type, wchar_t>)
+ {
+ verify_native_error(L"\xd800", "\uFFFD");
+ verify_native_error(L"///\xd800", "/\uFFFD");
+ }
+#endif
+}
+
+int main()
+{
+ test_display_and_native<char>();
+#ifdef _GLIBCXX_USE_WCHAR_T
+ test_display_and_native<wchar_t>();
+ test_display_invalid();
+#endif
+}
diff --git
a/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc
b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc
index 77d5766089e..3dfa866a028 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/generic/generic_string.cc
@@ -23,6 +23,8 @@
#include <testsuite_fs.h>
#include <testsuite_hooks.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
using std::filesystem::path;
void
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/itr/traversal.cc
b/libstdc++-v3/testsuite/27_io/filesystem/path/itr/traversal.cc
index 9eeb829944b..2e829eb8f82 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/itr/traversal.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/itr/traversal.cc
@@ -25,6 +25,8 @@
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
using std::filesystem::path;
void
diff --git
a/libstdc++-v3/testsuite/27_io/filesystem/path/native/display_native_string.cc
b/libstdc++-v3/testsuite/27_io/filesystem/path/native/display_native_string.cc
new file mode 100644
index 00000000000..149b52b0530
--- /dev/null
+++
b/libstdc++-v3/testsuite/27_io/filesystem/path/native/display_native_string.cc
@@ -0,0 +1,66 @@
+// { dg-do run { target c++26 } }
+
+#include <filesystem>
+#include <testsuite_fs.h>
+#include <testsuite_hooks.h>
+
+using std::filesystem::path;
+
+#define WIDEN(S) ::std::__format::_Widen<CharT>(S, L##S)
+
+template<typename CharT>
+void
+test_display_and_native()
+{
+ std::string res;
+ path p;
+ auto verify_both = [&res](const path& p, std::string_view expected)
+ {
+ res = p.display_string();
+ VERIFY( res == expected );
+ res = p.native_encoded_string();
+ VERIFY( res == expected );
+ };
+
+ verify_both(WIDEN("/usr/include"), "/usr/include");
+ verify_both(WIDEN("foo///bar"), "foo///bar");
+ for (path p : __gnu_test::test_paths)
+ verify_both(p, p.string()); // { dg-warning "deprecated" }
+
+ verify_both(
+
WIDEN("\u0428\u0447\u0443\u0447\u044B\u043D\u0448\u0447\u044B\u043D\u0430"),
+ "\u0428\u0447\u0443\u0447\u044B\u043D\u0448\u0447\u044B\u043D\u0430" );
+
+ if constexpr (path::preferred_separator == L'\\')
+ verify_both(WIDEN("C:\\foo\\bar"), "C:\\foo\\bar");
+}
+
+void
+test_display_invalid()
+{
+ std::string res;
+ auto verify_native_error = [&res](const path& p, std::string_view expected)
+ {
+ res = p.display_string();
+ VERIFY( res == expected );
+ try { p.native_encoded_string(); }
+ catch (const std::filesystem::filesystem_error&) {}
+ };
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ if constexpr (std::is_same_v<path::value_type, wchar_t>)
+ {
+ verify_native_error(L"\xd800", "\uFFFD");
+ verify_native_error(L"///\xd800", "///\uFFFD");
+ }
+#endif
+}
+
+int main()
+{
+ test_display_and_native<char>();
+#ifdef _GLIBCXX_USE_WCHAR_T
+ test_display_and_native<wchar_t>();
+ test_display_invalid();
+#endif
+}
diff --git
a/libstdc++-v3/testsuite/27_io/filesystem/path/native/string-char8_t.cc
b/libstdc++-v3/testsuite/27_io/filesystem/path/native/string-char8_t.cc
index c8f2b3d2c62..996d58e7e59 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/native/string-char8_t.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/native/string-char8_t.cc
@@ -48,7 +48,7 @@ test02()
auto str = p.string<char>();
VERIFY( str == "abc" );
- VERIFY( str == p.string() );
+ VERIFY( str == p.string() ); // { dg-warning "deprecated" "" { target c++26
} }
#ifdef _GLIBCXX_USE_WCHAR_T
auto strw = p.string<wchar_t>();
diff --git a/libstdc++-v3/testsuite/27_io/print/1.cc
b/libstdc++-v3/testsuite/27_io/print/1.cc
index 58f1eb163df..4fd7f5dc925 100644
--- a/libstdc++-v3/testsuite/27_io/print/1.cc
+++ b/libstdc++-v3/testsuite/27_io/print/1.cc
@@ -7,6 +7,8 @@
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
void
test_print_default()
{
@@ -25,7 +27,7 @@ void
test_print_file()
{
__gnu_test::scoped_file f;
- FILE* strm = std::fopen(f.path.string().c_str(), "w");
+ FILE* strm = std::fopen(f.path.string().c_str(), "w");
VERIFY( strm );
std::print(strm, "File under '{}' for {}", 'O', "OUT OF FILE");
std::fclose(strm);
diff --git a/libstdc++-v3/testsuite/27_io/print/2.cc
b/libstdc++-v3/testsuite/27_io/print/2.cc
index 8aa7888e7bd..bf7bcb1d6ee 100644
--- a/libstdc++-v3/testsuite/27_io/print/2.cc
+++ b/libstdc++-v3/testsuite/27_io/print/2.cc
@@ -14,6 +14,8 @@
#include <io.h>
#endif
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
namespace std
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
diff --git a/libstdc++-v3/testsuite/27_io/print/3.cc
b/libstdc++-v3/testsuite/27_io/print/3.cc
index 90c4cfb0d48..c23d2f10e4f 100644
--- a/libstdc++-v3/testsuite/27_io/print/3.cc
+++ b/libstdc++-v3/testsuite/27_io/print/3.cc
@@ -7,6 +7,8 @@
#include <testsuite_hooks.h>
#include <testsuite_fs.h>
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
void
test_println_blank()
{
diff --git a/libstdc++-v3/testsuite/util/testsuite_fs.h
b/libstdc++-v3/testsuite/util/testsuite_fs.h
index 6940ae51aa6..fa099b0986b 100644
--- a/libstdc++-v3/testsuite/util/testsuite_fs.h
+++ b/libstdc++-v3/testsuite/util/testsuite_fs.h
@@ -67,6 +67,8 @@ namespace __gnu_test
compare_paths(const test_fs::path& p1,
const test_fs::path& p2)
{
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
PATH_CHK( p1, p2, native );
PATH_CHK( p1, p2, string );
PATH_CHK( p1, p2, empty );
@@ -90,7 +92,7 @@ namespace __gnu_test
throw test_fs::filesystem_error(
"!equal(begin1, end1, begin2)", p1, p2,
std::make_error_code(std::errc::invalid_argument) );
-
+#pragma GCC diagnostic pop
}
const std::string test_paths[] = {
--
2.54.0