diff mbox series

[2/2] stdlib: Fix stdbit.h with -Wconversion for clang

Message ID 20240104194731.2357574-3-adhemerval.zanella@linaro.org
State New
Headers show
Series stdlib: Fix stdbit.h with -Wconversion | expand

Commit Message

Adhemerval Zanella Netto Jan. 4, 2024, 7:47 p.m. UTC
With clang 14 and also with main the tst-stdbit-Wconversion
issues the warnings:

  ../stdlib/stdbit.h:701:40: error: implicit conversion loses integer
  precision: 'int' to 'uint16_t' (aka 'unsigned short')
  [-Werror,-Wimplicit-int-conversion]
    return __x == 0 ? 0 : ((uint16_t) 1) << (__bw16_inline (__x) - 1);
    ~~~~~~                ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ../stdlib/stdbit.h:707:39: error: implicit conversion loses integer
  precision: 'int' to 'uint8_t' (aka 'unsigned char')
  [-Werror,-Wimplicit-int-conversion]
    return __x == 0 ? 0 : ((uint8_t) 1) << (__bw8_inline (__x) - 1);
    ~~~~~~                ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
  ../stdlib/stdbit.h:751:40: error: implicit conversion loses integer
  precision: 'int' to 'uint16_t' (aka 'unsigned short')
  [-Werror,-Wimplicit-int-conversion]
    return __x <= 1 ? 1 : ((uint16_t) 2) << (__bw16_inline (__x - 1) - 1);
    ~~~~~~                ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  ../stdlib/stdbit.h:757:39: error: implicit conversion loses integer
  precision: 'int' to 'uint8_t' (aka 'unsigned char')
  [-Werror,-Wimplicit-int-conversion]
    return __x <= 1 ? 1 : ((uint8_t) 2) << (__bw8_inline (__x - 1) - 1);
    ~~~~~~                ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  tst-stdbit-Wconversion.c:45:31: error: implicit conversion loses integer
  precision: 'unsigned short' to 'uint8_t' (aka 'unsigned char')
  [-Werror,-Wimplicit-int-conversion]
    (void) stdc_trailing_zeros (us);
           ~~~~~~~~~~~~~~~~~~~~~^~~
  ../stdlib/stdbit.h:164:30: note: expanded from macro
  'stdc_trailing_zeros'
     : stdc_trailing_zeros_uc (x))
       ~~~~~~~~~~~~~~~~~~~~~~~~^~
  ../stdlib/stdbit.h:191:52: note: expanded from macro
  'stdc_trailing_zeros_uc'
  # define stdc_trailing_zeros_uc(x) (__ctz8_inline (x))
                                      ~~~~~~~~~~~~~  ^
  tst-stdbit-Wconversion.c:46:31: error: implicit conversion loses integer
  precision: 'unsigned int' to 'uint16_t' (aka 'unsigned short')
  [-Werror,-Wimplicit-int-conversion]
    (void) stdc_trailing_zeros (ui);
           ~~~~~~~~~~~~~~~~~~~~~^~~
  ../stdlib/stdbit.h:163:48: note: expanded from macro
  'stdc_trailing_zeros'
     : sizeof (x) == 2 ? stdc_trailing_zeros_us (x)       \
                         ~~~~~~~~~~~~~~~~~~~~~~~~^~
  ../stdlib/stdbit.h:192:53: note: expanded from macro
  'stdc_trailing_zeros_us'
  # define stdc_trailing_zeros_us(x) (__ctz16_inline (x))
                                      ~~~~~~~~~~~~~~  ^
  tst-stdbit-Wconversion.c:46:31: error: implicit conversion loses integer
  precision: 'unsigned int' to 'uint8_t' (aka 'unsigned char')
  [-Werror,-Wimplicit-int-conversion]
    (void) stdc_trailing_zeros (ui);
           ~~~~~~~~~~~~~~~~~~~~~^~~
  ../stdlib/stdbit.h:164:30: note: expanded from macro
  'stdc_trailing_zeros'
     : stdc_trailing_zeros_uc (x))
       ~~~~~~~~~~~~~~~~~~~~~~~~^~
  ../stdlib/stdbit.h:191:52: note: expanded from macro
  'stdc_trailing_zeros_uc'
  # define stdc_trailing_zeros_uc(x) (__ctz8_inline (x))
                                      ~~~~~~~~~~~~~  ^
  tst-stdbit-Wconversion.c:47:31: error: implicit conversion loses integer
  precision: 'unsigned long' to 'uint16_t' (aka 'unsigned short')
  [-Werror,-Wimplicit-int-conversion]
    (void) stdc_trailing_zeros (ul);
           ~~~~~~~~~~~~~~~~~~~~~^~~
  ../stdlib/stdbit.h:163:48: note: expanded from macro
  'stdc_trailing_zeros'
     : sizeof (x) == 2 ? stdc_trailing_zeros_us (x)       \
                         ~~~~~~~~~~~~~~~~~~~~~~~~^~
  ../stdlib/stdbit.h:192:53: note: expanded from macro
  'stdc_trailing_zeros_us'
  # define stdc_trailing_zeros_us(x) (__ctz16_inline (x))
                                      ~~~~~~~~~~~~~~  ^
  [...]

It seems to boiler down to __builtin_clz not having a variant for 8 or
16 bits.  Fix it by explicit casting to the expected types.  Although
not strickly required for older gcc, using the same __pacify macro
simpify the required code.

Checked on x86_64-linux-gnu and i686-linux-gnu.
---
 stdlib/stdbit.h | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

Comments

