This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c/63611] New: Invalid optimization for "==" on pointers


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63611

            Bug ID: 63611
           Summary: Invalid optimization for "==" on pointers
           Product: gcc
           Version: 4.8.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Keith.S.Thompson at gmail dot com

"gcc --version" says
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2

"uname -a" says
Linux bomb20 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014
x86_64 x86_64 x86_64 GNU/Linux
(The system is Linux Mint 17, based on Ubuntu 14.04.1 LTS.)

I've created a Gist at
https://gist.github.com/Keith-S-Thompson/60dc069f4823fb1c3209
but of course I'll include the information here.

The C standard's definition of "==" for pointers (N1570 6.5.9 paragraph 6)
says:

Two pointers compare equal if and only if both are null pointers, both
are pointers to the same object (including a pointer to an object and a
subobject at its beginning) or function, both are pointers to one past
the last element of the same array object, or one is a pointer to one
past the end of one array object and the other is a pointer to the start
of a different array object that happens to immediately follow the first
array object in the address space.

which implies that the test program below should print (among other output)
one of the following:
- "y immediately follows x" followed by "ok";
- "x immediately follows y" followed by "ok"; or
- "x and y are not adjacent"

Instead, when compiled with gcc, it prints "inconsistent behavior: ...".

It appears that gcc is assuming that a pointer just past the end of one
declared object cannot be equal to a pointer to the beginning of another
object, when the two objects are not subobjects of the same containing
object. Examining an assembly listing indicates that the code to print
"ok" is not even generated, implying that this is an optimization bug
(that occurs even at "-O0".

I don't expect that this is a common use case, but the compiled program
does behave in a manner inconsistent with the standard's requirements.

I see the same behavior with a copy of gcc 4.9.1 built from source on the
same system.  (I also see it with clang 3.5-1ubuntu1, but with the order
of x and y reversed; that's not directly relevant to this bug report,
but it's mildly interesting.)

The command line used to compile and execute the program is:

$ gcc -std=c11 -pedantic -Wall -Wextra pointer_equality_bug.c -o
pointer_equality_bug && ./pointer_equality_bug

The output on my system is:

x  = 0x7fff2a94a1d0
x0 = 0x7fff2a94a1d0
x1 = 0x7fff2a94a250
y  = 0x7fff2a94a250
y0 = 0x7fff2a94a250
y1 = 0x7fff2a94a2d0
y immediately follows x
inconsistent behavior:
    0x7fff2a94a250 !=
    0x7fff2a94a250

And the program itself (73 lines, making up the remainder of this description)
is:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    typedef struct {
        int arr[32];
    } element;
    element x[1];
    element y[1];
    element *const x0 = x;
    element *const x1 = x0 + 1;
    element *const y0 = y;
    element *const y1 = y0 + 1;

    /*
     * x and y will typically be adjacent in memory.
     * x0 points to x; x1 points just past it.
     * y0 points to y; y1 points just past it.
     * We should have x1 == y0 if and only if y immediately follows x.
     * We should have y1 == x0 if and only if x immediately follows y.
     */

    printf("x  = %p\nx0 = %p\nx1 = %p\ny  = %p\ny0 = %p\ny1 = %p\n",
           (void*)x, (void*)x0, (void*)x1,
           (void*)y, (void*)y0, (void*)y1);

    if (x1 == y0) {
        puts("y immediately follows x");
        if (x + 1 == y) {
            puts("ok");
        }
        else if (x + 1 != y) {
            printf("inconsistent behavior:\n"
                   "    %p !=\n"
                   "    %p\n",
                   (void*)(x + 1),
                   (void*)y);
            exit(EXIT_FAILURE);
        }
        else {
            printf("inconsistent behavior:\n"
                   "    %p !=\n"
                   "    %p\n",
                   (void*)(x + 1),
                   (void*)y);
            exit(EXIT_FAILURE);
        }
    }
    else if (y1 == x0) {
        puts("x immediately follows y");
        if (y + 1 == x) {
            puts("ok");
        }
        else if (y + 1 != x) {
            printf("inconsistent behavior:\n"
                   "    %p !=\n"
                   "    %p\n",
                   (void*)(y + 1),
                   (void*)x);
            exit(EXIT_FAILURE);
        }
        else {
            printf("inconsistent behavior:\n"
                   "    %p !=\n"
                   "    %p\n",
                   (void*)(y + 1),
                   (void*)x);
            exit(EXIT_FAILURE);
        }
    }
    else {
        puts("x and y are not adjacent");
    }
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]