On Tue, Jan 27, 2026 at 7:15 PM Jonathan Wakely <[email protected]> wrote:

> On targets where wchar_t is unsigned we get warnings during the
> libstdc++ build:
>
> ctype_members.cc: In member function ‘virtual char
> std::ctype<wchar_t>::do_narrow(wchar_t, char) const’:
> ctype_members.cc:224:14: warning: comparison of unsigned expression in ‘>=
> 0’ is always true [-Wtype-limits]
>   224 |     if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
>       |         ~~~~~^~~~
> ctype_members.cc: In member function ‘virtual const wchar_t*
> std::ctype<wchar_t>::do_narrow(const wchar_t*, const wchar_t*, char, char*)
> const’:
> ctype_members.cc:247:21: warning: comparison of unsigned expression in ‘>=
> 0’ is always true [-Wtype-limits]
>   247 |           if (*__lo >= 0 && *__lo < 128)
>       |               ~~~~~~^~~~
>
> This introduces a helper function that converts the wchar_t to an
> unsigned type and then does the comparison. This means the comparison is
> not target-dependent, and there's no more warning.
>
> libstdc++-v3/ChangeLog:
>
>         * config/locale/gnu/ctype_members.cc (use_table): New function.
>         (ctype<wchar_t>::do_narrow): Use use_table.
> ---
>
> Tested x86_64-linux and aarch64-linux.

LGTM, assuming using C++11 features is fine (see question below).

>


>  libstdc++-v3/config/locale/gnu/ctype_members.cc | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
>
> diff --git a/libstdc++-v3/config/locale/gnu/ctype_members.cc
> b/libstdc++-v3/config/locale/gnu/ctype_members.cc
> index 183babb6c3f6..b34446a61ee1 100644
> --- a/libstdc++-v3/config/locale/gnu/ctype_members.cc
> +++ b/libstdc++-v3/config/locale/gnu/ctype_members.cc
> @@ -217,11 +217,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      return __hi;
>    }
>
> +  // True if c can be looked up in _M_narrow.
> +  [[gnu::always_inline]]
> +  static inline bool
> +  use_table(wchar_t c)
> +  {
> +    using U = std::make_unsigned<wchar_t>::type;
>
This is C++11 feature, and ctype facet in C++98, so at first glance this
seems like a problem.
However,  this is part of the object file and it is compiled during build,
so it strictly depends on what standard
we compile the source file. What is the approach here? If it is documented
somewhere, just drop a link.

> +    return U(c) < 128;
> +  }
> +
>    char
>    ctype<wchar_t>::
>    do_narrow(wchar_t __wc, char __dfault) const
>    {
> -    if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
> +    if (use_table(__wc) && _M_narrow_ok)
>        return _M_narrow[__wc];
>  #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2)
>      __c_locale __old = __uselocale(_M_c_locale_ctype);
> @@ -244,7 +253,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      if (_M_narrow_ok)
>        while (__lo < __hi)
>         {
> -         if (*__lo >= 0 && *__lo < 128)
> +         if (use_table(*__lo))
>             *__dest = _M_narrow[*__lo];
>           else
>             {
> --
> 2.52.0
>
>

Reply via email to