1

Consider the following example:

int a[4];

int main() {
  a[4] = 12; // <--
  return 0;
}

This is clearly an out of bounds error, is it not? I was wondering when gcc would warn about this, and found that it will only do so if optimisation is -O2 or higher (this is affected by the -ftree-vrp option that is only set automatically for -O2 or higher). I don't really see why this makes sense and whether it is correct that gcc does not warn otherwise.

The documentation has this to say about the matter:

This allows the optimizers to remove unnecessary range checks like array bound checks and null pointer checks.

Still, I don't see why that check should be unnecessary?

bitmask
  • 32,434
  • 14
  • 99
  • 159

1 Answers1

1

Your example is a case of constant propagation, not value range propagation, and it certainly triggers a warning on my version of gcc (4.5.1) whether or not -ftree-vrp is enabled.

In general, Java and Fortran are the only languages supported by gcc which (Java by default, and Fortan if you explicitly ask for it with -fbounds-check) will generate code for checking array bounds.

However, although C/C++ does not support any such thing, the compiler will still warn you at compile time if it believes that something is amiss. For constants, this is pretty obvious, for variable ranges, it is somewhat harder.

The clause "allows the compiler to remove unnecessary range checks" relates to cases where for example you use an unsigned 8 bit wide variable to index into an array that has >256 entries or an unsigned 16 bit value to index into an array of >65536 elements. Or, if you iterate over an array in a loop, and the (variable) loop counter is bounded by values that can be proven as compile-time constants which are legal array indices, so the counter can never possibly go beyond the array bounds.
In such cases, the compiler will neither warn you nor generate any code for target languages where this is supported.

Damon
  • 67,688
  • 20
  • 135
  • 185
  • So, if you compile my example code with `gcc -O0 -Wall main.c` it (`gcc 4.4.3`) throws you a warning? Because it sure does not on my machine. It does however, if I say `-O2` instead of `-O0`. – bitmask Jul 13 '11 at 18:39
  • I compiled it both with `-O2` and `-O3`, with `-Wall` and without, and with `-fbounds-check` and without. Got a warning every single time (gcc 4.5.1). – Damon Jul 13 '11 at 18:42
  • Precisely, as I said, you always get a warning with `-O2` **and higher** (i.e. `-O3` and `-Os`). However, **you don't** with `-O1` and `-O0`. The reason is that `-ftree-vrp` is implied by `-O2`, `-O3` and `-Os`. The question is why? -- So it would be great if you could try it out again, with e.g `-O0`. – bitmask Jul 14 '11 at 09:28
  • You are right, it gives that warning with `-O2` and higher, or _any_ optimization (including `-O1` or `-Os`) with the `-ftree-vrp` option manually (I had this in my IDE's global settings without noticing, so even `-O1` would warn). That is independent of explicit `-Warray-bounds`, too. Though the documentation of the latter says (without further explanation) that it can only work if `-ftree-vrp` is active. I assume the reason would be that the warning heuristics use the optimizer tree, which isn't present if no optimizations are done at all. – Damon Jul 14 '11 at 10:05