Bug 63477 - [6/7/8 Regression] Bogus warning with -O3 -Warray-bounds: array subscript is above array bounds
Summary: [6/7/8 Regression] Bogus warning with -O3 -Warray-bounds: array subscript is ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.8.3
: P3 normal
Target Milestone: 6.5
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Warray-bounds
  Show dependency treegraph
 
Reported: 2014-10-07 23:31 UTC by Jonathan Lennox
Modified: 2019-05-06 14:42 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.7.4, 8.0
Known to fail: 4.8.3, 4.9.3, 5.3.0, 6.2.0, 7.1.0
Last reconfirmed: 2017-10-17 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Lennox 2014-10-07 23:31:46 UTC
When compiled with -O3, the following code produces an "array subscript is above array bounds" warning, which is bogus as far as I can tell:

#define MAX_VAL 16

typedef struct 
{
	int itemList[MAX_VAL+1];
	unsigned int numItems;
} ItemList;

void FrobList(ItemList *l)
{
	unsigned int i;

	for (i=0; i < l->numItems-1; i++) {
		int minVal = l->itemList[i];
		unsigned int minIdx = i;
		unsigned int idx;
		for (idx=i+1; idx < l->numItems; ++idx) {
			if (l->itemList[idx] < minVal) {
				minVal = l->itemList[idx];
				minIdx = idx;
			}
		}
		l->itemList[i] = l->itemList[minIdx];
	}
}


$ gcc -O3 -Warray-bounds -c LmiH264RefPictures-Reduced.c
LmiH264RefPictures-Reduced.c: In function ‘FrobList’:
LmiH264RefPictures-Reduced.c:18:19: warning: array subscript is above array bounds [-Warray-bounds]
    if (l->itemList[idx] < minVal) {
                   ^

The warning occurs on compilers targeted to x86_64 and armhf, but not i686.  It does not occur with -O2 or lower.  Tested on both Linux and Cygwin.

This is a regression from GCC 4.6.3, at least. Have not tested 4.7.x.

Clearly it would be an out-of-bounds access if l->numItems were >= MAX_VAL+1, but (in the actual application this testcase is reduced from), it's an invariant that it won't be, and the compiler shouldn't be making range assumptions to the contrary.

Verbose compiler output:

$ gcc -v -O3 -Warray-bounds -c LmiH264RefPictures-Reduced.c
Using built-in specs.
COLLECT_GCC=gcc
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) 
COLLECT_GCC_OPTIONS='-v' '-O3' '-Warray-bounds' '-c' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1 -quiet -v -imultiarch x86_64-linux-gnu LmiH264RefPictures-Reduced.c -quiet -dumpbase LmiH264RefPictures-Reduced.c -mtune=generic -march=x86-64 -auxbase LmiH264RefPictures-Reduced -O3 -Warray-bounds -version -fstack-protector -Wformat -Wformat-security -o /tmp/ccXMNHkF.s
GNU C (Ubuntu 4.8.2-19ubuntu1) version 4.8.2 (x86_64-linux-gnu)
	compiled by GNU C version 4.8.2, GMP version 5.1.3, MPFR version 3.1.2-p3, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
GNU C (Ubuntu 4.8.2-19ubuntu1) version 4.8.2 (x86_64-linux-gnu)
	compiled by GNU C version 4.8.2, GMP version 5.1.3, MPFR version 3.1.2-p3, MPC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: dc75e0628c9356affcec059d0c81cc01
LmiH264RefPictures-Reduced.c: In function ‘FrobList’:
LmiH264RefPictures-Reduced.c:18:19: warning: array subscript is above array bounds [-Warray-bounds]
    if (l->itemList[idx] < minVal) {
                   ^
COLLECT_GCC_OPTIONS='-v' '-O3' '-Warray-bounds' '-c' '-mtune=generic' '-march=x86-64'
 as -v --64 -o LmiH264RefPictures-Reduced.o /tmp/ccXMNHkF.s
GNU assembler version 2.24 (x86_64-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.24
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-O3' '-Warray-bounds' '-c' '-mtune=generic' '-march=x86-64'
Comment 1 Martin Sebor 2017-10-17 15:18:39 UTC
Confirmed.  The first revision to trigger the error is r192990 (gcc 4.8.0) so marking this a regression.
Comment 2 Martin Sebor 2017-11-16 16:49:08 UTC
Author: msebor
Date: Thu Nov 16 16:48:36 2017
New Revision: 254833

URL: https://gcc.gnu.org/viewcvs?rev=254833&root=gcc&view=rev
Log:
PR middle-end/63477 - Bogus warning with -O3 -Warray-bounds: array subscript
is above array bounds

gcc/testsuite/ChangeLog:

	PR middle-end/63477
	* gcc.dg/pr63477.c: New test.


Added:
    trunk/gcc/testsuite/gcc.dg/pr63477.c
Modified:
    trunk/gcc/testsuite/ChangeLog
Comment 3 Martin Sebor 2017-11-16 16:50:01 UTC
Strangely, I cannot reproduce this warning anymore with GCC 8.  Bisection points to r220157 (gcc 5.0.0) as the revision that fixed it.  I've added the test case to the test suite in r254833 and with that I'm resolving this bug as fixed.  Please reopen it if the problem reappears.
Comment 4 Alexandre Ganea 2019-05-06 13:29:50 UTC
Hi,

We get what seems like a spurious warning at the following location in LLVM: https://github.com/llvm/llvm-project/blob/master/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp#L1718

The warning is:
    //    warning: array subscript is above array bounds [-Warray-bounds]
    //    if (NewBldVec[i] == NewBldVec[j]) {
    //        ~~~~~~~~~~~^

This only occurs when compiling with GCC 7.1+ and 9.1/trunk (not with 8), with -O3 -Warray-bounds

This has been creduce'd to:

class a {
  int b;
  unsigned c;

public:
  bool operator==(a) { return b && c; }
};
class d {
public:
  void e();
};
class f {
  a g(d &) const;
};
a f::g(d &h) const {
  a j[1];
  for (unsigned i;; i++)
    for (; i;)
      if (j[i] == j[0])
        h.e();
}

Could you please confirm the issue?
Thank you!
Comment 5 Martin Sebor 2019-05-06 14:42:20 UTC
(In reply to Alexandre Ganea from comment #4)

The test case has been reduced a little too far -- it reads an uninitialized variable:

  for (unsigned i;; i++)
    for (; i;)
      if (j[i] == j[0])
        h.e();

But the false positive can also be reproduced by initializing the variable to zero.  Can you please open a new bug with the corrected test case?