Index: libcxx/include/__config =================================================================== --- libcxx/include/__config +++ libcxx/include/__config @@ -999,6 +999,12 @@ # define _LIBCPP_DEPRECATED_IN_CXX17 #endif +#if !defined(_LIBCPP_NO_HAS_CHAR8_T) +# define _LIBCPP_DEPRECATED_WITH_CHAR8_T _LIBCPP_DEPRECATED +#else +# define _LIBCPP_DEPRECATED_WITH_CHAR8_T +#endif + // Macros to enter and leave a state where deprecation warnings are suppressed. #if !defined(_LIBCPP_SUPPRESS_DEPRECATED_PUSH) && \ (defined(_LIBCPP_COMPILER_CLANG) || defined(_LIBCPP_COMPILER_GCC)) Index: libcxx/include/filesystem =================================================================== --- libcxx/include/filesystem +++ libcxx/include/filesystem @@ -543,6 +543,13 @@ static const bool value = true; using __char_type = wchar_t; }; +#ifndef _LIBCPP_NO_HAS_CHAR8_T +template <> +struct __can_convert_char { + static const bool value = true; + using __char_type = char8_t; +}; +#endif template <> struct __can_convert_char { static const bool value = true; @@ -999,7 +1006,11 @@ _LIBCPP_INLINE_VISIBILITY std::wstring wstring() const { return string(); } +#ifndef _LIBCPP_NO_HAS_CHAR8_T + _LIBCPP_INLINE_VISIBILITY std::u8string u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); } +#else _LIBCPP_INLINE_VISIBILITY std::string u8string() const { return __pn_; } +#endif _LIBCPP_INLINE_VISIBILITY std::u16string u16string() const { return string(); } @@ -1017,7 +1028,11 @@ std::string generic_string() const { return __pn_; } std::wstring generic_wstring() const { return string(); } +#ifndef _LIBCPP_NO_HAS_CHAR8_T + std::u8string generic_u8string() const { return std::u8string(__pn_.begin(), __pn_.end()); } +#else std::string generic_u8string() const { return __pn_; } +#endif std::u16string generic_u16string() const { return string(); } std::u32string generic_u32string() const { return string(); } @@ -1194,10 +1209,14 @@ size_t hash_value(const path& __p) noexcept; template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T typename enable_if<__is_pathable<_Source>::value, path>::type u8path(const _Source& __s) { static_assert( +#ifndef _LIBCPP_NO_HAS_CHAR8_T + // Proposed in P1423 + is_same::__char_type, char8_t>::value || +#endif is_same::__char_type, char>::value, "u8path(Source const&) requires Source have a character type of type " "'char'"); @@ -1205,10 +1224,14 @@ } template -_LIBCPP_INLINE_VISIBILITY +_LIBCPP_INLINE_VISIBILITY _LIBCPP_DEPRECATED_WITH_CHAR8_T typename enable_if<__is_pathable<_InputIt>::value, path>::type u8path(_InputIt __f, _InputIt __l) { static_assert( +#ifndef _LIBCPP_NO_HAS_CHAR8_T + // Proposed in P1423 + is_same::__char_type, char8_t>::value || +#endif is_same::__char_type, char>::value, "u8path(Iter, Iter) requires Iter have a value_type of type 'char'"); return path(__f, __l); Index: libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/source.pass.cpp =================================================================== --- libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/source.pass.cpp +++ libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/source.pass.cpp @@ -122,6 +122,9 @@ int main(int, char**) { for (auto const& MS : PathList) { RunTestCase(MS); +#if TEST_STD_VER > 17 && defined(__cpp_char8_t) + RunTestCase(MS); +#endif RunTestCase(MS); RunTestCase(MS); RunTestCase(MS); Index: libcxx/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp =================================================================== --- libcxx/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp +++ libcxx/test/std/input.output/filesystems/class.path/path.member/path.generic.obs/named_overloads.pass.cpp @@ -42,8 +42,15 @@ assert(s == value); } { +#if TEST_STD_VER > 17 && defined(__cpp_char8_t) + ASSERT_SAME_TYPE(decltype(p.generic_u8string()), std::u8string); + std::u8string s = p.generic_u8string(); + assert(s == (const char8_t*)MS); +#else + ASSERT_SAME_TYPE(decltype(p.generic_u8string()), std::string); std::string s = p.generic_u8string(); assert(s == (const char*)MS); +#endif } { std::wstring s = p.generic_wstring(); Index: libcxx/test/std/input.output/filesystems/class.path/path.member/path.native.obs/named_overloads.pass.cpp =================================================================== --- libcxx/test/std/input.output/filesystems/class.path/path.member/path.native.obs/named_overloads.pass.cpp +++ libcxx/test/std/input.output/filesystems/class.path/path.member/path.native.obs/named_overloads.pass.cpp @@ -43,8 +43,15 @@ assert(s == value); } { +#if TEST_STD_VER > 17 && defined(__cpp_char8_t) + ASSERT_SAME_TYPE(decltype(p.u8string()), std::u8string); + std::u8string s = p.u8string(); + assert(s == (const char8_t*)MS); +#else + ASSERT_SAME_TYPE(decltype(p.u8string()), std::string); std::string s = p.u8string(); assert(s == (const char*)MS); +#endif } { std::wstring s = p.wstring(); Index: libcxx/test/std/input.output/filesystems/class.path/path.nonmember/path.factory.pass.cpp =================================================================== --- libcxx/test/std/input.output/filesystems/class.path/path.nonmember/path.factory.pass.cpp +++ libcxx/test/std/input.output/filesystems/class.path/path.nonmember/path.factory.pass.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03 +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS // @@ -48,6 +49,29 @@ path p = fs::u8path(In3, In3End); assert(p == In1); } +#if TEST_STD_VER > 17 && defined(__cpp_char8_t) && defined(_LIBCPP_VERSION) + const char8_t* u8In1 = u8"abcd/efg"; + const std::u8string u8In2(u8In1); + const auto u8In3 = u8In2.begin(); + const auto u8In3End = u8In2.end(); + // Proposed in P1423, marked tested only for libc++ + { + path p = fs::u8path(u8In1); + assert(p == In1); + } + { + path p = fs::u8path(u8In2); + assert(p == In1); + } + { + path p = fs::u8path(u8In3); + assert(p == In1); + } + { + path p = fs::u8path(u8In3, u8In3End); + assert(p == In1); + } +#endif return 0; } Index: libcxx/test/support/filesystem_test_helper.h =================================================================== --- libcxx/test/support/filesystem_test_helper.h +++ libcxx/test/support/filesystem_test_helper.h @@ -418,16 +418,24 @@ // Misc test types -#define MKSTR(Str) {Str, TEST_CONCAT(L, Str), TEST_CONCAT(u, Str), TEST_CONCAT(U, Str)} +#define MKSTR(Str) {Str, TEST_CONCAT(L, Str), TEST_CONCAT(u8, Str), TEST_CONCAT(u, Str), TEST_CONCAT(U, Str)} struct MultiStringType { const char* s; const wchar_t* w; +#if TEST_STD_VER > 17 && defined(__cpp_char8_t) + const char8_t* u8; +#else + const char* dummy; +#endif const char16_t* u16; const char32_t* u32; operator const char* () const { return s; } operator const wchar_t* () const { return w; } +#if TEST_STD_VER > 17 && defined(__cpp_char8_t) + operator const char8_t* () const { return u8; } +#endif operator const char16_t* () const { return u16; } operator const char32_t* () const { return u32; } };