diff --git a/libcxx/include/filesystem b/libcxx/include/filesystem --- a/libcxx/include/filesystem +++ b/libcxx/include/filesystem @@ -1193,7 +1193,12 @@ #if defined(_LIBCPP_WIN32API) _LIBCPP_INLINE_VISIBILITY _VSTD::wstring wstring() const { return __pn_; } - _VSTD::wstring generic_wstring() const { return __pn_; } + _VSTD::wstring generic_wstring() const { + _VSTD::wstring __s; + __s.resize(__pn_.size()); + _VSTD::replace_copy(__pn_.begin(), __pn_.end(), __s.begin(), '\\', '/'); + return __s; + } #if !defined(_LIBCPP_HAS_NO_LOCALIZATION) template , @@ -1230,13 +1235,24 @@ class _Allocator = allocator<_ECharT> > basic_string<_ECharT, _Traits, _Allocator> generic_string(const _Allocator& __a = _Allocator()) const { - return string<_ECharT, _Traits, _Allocator>(__a); + using _Str = basic_string<_ECharT, _Traits, _Allocator>; + _Str __s = string<_ECharT, _Traits, _Allocator>(__a); + // Note: This (and generic_u8string below) is slightly suboptimal as + // it iterates twice over the string; once to convert it to the right + // character type, and once to replace path delimiters. + _VSTD::replace(__s.begin(), __s.end(), + static_cast<_ECharT>('\\'), static_cast<_ECharT>('/')); + return __s; } _VSTD::string generic_string() const { return generic_string(); } _VSTD::u16string generic_u16string() const { return generic_string(); } _VSTD::u32string generic_u32string() const { return generic_string(); } - __u8_string generic_u8string() const { return u8string(); } + __u8_string generic_u8string() const { + __u8_string __s = u8string(); + _VSTD::replace(__s.begin(), __s.end(), '\\', '/'); + return __s; + } #endif /* !_LIBCPP_HAS_NO_LOCALIZATION */ #else /* _LIBCPP_WIN32API */ diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp --- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp @@ -32,17 +32,24 @@ #include "min_allocator.h" #include "filesystem_test_helper.h" -MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); +MultiStringType input = MKSTR("c:\\foo\\bar"); +#ifdef _WIN32 +// On windows, the generic_* accessors return a path with forward slashes +MultiStringType ref = MKSTR("c:/foo/bar"); +#else +// On posix, the input string is returned as-is +MultiStringType ref = MKSTR("c:\\foo\\bar"); +#endif int main(int, char**) { using namespace fs; - auto const& MS = longString; - const char* value = longString; + auto const& MS = ref; + const char* value = input; const path p(value); { std::string s = p.generic_string(); - assert(s == value); + assert(s == (const char*)MS); } { #if TEST_STD_VER > 17 && defined(__cpp_char8_t)