Re: array subscript is below array bounds : false positive?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ian Lance Taylor wrote:
"Peter A. Felvegi" <petschy@xxxxxxxxxxxxxxxxxx> 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-help@xxxxxxxxxxx, not
gcc@xxxxxxxxxxxx  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(); }

Now I got 'noreturn function does return' warning/error in assert_failure(). actually, assert_failure() should return when running the program in a debugger and continuing after the break.

Is there some other way to prevent gcc messing with the 'if' construct of the assertion (other than moving the whole 'if' block into a non-inline function) ?

Cheers, Peter

[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux