[libcxx] Implement c++2a char8_t input/output of std::filesystem::path

This implements the std::filesystem parts of P0482 (which is already
marked as in progress), and applies the actions that are suggested
in P1423.

Differential Revision: https://reviews.llvm.org/D90222
This commit is contained in:
Martin Storsjö 2020-10-26 13:18:46 +02:00
parent c17fdca188
commit 6be11e35d5
9 changed files with 100 additions and 6 deletions

View File

@ -115,7 +115,7 @@
"`P1208 <https://wg21.link/P1208>`__","LWG","Adopt source_location for C++20","Cologne","",""
"`P1355 <https://wg21.link/P1355>`__","LWG","Exposing a narrow contract for ceil2","Cologne","|Complete|","9.0"
"`P1361 <https://wg21.link/P1361>`__","LWG","Integration of chrono with text formatting","Cologne","",""
"`P1423 <https://wg21.link/P1423>`__","LWG","char8_t backward compatibility remediation","Cologne","",""
"`P1423 <https://wg21.link/P1423>`__","LWG","char8_t backward compatibility remediation","Cologne","|In Progress|",""
"`P1424 <https://wg21.link/P1424>`__","LWG","'constexpr' feature macro concerns","Cologne","Superseded by `P1902 <https://wg21.link/P1902>`__",""
"`P1466 <https://wg21.link/P1466>`__","LWG","Miscellaneous minor fixes for chrono","Cologne","",""
"`P1474 <https://wg21.link/P1474>`__","LWG","Helpful pointers for ContiguousIterator","Cologne","",""

1 Paper # Group Paper Name Meeting Status First released version
115 `P1208 <https://wg21.link/P1208>`__ LWG Adopt source_location for C++20 Cologne
116 `P1355 <https://wg21.link/P1355>`__ LWG Exposing a narrow contract for ceil2 Cologne |Complete| 9.0
117 `P1361 <https://wg21.link/P1361>`__ LWG Integration of chrono with text formatting Cologne
118 `P1423 <https://wg21.link/P1423>`__ LWG char8_t backward compatibility remediation Cologne |In Progress|
119 `P1424 <https://wg21.link/P1424>`__ LWG 'constexpr' feature macro concerns Cologne Superseded by `P1902 <https://wg21.link/P1902>`__
120 `P1466 <https://wg21.link/P1466>`__ LWG Miscellaneous minor fixes for chrono Cologne
121 `P1474 <https://wg21.link/P1474>`__ LWG Helpful pointers for ContiguousIterator Cologne

View File

@ -56,3 +56,9 @@ API Changes
- ``ceil2`` has been renamed to ``bit_ceil``
- ``floor2`` has been renamed to ``bit_floor``
- ``log2p1`` has been renamed to ``bit_width``
- In C++20 mode, ``std::filesystem::path::u8string()`` and
``generic_u8string()`` now return ``std::u8string`` according to P0428,
while they return ``std::string`` in C++17. This can cause source
incompatibility, which is discussed and acknowledged in P1423, but that
paper doesn't suggest any remediation for this incompatibility.

View File

@ -989,6 +989,12 @@ typedef unsigned int char32_t;
# define _LIBCPP_DEPRECATED_IN_CXX20
#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))

View File

@ -547,6 +547,13 @@ struct __can_convert_char<wchar_t> {
static const bool value = true;
using __char_type = wchar_t;
};
#ifndef _LIBCPP_NO_HAS_CHAR8_T
template <>
struct __can_convert_char<char8_t> {
static const bool value = true;
using __char_type = char8_t;
};
#endif
template <>
struct __can_convert_char<char16_t> {
static const bool value = true;
@ -995,7 +1002,11 @@ public:
_LIBCPP_INLINE_VISIBILITY operator string_type() const { return __pn_; }
_LIBCPP_INLINE_VISIBILITY _VSTD::string string() const { return __pn_; }
#ifndef _LIBCPP_NO_HAS_CHAR8_T
_LIBCPP_INLINE_VISIBILITY _VSTD::u8string u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
#else
_LIBCPP_INLINE_VISIBILITY _VSTD::string u8string() const { return __pn_; }
#endif
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
template <class _ECharT, class _Traits = char_traits<_ECharT>,
@ -1023,7 +1034,11 @@ public:
// generic format observers
_VSTD::string generic_string() const { return __pn_; }
#ifndef _LIBCPP_NO_HAS_CHAR8_T
_VSTD::u8string generic_u8string() const { return _VSTD::u8string(__pn_.begin(), __pn_.end()); }
#else
_VSTD::string generic_u8string() const { return __pn_; }
#endif
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
template <class _ECharT, class _Traits = char_traits<_ECharT>,
@ -1213,23 +1228,37 @@ _LIBCPP_FUNC_VIS
size_t hash_value(const path& __p) noexcept;
template <class _Source>
_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
is_same<typename __is_pathable<_Source>::__char_type, char8_t>::value ||
#endif
is_same<typename __is_pathable<_Source>::__char_type, char>::value,
"u8path(Source const&) requires Source have a character type of type "
"'char'");
"'char'"
#ifndef _LIBCPP_NO_HAS_CHAR8_T
" or 'char8_t'"
#endif
);
return path(__s);
}
template <class _InputIt>
_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
is_same<typename __is_pathable<_InputIt>::__char_type, char8_t>::value ||
#endif
is_same<typename __is_pathable<_InputIt>::__char_type, char>::value,
"u8path(Iter, Iter) requires Iter have a value_type of type 'char'");
"u8path(Iter, Iter) requires Iter have a value_type of type 'char'"
#ifndef _LIBCPP_NO_HAS_CHAR8_T
" or 'char8_t'"
#endif
);
return path(__f, __l);
}

View File

@ -123,6 +123,9 @@ void test_sfinae() {
int main(int, char**) {
for (auto const& MS : PathList) {
RunTestCase<char>(MS);
#if TEST_STD_VER > 17 && defined(__cpp_char8_t)
RunTestCase<char8_t>(MS);
#endif
RunTestCase<wchar_t>(MS);
RunTestCase<char16_t>(MS);
RunTestCase<char32_t>(MS);

View File

@ -45,8 +45,15 @@ int main(int, char**)
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();

View File

@ -46,8 +46,15 @@ int main(int, char**)
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();

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
// <filesystem>
@ -48,6 +49,29 @@ int main(int, char**)
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;
}

View File

@ -430,16 +430,28 @@ struct CWDGuard {
// Misc test types
#define MKSTR(Str) {Str, TEST_CONCAT(L, Str), TEST_CONCAT(u, Str), TEST_CONCAT(U, Str)}
#if TEST_STD_VER > 17 && defined(__cpp_char8_t)
#define CHAR8_ONLY(x) x,
#else
#define CHAR8_ONLY(x)
#endif
#define MKSTR(Str) {Str, TEST_CONCAT(L, Str), CHAR8_ONLY(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;
#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; }
};