On 14/01/21 13:41 +0000, Jonathan Wakely wrote:
<aside>
Is it the case that the wchar_t type is defined on this target, it's
just that libc doesn't have support for wcslen etc? Because we should
probably audit all our uses of _GLIBCXX_USE_WCHAR_T and find which
ones actually need libc support and which just need the wchar_t type
to exist. Some things really do need the libc support, but I suspect
many others don't.
It seems wrong that we can provide full support for char16_t and
char32_t but not wchar_t, just because the former two don't depend on
anything being present in libc. Why can't we just implement the same
functionality for wchar_t without using libc?
In fact, if we just define std::char_traits<wchar_t> generically
without using any libc functions (or just using them as optimisations)
we might be able to support std::basic_string<wchar_t> and iostream
classes with almost no work. But that's something to consider in the
future.
</aside>
Oops, I considered it already.
This untested patch should define std::char_traits<wchar_t> so it is
available if wchar_t is defined by the front end (which I assume is
always true, is that right?), only using optimized libc routines if
available.
This would be the first step to enabling std::wstring etc for targets
with no wchar_t support in libc.
diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h
index ea1e036f721..3a60478ea32 100644
--- a/libstdc++-v3/include/bits/char_traits.h
+++ b/libstdc++-v3/include/bits/char_traits.h
@@ -438,7 +438,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
-#ifdef _GLIBCXX_USE_WCHAR_T
+#ifdef __SIZEOF_WCHAR_T__
/// 21.1.3.2 char_traits specializations
template<>
struct char_traits<wchar_t>
@@ -469,23 +469,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__n == 0)
return 0;
-#if __cplusplus >= 201703L
- if (__builtin_constant_p(__n)
- && __constant_char_array_p(__s1, __n)
- && __constant_char_array_p(__s2, __n))
- return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
+#ifdef _GLIBCXX_USE_WCHAR_T
+ if (!__builtin_is_constant_evaluated())
+ return wmemcmp(__s1, __s2, __n);
#endif
- return wmemcmp(__s1, __s2, __n);
+ return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
}
static _GLIBCXX17_CONSTEXPR size_t
length(const char_type* __s)
{
-#if __cplusplus >= 201703L
- if (__constant_string_p(__s))
- return __gnu_cxx::char_traits<char_type>::length(__s);
+#ifdef _GLIBCXX_USE_WCHAR_T
+ if (!__builtin_is_constant_evaluated())
+ return wcslen(__s);
#endif
- return wcslen(__s);
+ return __gnu_cxx::char_traits<char_type>::length(__s);
}
static _GLIBCXX17_CONSTEXPR const char_type*
@@ -493,13 +491,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__n == 0)
return 0;
-#if __cplusplus >= 201703L
- if (__builtin_constant_p(__n)
- && __builtin_constant_p(__a)
- && __constant_char_array_p(__s, __n))
- return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
+#ifdef _GLIBCXX_USE_WCHAR_T
+ if (!__builtin_is_constant_evaluated())
+ return wmemchr(__s, __a, __n);
#endif
- return wmemchr(__s, __a, __n);
+ return __gnu_cxx::char_traits<char_type>::find(__s, __n, __a);
}
static _GLIBCXX20_CONSTEXPR char_type*
@@ -507,11 +503,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__n == 0)
return __s1;
-#ifdef __cpp_lib_is_constant_evaluated
- if (std::is_constant_evaluated())
- return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
+#ifdef _GLIBCXX_USE_WCHAR_T
+ if (!__builtin_is_constant_evaluated())
+ return wmemmove(__s1, __s2, __n);
#endif
- return wmemmove(__s1, __s2, __n);
+ return __gnu_cxx::char_traits<char_type>::move(__s1, __s2, __n);
}
static _GLIBCXX20_CONSTEXPR char_type*
@@ -519,11 +515,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__n == 0)
return __s1;
-#ifdef __cpp_lib_is_constant_evaluated
- if (std::is_constant_evaluated())
- return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
+#ifdef _GLIBCXX_USE_WCHAR_T
+ if (!__builtin_is_constant_evaluated())
+ return wmemcpy(__s1, __s2, __n);
#endif
- return wmemcpy(__s1, __s2, __n);
+ return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2, __n);
}
static _GLIBCXX20_CONSTEXPR char_type*
@@ -531,11 +527,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
if (__n == 0)
return __s;
-#ifdef __cpp_lib_is_constant_evaluated
- if (std::is_constant_evaluated())
- return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
+#ifdef _GLIBCXX_USE_WCHAR_T
+ if (!__builtin_is_constant_evaluated())
+ return wmemset(__s, __a, __n);
#endif
- return wmemset(__s, __a, __n);
+ return __gnu_cxx::char_traits<char_type>::assign(__s, __n, __a);
}
static _GLIBCXX_CONSTEXPR char_type
@@ -558,7 +554,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT
{ return eq_int_type(__c, eof()) ? 0 : __c; }
};
-#endif //_GLIBCXX_USE_WCHAR_T
+#endif // __SIZEOF_WCHAR_T__
#ifdef _GLIBCXX_USE_CHAR8_T
template<>