"Peter A. Felvegi" <pets...@praire-chicken.com> writes: > I've run into this strange warning when compiling w/ optimization: > gcc-4.3 -O2 -Werror -Wall -c -o t.o t.c > cc1: warnings being treated as errors > t.c: In function ‘foo’: > t.c:25: error: array subscript is below array bounds
This question is appropriate for gcc-h...@gcc.gnu.org, not g...@gcc.gnu.org. Please take any followups to gcc-help. Thanks. > t.c is : > ---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---- > #define ASSERT(x) if (x) { } else { __asm__("int $0x03"); } > #define SIZE 5 > > char hnd[SIZE]; > char flg[SIZE]; > > char crd(); > int idx(char); > void set(int i, char v); > > #if 1 > void set(int i, char v) > { > ASSERT(i >=0 && i < SIZE); > flg[i] = v; > } > #endif > > > void foo() > { > char c = crd(); > int i = idx(0); > ASSERT(i != -1); > hnd[i] = c; // array subscript is below array bounds > set(i, 1); > } > ---->8---->8---->8---->8---->8---->8---->8---->8---->8---->8---- > > Suppose that idx(c) returns the position of c in an array, an the > return value of -1 means that c is not in the array. The assertion > checks that. > > The funny thing is, if I change the source a bit, the warning goes away: > 1) set '#if 1' to '#if 0' so that only the prototype of set() is visible > 2) comment out the ASSERT() int set() > 3) comment out ASSERT() just before the marked line > 4) comment out set(i, 1) just after the marked line > > The warning is not present under -O2. gcc is getting fooled because of your ASSERT macro. The optimizer is pulling the reference to hnd[i] into the ASSERT branches, because it can then optimize the reference knowing that i == -1. That is: ASSERT (i != -1) hnd[i] = c; => if (i != -1) { } else { __asm__ (""); } hnd[i] = c; => if (i != -1) { hnd[i] = c; } else { __asm__ (""); hnd[-1] = c; } You can avoid this kind of thing by telling gcc that your assert condition does not return. void assert_failure () __attribute__ ((noreturn, always_inline)); void assert_failure() { __asm__ ("int $0x03"); } #define ASSERT(x) if (x) { } else { assert_failure(); } Ian