Bug 37130 - warning: array subscript is above array bounds.
Summary: warning: array subscript is above array bounds.
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: 4.5.0
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2008-08-15 16:52 UTC by gdsjaar
Modified: 2011-12-07 12:44 UTC (History)
5 users (show)

See Also:
Host: x86_64-unknown-linux-gnu
Target: x86_64-unknown-linux-gnu
Build: x86_64-unknown-linux-gnu
Known to work: 4.4.2, 4.5.0
Known to fail: 4.3.4
Last reconfirmed: 2011-12-07 00:00:00

Code that warns, 50 lines, no #include. #ifdef for variations w/o warning (698 bytes, text/plain)
2009-10-23 07:41 UTC, enrio

Note You need to log in before you can comment on or make changes to this bug.
Description gdsjaar 2008-08-15 16:52:09 UTC
#include <algorithm>

class Id {
  Id( const Id & );
  operator int() const;
  int id;

int get_int();

int main()
struct SideVertexBuffer {
  enum { max_vertices = 4 };
  Id node_id[ max_vertices ] ;
  int     processor ;


 SideVertexBuffer entry;
 int num_side_vert = get_int();
   std::sort(entry.node_id, entry.node_id+num_side_vert);

when compiled as:
g++ -finline-functions -O2 -Wall -c test.C

Gives the warning message:
/home/sntools/extras/compilers/gcc-4.3.1/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../../../include/c++/4.3.1/bits/stl_algo.h:In function ‘int main()’:
/home/sntools/extras/compilers/gcc-4.3.1/lib/gcc/x86_64-unknown-linux-gnu/4.3.1/../../../../include/c++/4.3.1/bits/stl_algo.h:1829: warning: array subscript is above array bounds

We are required compile with -Werror, so this warning results in a build error from our code.

As best I can tell, the error is due to _S_threshold being larger than the dimensioned size of the array being passed to std::sort. Since the compiler is inlining the functions, it "knows" that "__first+_S_threshold" is larger than the dimensioned size of the array I pass to sort and emits the warning.

If I change the "num_side_vert" variable to an explicit value (num_side_vert = 4), then I don't get the warning since the compiler then knows that the one branch of the if statement won't be taken in std::sort.
Comment 1 Paolo Carlini 2008-08-15 17:26:37 UTC
I don't see anything wrong with the code in __final_insertion_sort, thus this is indeed, in my opinion, a bogus warning emitted by the compiler. Seems related to PR 36902.
Comment 2 Andrew Pinski 2008-08-16 22:54:54 UTC
  __insertion_sort (&entry.node_id[0], &entry.node_id[16]);

The length is only 4.

One issue is that we don't reduce:
  D.8167 = &entry.node_id[0] + (unsigned int) num_side_vert * 4;
  if (&entry.node_id[0] != D.8167)

 if ((unsigned int)num_side_vert * 4 != 0)

So I think the other issue is that the code for std::sort assumes that it will be a pointer and an array with a small size.

The warning is only partly bogus but since this is only runtime undefinedness, this is valid code.  The function get_int better never return more than 4 really.
Comment 3 enrio 2009-10-23 07:41:08 UTC
Created attachment 18877 [details]
Code that warns, 50 lines, no #include. #ifdef for variations w/o warning
Comment 4 enrio 2009-10-23 10:06:38 UTC
In my example code there is a pointer to a struct that has an array as the first member. I appears that the compiler treats the pointer as a pointer to this first member, and flags a loop that writes outside the first member already at the first iteration. The code uses an integer offset from the pointer, and the pointer itself is not changed.

If the members are reordered so that an unsigned char member becomes the first one, the warning goes away. (But the example comes from a driver, and the struct maps hardware registers, so it cannot be reordered at a whim.)

If the loop is modified so that it begins within the array, the warning goes away, even the iterator has a constant end condition - outside the array.

If the loop is modified so that it begins exactly at the first byte after the array, there are four warnings rather than three. It makes me wonder if the compiler is generating code that does access the memory locations intended.

Since we got the strict aliasing optimizations, we probably should learn to rewrite such old code using a union, or properly accessing the structure members one by one.  I just tried the union approach: 

union mac_u {
  struct mac_regs regs;
  u8 bytes[sizeof(struct mac_regs)];

I changed the function argument to a pointer to this union rather than to a struct mac_regs, initialized the local pointer variable from the 'bytes' union member, and the warning went away.  This appears to be the way to properly tell the compiler how one plans to use the pointer.

Also if the pointer is incremented to point directly at the bytes of interest rather than being indexed, the warning goes away.
Comment 5 Richard Biener 2010-01-02 19:30:07 UTC
Works with 4.4 and 4.5.
Comment 6 Scott Harrison 2010-02-12 16:16:24 UTC
I get this on 4.4.3 for x86 32bit, is there a patch, or will I have to wait for 4.5 to be released ?
Comment 7 Francois-Xavier Coudert 2011-12-07 07:12:54 UTC
I have the same issue with 4.3.5 and 4.4.6 on x86_64-apple-darwin11 when compiling with "-m32 -O2 -W -Wall". It is fixed with 4.5.3 (at least). I'm reopening as 4.4 is still an active branch.
Comment 8 Richard Biener 2011-12-07 12:44:10 UTC
It's not a regression.