Bug 60957 - [4.9/4.10 Regression] Bogus error: array subscript is above array bounds [-Werror=array-bounds]
Summary: [4.9/4.10 Regression] Bogus error: array subscript is above array bounds [-We...
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: 4.9.1
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2014-04-24 20:21 UTC by H.J. Lu
Modified: 2014-04-28 13:41 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-04-24 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2014-04-24 20:21:32 UTC
[hjl@gnu-6 gcc]$ cat bar.cc
class XXX
{
private:
    bool _enabled;
public:
    bool on() const {return _enabled;}
};
extern XXX xxx;
extern bool foobar(const unsigned int);
extern void foo (const char *);
extern const unsigned int bar (void * p);
extern void bar2(void * ptr)
{
  static const unsigned int size_map[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8};
  const unsigned int old_width = bar (ptr);
  if(!(old_width <= 8))
    if(xxx.on())
      foo ("");
  unsigned int size = size_map[old_width];
  if(!(size != 0))
    if(xxx.on())
      foo ("");
  if(!(foobar(size)))
    foo ("");
}
[hjl@gnu-6 gcc]$  ./xgcc -B./ -S -O2 -Wall bar.cc -Werror
bar.cc: In function \u2018void bar2(void*)\u2019:
bar.cc:19:41: error: array subscript is above array bounds [-Werror=array-bounds]
   unsigned int size = size_map[old_width];
                                         ^
cc1plus: all warnings being treated as errors
[hjl@gnu-6 gcc]$
Comment 1 H.J. Lu 2014-04-24 20:27:12 UTC
It is caused by r205074.
Comment 2 Andrew Pinski 2014-04-24 20:44:44 UTC
This is not fully a bogus warning.  The warning is true if xxx._enabled is false and bar returns something which is > 8.

Here is a shorter testcase:
extern bool foobar(const unsigned int);
extern void foo (void);
extern void bar2(bool *enabled, unsigned int old_width)
{
  static const unsigned int size_map[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8};
  if(old_width > 8)
    if(*enabled)
      foo ();
  unsigned int size = size_map[old_width];
  if(size == 0)
    if(*enabled)
      foo ();
  if(foobar(size))
    foo ();
}

We are transforming the above into:
extern bool foobar(const unsigned int);
extern void foo (void);
extern void bar2(bool *enabled, unsigned int old_width)
{
  unsigned int size;
  static const unsigned int size_map[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8};
  if(old_width > 8)
  {
    if(*enabled)
      foo ();
    else
      {
        size = size_map[old_width];
        goto t;
      }
  }
  size = size_map[old_width];
  if(size == 0)
    if(*enabled)
      foo ();
t:
  if(foobar(size))
    foo ();
}


Which is correct and we are warning about the access under the else statement.
Comment 3 Andrew Pinski 2014-04-24 20:44:57 UTC
What source does this come from?
Comment 4 H.J. Lu 2014-04-24 20:49:01 UTC
(In reply to Andrew Pinski from comment #3)
> What source does this come from?

This comes from a real application.
Comment 5 Richard Biener 2014-04-25 08:17:10 UTC
Yeah, nothing guards the size_map access if !(old_width <= 8).  I'd say this
report is invalid.

Triggered by more elaborate jump-threading, btw.
Comment 6 Jeffrey A. Law 2014-04-28 13:41:11 UTC
Agreed.  Nothing guards the reference to size_map[old_width].