Description
Consider this test case:
unsigned foo(unsigned _BitInt(44) x) {
_BitInt(9) c = -2;
return x >> c;
}
int main() {
return foo(5) ? 1 : 0;
}
As shown by https://godbolt.org/z/M614qnhco , the result when compiling and running this program (with ubsan) is weird:
/app/example.c:3:14: runtime error: shift exponent 510 is too large for 64-bit type 'unsigned _BitInt(44)'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.c:3:14
The expected error here would be "shift exponent -2 is negative". But it is not only the detection of isNegative for the exponent that is wrong, it also reports an incorrect bitwidth (64-bit type) for the shifted value.
Afaict the problem is that the TypeDescriptor encoding (compiler-rt/lib/ubsan/ubsan_value.h) encodes the _BitInt types like ordinary integer types:
/// An integer type. Lowest bit is 1 for a signed value, 0 for an unsigned
/// value. Remaining bits are log_2(bit width). The value representation is
/// the integer itself if it fits into a ValueHandle, and a pointer to the
/// integer otherwise.
TK_Integer = 0x0000,
But using log_2(bit width) does not work that well when having non-power-of-two bit widths.
One idea could be to introduce a new TK_BitInt kind, that encodes the bit wifth in some other way? Although I have no idea how big impact that has on the rest of the code.
This problem was found when running tests with the fix from #88004