Open
Description
Test code
#include <stdint.h>
#include <stdio.h>
static inline unsigned int popCount8(uint8_t x) {
// Formula borrowed from https://github.com/llvm/llvm-project/issues/79823
uint32_t n = (uint32_t)(x * 0x08040201U);
n = ((((n >> 3) & 0x11111111U) * 0x11111111U) & 0xF0000000U) >> 28;
return n;
}
int main(void) {
volatile uint8_t x;
x = 0xFF;
// Expected output: 8
printf("%u\n", popCount8(x));
return 0;
}
Compile with: clang -fsanitize=integer -o test test.c
Then run with ./test
Actual behavior
test1.c:6:30: runtime error: unsigned integer overflow: 255 * 134480385 cannot be represented in type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test1.c:6:30 in
test1.c:7:35: runtime error: unsigned integer overflow: 286331153 * 286331153 cannot be represented in type 'unsigned int'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior test1.c:7:44 in
Expected behavior
No errors and no warnings.
The compiler and UndefinedBehaviorSanitizer should not warn about both overflow cases as I have made downcasts and bitwise-AND masks to tell that the "overflows" are intentional.
(uint32_t)(x * 0x08040201U)
((x * 0x11111111U) & 0xF0000000U)
While I can workaround the bug by adding a upcast like this...
(uint32_t)((uint64_t)x * 0x08040201U)
(((uint64_t)x * 0x11111111U) & 0xF0000000U)
... I would rather like conciseness and not needing such casts.