Joseph Myers Jan. 4, 2024, 8:07 p.m. UTC | #1
On Thu, 4 Jan 2024, Adhemerval Zanella wrote:

> -# define stdc_trailing_zeros_uc(x) (__ctz8_inline (x))
> -# define stdc_trailing_zeros_us(x) (__ctz16_inline (x))
> +# define stdc_trailing_zeros_uc(x) (__ctz8_inline (__pacify_uint8 (x)))
> +# define stdc_trailing_zeros_us(x) (__ctz16_inline (__pacify_uint16 (x)))

For all of these cases, I think the __pacify calls should go in the 
type-generic macros, not the type-specific ones.  For the type-specific 
macros I think it's best to have the implicit conversions (to ensure the 
user gets the expected diagnostics for an implicit conversion if they've 
somehow passed a type for which an implicit conversion is invalid, e.g. a 
pointer type - an actual function call would have an implicit conversion, 
and the type-specific macros should have effects as similar as possible to 
a function call, which the current definitions achieve by directly calling 
an inline function).
diff mbox series

Patch

diff --git a/stdlib/stdbit.h b/stdlib/stdbit.h
index 2945550385..9daf414651 100644
--- a/stdlib/stdbit.h
+++ b/stdlib/stdbit.h
@@ -42,7 +42,8 @@ 
 __BEGIN_DECLS
 
 /* Use __pacify_uint16 (N) instead of (uint16_t) (N) when the cast is helpful
-   only to pacify older GCC (e.g., GCC 10 -Wconversion) or non-GCC.  */
+   only to pacify older GCC (e.g., GCC 10 -Wconversion) or non-GCC (e.g
+   clang -Wimplicit-int-conversion).  */
 #if __GNUC_PREREQ (11, 0)
 # define __pacify_uint8(n)  (n)
 # define __pacify_uint16(n) (n)
@@ -198,8 +199,8 @@  __ctz8_inline (uint8_t __x)
   return __x == 0 ? 8U : (unsigned int) __builtin_ctz (__x);
 }
 
-# define stdc_trailing_zeros_uc(x) (__ctz8_inline (x))
-# define stdc_trailing_zeros_us(x) (__ctz16_inline (x))
+# define stdc_trailing_zeros_uc(x) (__ctz8_inline (__pacify_uint8 (x)))
+# define stdc_trailing_zeros_us(x) (__ctz16_inline (__pacify_uint16 (x)))
 # define stdc_trailing_zeros_ui(x) (__ctz32_inline (x))
 # if __WORDSIZE == 64
 #  define stdc_trailing_zeros_ul(x) (__ctz64_inline (x))
@@ -302,8 +303,8 @@  __flz8_inline (uint8_t __x)
   return __x == (uint8_t) -1 ? 0 : 1 + __clo8_inline (__x);
 }
 
-# define stdc_first_leading_zero_uc(x) (__flz8_inline (x))
-# define stdc_first_leading_zero_us(x) (__flz16_inline (x))
+# define stdc_first_leading_zero_uc(x) (__flz8_inline (__pacify_uint8 (x)))
+# define stdc_first_leading_zero_us(x) (__flz16_inline (__pacify_uint16 (x)))
 # define stdc_first_leading_zero_ui(x) (__flz32_inline (x))
 # if __WORDSIZE == 64
 #  define stdc_first_leading_zero_ul(x) (__flz64_inline (x))
@@ -356,8 +357,8 @@  __flo8_inline (uint8_t __x)
   return __x == 0 ? 0 : 1 + __clz8_inline (__x);
 }
 
-# define stdc_first_leading_one_uc(x) (__flo8_inline (x))
-# define stdc_first_leading_one_us(x) (__flo16_inline (x))
+# define stdc_first_leading_one_uc(x) (__flo8_inline (__pacify_uint8 (x)))
+# define stdc_first_leading_one_us(x) (__flo16_inline (__pacify_uint16 (x)))
 # define stdc_first_leading_one_ui(x) (__flo32_inline (x))
 # if __WORDSIZE == 64
 #  define stdc_first_leading_one_ul(x) (__flo64_inline (x))
@@ -410,8 +411,8 @@  __ftz8_inline (uint8_t __x)
   return __x == (uint8_t) -1 ? 0 : 1 + __cto8_inline (__x);
 }
 
-# define stdc_first_trailing_zero_uc(x) (__ftz8_inline (x))
-# define stdc_first_trailing_zero_us(x) (__ftz16_inline (x))
+# define stdc_first_trailing_zero_uc(x) (__ftz8_inline (__pacify_uint8 (x)))
+# define stdc_first_trailing_zero_us(x) (__ftz16_inline (__pacify_uint16 (x)))
 # define stdc_first_trailing_zero_ui(x) (__ftz32_inline (x))
 # if __WORDSIZE == 64
 #  define stdc_first_trailing_zero_ul(x) (__ftz64_inline (x))
@@ -464,8 +465,8 @@  __fto8_inline (uint8_t __x)
   return __x == 0 ? 0 : 1 + __ctz8_inline (__x);
 }
 
-# define stdc_first_trailing_one_uc(x) (__fto8_inline (x))
-# define stdc_first_trailing_one_us(x) (__fto16_inline (x))
+# define stdc_first_trailing_one_uc(x) (__fto8_inline (__pacify_uint8 (x)))
+# define stdc_first_trailing_one_us(x) (__fto16_inline (__pacify_uint16 (x)))
 # define stdc_first_trailing_one_ui(x) (__fto32_inline (x))
 # if __WORDSIZE == 64
 #  define stdc_first_trailing_one_ul(x) (__fto64_inline (x))