The following test case generates a wrong "out-of-bounds" warning. This problem only happens under -Os gcc test.i -c -Os -Werror -Wall In function ‘rcu_init_lal’: /home/llozano/trash/min_rcutree.i:17:13: error: array subscript is above array bounds [-Werror=array-bounds] rsp->level[i] = rsp->level[i - 1] + rsp->levelcnt[i - 1]; rcu_num_levels is never larger than 1. So the code inside the loop is never executed. test.i: --- extern int rcu_num_lvls; int rcu_num_lvls = 1; struct rcu_node { }; struct rcu_state { struct rcu_node *level[1]; int levelcnt[4 + 1]; }; void rcu_init_lal(struct rcu_state *rsp) { int i; for (i = 1; i < rcu_num_lvls; i++) rsp->level[i] = rsp->level[i - 1] + rsp->levelcnt[i - 1]; }
Raising priority of this issue. This problem was found while build the ChromOS linux kernel. Most probably this will be found by other platfroms using the linux kernel.
Perhaps a dup of PR41847. Fails even with -O2, -O3, -Ofast, no only -Os. -fno-tree-vrp makes it go away...
(In reply to Marek Polacek from comment #2) > Perhaps a dup of PR41847. Fails even with -O2, -O3, -Ofast, no only -Os. > -fno-tree-vrp makes it go away... I dont think it is a duplicate of this issue. This problem does not happen with GCC 4.7.2
Luis, why do you state that "rcu_num_levels is never larger than 1", this cannot be proved as this variable is not const and can change its value (e.g. in another thread).
Confirmed with 5.1 and 6.0. A simpler test case: $ cat a.c && /home/msebor/build/gcc-trunk-svn/gcc/xgcc -shared-libgcc -B/home/msebor/build/gcc-trunk-svn/gcc -Os -S -Wall -o/dev/null a.c int a [1]; void foo (int n) { for (int i = 1; i < n; i++) a [i] = a [i - 1]; } a.c: In function ‘foo’: a.c:6:10: warning: array subscript is above array bounds [-Warray-bounds] a [i] = a [i - 1]; ~~^~~
Further reduced: int a [1]; void foo (int n) { if (n <= 1) return; int i = 1; a [i] = a [i - 1]; } This is one of these false positives warning where we should maybe not warn but instead just change the code to be a trap. Note in the original testcase, GCC is able to remove the loop and just change it to one statement. That is part of the reason for the warning even. clang does not warn about the above because they only warn for the literal a[1] case.