From d242706f3b739bcb00de1d970a01a319db6ad77d Mon Sep 17 00:00:00 2001 From: grischka Date: Tue, 9 May 2017 18:10:02 +0200 Subject: bitfields: one more hack and a "-Wgcc-compat" switch bit_pos + bit_size > type_size * 8 must NEVER happen because the code generator can read/write only the basic integral types. Warn if tcc has to break GCC compatibility for that reason and if -Wgcc-compat is given. Example: struct __attribute__((packed)) _s { unsigned int x : 12; unsigned char y : 7; unsigned int z : 28; }; Expected (GCC) layout (sizeof struct = 6) .xxxxxxxx.xxxxyyyy.yyyzzzzz.zzzzzzzz.zzzzzzzz.zzzzzzz0. But we cannot read/write 'char y'from 2 bytes in memory. So we have to adjust: .xxxxxxxx.xxxx0000.yyyyyyyz.zzzzzzzz.zzzzzzzz.zzzzzzzz.zzz00000 Now 'int z' cannot be accessed from 5 bytes. So we arrive at this (sizeof struct = 7): .xxxxxxxx.xxxx0000.yyyyyyy0.zzzzzzzz.zzzzzzzz.zzzzzzzz.zzzz0000 Otherwise the bitfield load/store generator needs to be changed to allow byte-wise accesses. Also we may touch memory past the struct in some cases currently. The patch adds a warning for that too. 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: 81 ec 04 00 00 00 sub $0x4,%esp 9: 90 nop struct __attribute__((packed)) { unsigned x : 5; } b = {0} ; a: 8b 45 ff mov -0x1(%ebp),%eax d: 83 e0 e0 and $0xffffffe0,%eax 10: 89 45 ff mov %eax,-0x1(%ebp) This touches -0x1 ... +0x3(%ebp), hence 3 bytes beyond stack space. Since the data is not changed, nothing else happens here. --- libtcc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'libtcc.c') diff --git a/libtcc.c b/libtcc.c index 331baf3..89e75fa 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1578,6 +1578,7 @@ static const FlagDef options_W[] = { { offsetof(TCCState, warn_unsupported), 0, "unsupported" }, { offsetof(TCCState, warn_write_strings), 0, "write-strings" }, { offsetof(TCCState, warn_error), 0, "error" }, + { offsetof(TCCState, warn_gcc_compat), 0, "gcc-compat" }, { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, "implicit-function-declaration" }, { 0, 0, NULL } -- cgit v1.3.1