From: Mathieu Desnoyers Date: Tue, 14 May 2019 14:56:14 +0000 (-0400) Subject: Fix: bitfield: shift undefined/implementation defined behaviors X-Git-Tag: v2.10.10~11 X-Git-Url: http://git.liburcu.org/?a=commitdiff_plain;h=4f656c2f65698720ed93ffb7d369f73dbe27689b;hp=4f656c2f65698720ed93ffb7d369f73dbe27689b;p=lttng-modules.git Fix: bitfield: shift undefined/implementation defined behaviors bitfield.h uses the left shift operator with a left operand which may be negative. The C99 standard states that shifting a negative value is undefined. When building with -Wshift-negative-value, we get this gcc warning: In file included from /home/smarchi/src/babeltrace/include/babeltrace/ctfser-internal.h:44:0, from /home/smarchi/src/babeltrace/ctfser/ctfser.c:42: /home/smarchi/src/babeltrace/include/babeltrace/ctfser-internal.h: In function ‘bt_ctfser_write_unsigned_int’: /home/smarchi/src/babeltrace/include/babeltrace/bitfield-internal.h:116:24: error: left shift of negative value [-Werror=shift-negative-value] mask = ~((~(type) 0) << (__start % ts)); \ ^ /home/smarchi/src/babeltrace/include/babeltrace/bitfield-internal.h:222:2: note: in expansion of macro ‘_bt_bitfield_write_le’ _bt_bitfield_write_le(ptr, type, _start, _length, _v) ^~~~~~~~~~~~~~~~~~~~~ /home/smarchi/src/babeltrace/include/babeltrace/ctfser-internal.h:418:3: note: in expansion of macro ‘bt_bitfield_write_le’ bt_bitfield_write_le(mmap_align_addr(ctfser->base_mma) + ^~~~~~~~~~~~~~~~~~~~ This boils down to the fact that the expression ~((uint8_t)0) has type "signed int", which is used as an operand of the left shift. This is due to the integer promotion rules of C99 (6.3.3.1): If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions. We also need to cast the result explicitly into the left hand side type to deal with: warning: large integer implicitly truncated to unsigned type [-Woverflow] The C99 standard states that a right shift has implementation-defined behavior when shifting a signed negative value. Add a preprocessor check that the compiler provides the expected behavior, else provide an alternative implementation which guarantees the intended behavior. A preprocessor check is also added to ensure that the compiler representation for signed values is two's complement, which is expected by this header. Document that this header strictly respects the C99 standard, with the exception of its use of __typeof__. Signed-off-by: Mathieu Desnoyers ---