On 9 May 2018 at 02:44, John Carter <john.carter@xxxxxxxxxxxxx> wrote: > I tried playing with __builtin_constant_p and __builtin_choose_exp but they > have a very different notion of what a compile time constant is. ie. It's > something a literal or something declared const, _not_ something that is > known at compile time. Are you sure? __builtin_constant_p should be precisely something that is known at compile time, whether declared const or not. > > Even weirder.... The following compiles without warnings, but..... > > #include <stdlib.h>#include <stdio.h>#include <assert.h> > static char __rangeCheckVariable; > #define asshurt(exp) \ > do { \ > char __rangeCheck[2]="a"; \ > __rangeCheckVariable = \ > __rangeCheck[(exp) ? 0 : 10]; \ > } while(0) > void bunc( int i){ > > asshurt( i< 4); > assert( i<4); > printf( "%d\n",i);} > void func( int i){ > bunc( i);} > int main( int argc __attribute__((unused)), char * argv[] > __attribute__((unused))){ You know you can just declare main with no arguments? int main(){ > int i = 10; > > func( i); > > return 0;} > > Removed the line assert( i< 4); and you get > > gcc -g3 -ggdb3 -O3 -W -Wall -Wextra -c d.c ;objdump -S d.o > d.c: In function ‘main’: > d.c:11:22: warning: array subscript is above array bounds [-Warray-bounds] > __rangeCheck[(exp) ? 0 : 10]; \ > ^ > d.c:17:4: note: in expansion of macro ‘asshurt’ > asshurt( i< 4); > ^ Now I think what Mason said applies: the extra code for assert(i<4) prevents GCC from inlining bunc, and so the optimizer doesn't see that the argument to bunc will make (i<4) false. If you make bunc static, or add __attribute__((always_inline)) then you get a warning even with the assert line present.