Description
Consider
_BitInt(15) foo (_BitInt(15) x, _BitInt(15) y) { return x + y; }
_BitInt(115) bar (_BitInt(115) x, _BitInt(115) y) { return x + y; }
_BitInt(385) baz (_BitInt(385) x, _BitInt(385) y) { return x + y; }
int
main ()
{
volatile _BitInt(15) a = foo (16383wb, 1wb);
volatile _BitInt(115) b = bar (20769187434139310514121985316880383wb, 1wb);
volatile _BitInt(385) c = baz (39402006196394479212279040100143613805079739270465446667948293404245721771497210611414266254884915640806627990306815wb, 1wb);
}
with -fsanitize=undefined.
At least on godbolt with clang trunk I'm getting
/app/example.c:1:59: runtime error: signed integer overflow: 16383 + 1 cannot be represented in type '_BitInt(15)'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.c:1:59 in
/app/example.c:2:62: runtime error: signed integer overflow: 0x0003ffffffffffffffffffffffffffff + 1 cannot be represented in type '_BitInt(115)'
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /app/example.c:2:62 in
UndefinedBehaviorSanitizer: CHECK failed: ubsan_value.cpp:86 "((0 && "unexpected bit width")) != (0)" (0x0, 0x0) (tid=1)
The ubsan_value.{h,cpp} representation I guess is fine for very small _BitInt, the ones which fit into ValueHandle, the compiler
can/will sign/zero extend the values to ValueHandle bits. For slightly larger _BitInt (33 to 64 on 32-bit arches, 65 to 128 on 64-bit arches), I guess the compiler could sign/zero extend it in memory, but anything larger will simply not be handled by the library.
I wonder if we shouldn't add Tk_BitInt = 0x0002 and have TypeInfo in that case be the _BitInt precision rather than ceil log2 of it,
though that field is just 16-bit and I think LLVM currently supports even larger _BitInt.
I guess for now I'll add GCC -fsanitize=undefined support just for what can be encoded in the current scheme, but it would be really nice to have libubsan support even for larger _BitInts.