Bug 21474 - missed optimizations when comparing address to NULL
Summary: missed optimizations when comparing address to NULL
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.1.0
: P2 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2005-05-09 17:22 UTC by Tom Truscott
Modified: 2007-11-15 17:03 UTC (History)
2 users (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed: 2007-11-15 17:03:30


Note You need to log in before you can comment on or make changes to this bug.
Description Tom Truscott 2005-05-09 17:22:19 UTC
The program below gives some expressions which gcc could, but does not, evaluate
to true.  E.g. gcc considers &p->a true, even when a is the first element
of the struct (is this a bug?), but does not consider &p->b[3] to be true.

struct foo {int a, b[10];};
int subr(int i, struct foo *p)
    int x[10];
#if 0
    // gcc folds this
    if (&p->a) return 1;
    // but not these
    if (&p->b[3]) return 1;
    if (&x[3] != 0) return 1;
    if (&x[i] != 0) return 1;  // not sure if this one is safe to fold
    return 0;
Comment 1 Andrew Pinski 2005-05-09 17:26:02 UTC
Actually I don't think it is safe to fold any of these.
Comment 2 Tom Truscott 2005-05-12 15:08:51 UTC
I think it is reasonable to assume the address of an auto variable is non-NULL,
and so the address of anything in the local "int x[10];"  is non-NULL.
So gcc can (and does) fold "if (x) ..." and "if (&x[0]) ..."

gcc does not fold "if (&x[3]) ..." due to the the quirk that
that it is represented as x+3 and fold does not recognize that to be non-NULL.

Now consider "if (&x[i])".  The only legal values for i are 0..10,
which precludes any value of `i' that might cause &x[i] to be NULL.
I suppose if x were a pointer, instead of an array, then we wouldn't know
the legal range of values for `i'. But whatever the legal range happens to be
would still (I think) preclude values which could cause &x[i] to be NULL.

The argument for 'if (&p->b[3])' is more convoluted.
Suppose p is non-NULL, then surely this address should be considered non-NULL
for basically the same reason that &x[3] above is considered to be non-NULL.
Suppose instead that p is NULL, then surely a non-zero offset added to p
yields a non-NULL value.

That leaves "if (&p->a)" which gcc folds even though a's offset is zero.
I think this is arguably a bug.  But if no one reports it as a bug ...
well I think this one could be argued either way.
Comment 3 Manuel López-Ibáñez 2007-11-15 17:03:30 UTC
I think it is odd that if you call subr(i,0), it doesn't crash, that is &(p->a) does not actually dereferences p. Nonetheless, I agree that the behaviour seems inconsistent. A nice little project for someone. As they say, patches welcome!