https://gcc.gnu.org/g:16491e137c47ad36f9d73f070978841f1e8ca95d
commit r15-3935-g16491e137c47ad36f9d73f070978841f1e8ca95d Author: Jonathan Wakely <jwak...@redhat.com> Date: Fri Sep 27 15:53:04 2024 +0100 libstdc++: Refactor experimental::filesystem::path string conversions I noticed a -Wc++17-extensions warning due to use of if-constexpr in std::experimental::filesystem::path, which was not protected by diagnostic pragmas to disable the warning. While adding the pragmas I noticed that other places in the same file use tag dispatching and multiple overloads instead of if-constexpr. Since we're already using it in that file, we might as well just use it everywhere. libstdc++-v3/ChangeLog: * include/experimental/bits/fs_path.h (path::_Cvt): Refactor to use if-constexpr. (path::string(const Allocator&)): Likewise. Diff: --- libstdc++-v3/include/experimental/bits/fs_path.h | 137 +++++++++-------------- 1 file changed, 53 insertions(+), 84 deletions(-) diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h index 5008e26af8db..a504aa2492cc 100644 --- a/libstdc++-v3/include/experimental/bits/fs_path.h +++ b/libstdc++-v3/include/experimental/bits/fs_path.h @@ -775,60 +775,38 @@ namespace __detail __codecvt_utf8_to_wchar, __codecvt_utf8_to_utfNN>; -#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS -#ifdef _GLIBCXX_USE_CHAR8_T - static string_type - _S_wconvert(const char8_t* __f, const char8_t* __l, const char8_t*) - { - const char* __f2 = (const char*)__f; - const char* __l2 = (const char*)__l; - std::wstring __wstr; - std::codecvt_utf8_utf16<wchar_t> __wcvt; - if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt)) - return __wstr; - } -#endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr static string_type - _S_wconvert(const char* __f, const char* __l, const char*) - { - std::codecvt_utf8_utf16<wchar_t> __cvt; - std::wstring __wstr; - if (__str_codecvt_in_all(__f, __l, __wstr, __cvt)) - return __wstr; - _GLIBCXX_THROW_OR_ABORT(filesystem_error( - "Cannot convert character sequence", - std::make_error_code(errc::illegal_byte_sequence))); - } - - static string_type - _S_wconvert(const _CharT* __f, const _CharT* __l, const void*) + _S_convert(const _CharT* __f, const _CharT* __l) { - __codecvt_utf8_to_wide __cvt; - std::string __str; - if (__str_codecvt_out_all(__f, __l, __str, __cvt)) +#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS + if constexpr (is_same<_CharT, char>::value) { - const char* __f2 = __str.data(); - const char* __l2 = __f2 + __str.size(); - std::codecvt_utf8_utf16<wchar_t> __wcvt; + std::codecvt_utf8_utf16<wchar_t> __cvt; std::wstring __wstr; - if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt)) + // Convert char (assumed to be UTF-8) to wchar_t (UTF-16). + if (__str_codecvt_in_all(__f, __l, __wstr, __cvt)) return __wstr; } +#ifdef _GLIBCXX_USE_CHAR8_T + else if constexpr (is_same<_CharT, char8_t>::value) + return _S_convert((const char*)__f, (const char*)__l); +#endif + else + { + // Convert from _CharT to char first: + __codecvt_utf8_to_utfNN __cvt; + std::string __str; + if (__str_codecvt_out_all(__f, __l, __str, __cvt)) + // Then convert char to wchar_t: + return _S_convert(__str.c_str(), __str.c_str() + __str.size()); + } _GLIBCXX_THROW_OR_ABORT(filesystem_error( "Cannot convert character sequence", std::make_error_code(errc::illegal_byte_sequence))); - } - - static string_type - _S_convert(const _CharT* __f, const _CharT* __l) - { - return _S_wconvert(__f, __l, (const _CharT*)nullptr); - } -#else - static string_type - _S_convert(const _CharT* __f, const _CharT* __l) - { +#else // ! WINDOWS #ifdef _GLIBCXX_USE_CHAR8_T if constexpr (is_same<_CharT, char8_t>::value) return string_type(__f, __l); @@ -843,8 +821,9 @@ namespace __detail "Cannot convert character sequence", std::make_error_code(errc::illegal_byte_sequence))); } +#endif // ! WINDOWS } -#endif +#pragma GCC diagnostic pop static string_type _S_convert(_CharT* __f, _CharT* __l) @@ -1038,66 +1017,55 @@ namespace __detail std::swap(_M_type, __rhs._M_type); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr template<typename _CharT, typename _Traits, typename _Allocator> inline std::basic_string<_CharT, _Traits, _Allocator> path::string(const _Allocator& __a) const { - if _GLIBCXX17_CONSTEXPR (is_same<_CharT, value_type>::value) - return { _M_pathname.begin(), _M_pathname.end(), __a }; - using _WString = basic_string<_CharT, _Traits, _Allocator>; const value_type* __first = _M_pathname.data(); const value_type* __last = __first + _M_pathname.size(); + if constexpr (is_same<_CharT, value_type>::value) + return _WString(__first, __last, __a); #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS - using _CharAlloc = __alloc_rebind<_Allocator, char>; - using _String = basic_string<char, char_traits<char>, _CharAlloc>; - - // First convert native string from UTF-16 to to UTF-8. - // XXX This assumes that the execution wide-character set is UTF-16. - codecvt_utf8_utf16<value_type> __cvt; - _String __u8str{_CharAlloc{__a}}; - if (__str_codecvt_out_all(__first, __last, __u8str, __cvt)) + else { - struct - { - const _String* - operator()(const _String& __from, _String&, true_type) - { return std::__addressof(__from); } - - _WString* - operator()(const _String& __from, _WString& __to, false_type) + using _CharAlloc = __alloc_rebind<_Allocator, char>; + using _String = basic_string<char, char_traits<char>, _CharAlloc>; + + // First convert native string from UTF-16 to to UTF-8. + // XXX This assumes that the execution wide-character set is UTF-16. + codecvt_utf8_utf16<value_type> __cvt; + _String __u8str{_CharAlloc{__a}}; + if (__str_codecvt_out_all(__first, __last, __u8str, __cvt)) { + if constexpr (is_same<_CharT, char>::value) + return __u8str; #ifdef _GLIBCXX_USE_CHAR8_T - if constexpr (is_same<_CharT, char8_t>::value) - { - __to.assign(__from.begin(), __from.end()); - return std::__addressof(__to); - } - else + else if constexpr (is_same<_CharT, char8_t>::value) + return _WString(__u8str.begin(), __u8str.end(), __a); #endif - { + else + { + _WString __wstr(__a); // Convert UTF-8 to char16_t or char32_t string. typename path::_Cvt<_CharT>::__codecvt_utf8_to_wide __cvt; - const char* __f = __from.data(); - const char* __l = __f + __from.size(); - if (__str_codecvt_in_all(__f, __l, __to, __cvt)) - return std::__addressof(__to); - } - return nullptr; + const char* __f = __u8str.data(); + const char* __l = __f + __u8str.size(); + if (__str_codecvt_in_all(__f, __l, __wstr, __cvt)) + return __wstr; + } } - } __dispatch; - _WString __wstr(__a); - if (auto* __p = __dispatch(__u8str, __wstr, is_same<_CharT, char>{})) - return *__p; } #else // ! Windows #ifdef _GLIBCXX_USE_CHAR8_T - if constexpr (is_same<_CharT, char8_t>::value) - return _WString(__first, __last, __a); - else + else if constexpr (is_same<_CharT, char8_t>::value) + return _WString(__first, __last, __a); #endif + else { typename path::_Cvt<_CharT>::__codecvt_utf8_to_wide __cvt; _WString __wstr(__a); @@ -1109,6 +1077,7 @@ namespace __detail "Cannot convert character sequence", std::make_error_code(errc::illegal_byte_sequence))); } +#pragma GCC diagnostic pop inline std::string path::string() const { return string<char>(); }