[PATCH] newlib/libc/stdbit: Fix static assertions for 16-bit int
Jonathan Wakely <[email protected]> Mon, 20 Apr 2026 16:24:21 +0100
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
All the USHRT_WIDTH < UINT_WIDTH assertions fail for 16-bit int targets, such as msp430-elf. Remove those static assertions and instead fix the stdc_xxx_us functions to work correctly when USHRT_WIDTH == UINT_WIDTH. Signed-off-by: Jonathan Wakely <[email protected]> --- This is untested, except to check that it now compiles on msp430-elf and still compiles on arm-eabi. newlib/libc/stdbit/stdc_bit_ceil.c | 9 +++++---- newlib/libc/stdbit/stdc_leading_ones.c | 10 ++++++---- newlib/libc/stdbit/stdc_leading_zeros.c | 10 ++++++---- newlib/libc/stdbit/stdc_trailing_ones.c | 10 ++++++---- newlib/libc/stdbit/stdc_trailing_zeros.c | 11 +++++++---- 5 files changed, 30 insertions(+), 20 deletions(-) diff --git a/newlib/libc/stdbit/stdc_bit_ceil.c b/newlib/libc/stdbit/stdc_bit_ceil.c index f25d184af..7ffed05f4 100644 --- a/newlib/libc/stdbit/stdc_bit_ceil.c +++ b/newlib/libc/stdbit/stdc_bit_ceil.c @@ -23,16 +23,17 @@ stdc_bit_ceil_uc(unsigned char x) return (1U << (UINT_WIDTH - __builtin_clz(x - 1))); } -/* Ensure we don't shift 1U out of range. */ -_Static_assert(USHRT_WIDTH < UINT_WIDTH, - "stdc_bit_ceil_us needs USHRT_WIDTH < UINT_WIDTH"); - unsigned short stdc_bit_ceil_us(unsigned short x) { if (x <= 1) return (1); +#if USHRT_WIDTH == UINT_WIDTH + if (x > USHRT_MAX/2 + 1) + return (0); +#endif + return (1U << (UINT_WIDTH - __builtin_clz(x - 1))); } diff --git a/newlib/libc/stdbit/stdc_leading_ones.c b/newlib/libc/stdbit/stdc_leading_ones.c index c7ab75b98..48f61d71e 100644 --- a/newlib/libc/stdbit/stdc_leading_ones.c +++ b/newlib/libc/stdbit/stdc_leading_ones.c @@ -22,13 +22,15 @@ stdc_leading_ones_uc(unsigned char x) return (__builtin_clz(~(x << offset))); } -/* Avoid triggering undefined behavior if x == 0. */ -_Static_assert(USHRT_WIDTH < UINT_WIDTH, - "stdc_leading_ones_us needs USHRT_WIDTH < UINT_WIDTH"); - unsigned int stdc_leading_ones_us(unsigned short x) { +#if USHRT_WIDTH == UINT_WIDTH + /* Avoid triggering undefined behavior if x == 0. */ + if (x == ~0U) + return (USHRT_WIDTH); +#endif + const int offset = UINT_WIDTH - USHRT_WIDTH; return (__builtin_clz(~(x << offset))); diff --git a/newlib/libc/stdbit/stdc_leading_zeros.c b/newlib/libc/stdbit/stdc_leading_zeros.c index dba6a14e2..204f71e21 100644 --- a/newlib/libc/stdbit/stdc_leading_zeros.c +++ b/newlib/libc/stdbit/stdc_leading_zeros.c @@ -22,13 +22,15 @@ stdc_leading_zeros_uc(unsigned char x) return (__builtin_clz((x << offset) + (1U << (offset - 1)))); } -/* Offset must be greater than zero. */ -_Static_assert(USHRT_WIDTH < UINT_WIDTH, - "stdc_leading_zeros_us needs USHRT_WIDTH < UINT_WIDTH"); - unsigned int stdc_leading_zeros_us(unsigned short x) { +#if USHRT_WIDTH == UINT_WIDTH + /* Offset must be greater than zero. */ + if (x == 0) + return (USHRT_WIDTH); +#endif + const int offset = UINT_WIDTH - USHRT_WIDTH; return (__builtin_clz((x << offset) + (1U << (offset - 1)))); diff --git a/newlib/libc/stdbit/stdc_trailing_ones.c b/newlib/libc/stdbit/stdc_trailing_ones.c index 0f7ccb553..22f002878 100644 --- a/newlib/libc/stdbit/stdc_trailing_ones.c +++ b/newlib/libc/stdbit/stdc_trailing_ones.c @@ -20,13 +20,15 @@ stdc_trailing_ones_uc(unsigned char x) return (__builtin_ctz(~x)); } -/* Avoid triggering undefined behavior if x == ~0. */ -_Static_assert(USHRT_WIDTH < UINT_WIDTH, - "stdc_trailing_ones_uc needs USHRT_WIDTH < UINT_WIDTH"); - unsigned int stdc_trailing_ones_us(unsigned short x) { +#if USHRT_WIDTH == UINT_WIDTH + /* Avoid triggering undefined behavior if x == ~0. */ + if (x == ~0U) + return (USHRT_WIDTH); +#endif + return (__builtin_ctz(~x)); } diff --git a/newlib/libc/stdbit/stdc_trailing_zeros.c b/newlib/libc/stdbit/stdc_trailing_zeros.c index 396333e17..8526461bc 100644 --- a/newlib/libc/stdbit/stdc_trailing_zeros.c +++ b/newlib/libc/stdbit/stdc_trailing_zeros.c @@ -20,14 +20,17 @@ stdc_trailing_zeros_uc(unsigned char x) return (__builtin_ctz(x | 1U << UCHAR_WIDTH)); } -/* Ensure we do not shift 1U out of range. */ -_Static_assert(USHRT_WIDTH < UINT_WIDTH, - "stdc_trailing_zeros_uc needs USHRT_WIDTH < UINT_WIDTH"); - unsigned int stdc_trailing_zeros_us(unsigned short x) { +#if USHRT_WIDTH == UINT_WIDTH + /* Ensure we do not shift 1U out of range. */ + if (x == 0U) + return (USHRT_WIDTH); + return (__builtin_ctz(x)); +#else return (__builtin_ctz(x | 1U << USHRT_WIDTH)); +#endif } unsigned int -- 2.53.0