<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Invalid optimization for "==" on pointers"
   href="http://llvm.org/bugs/show_bug.cgi?id=21327">21327</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Invalid optimization for "==" on pointers
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>-New Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>Keith.S.Thompson@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>"clang --version" says
Ubuntu clang version 3.5-1ubuntu1 (trunk) (based on LLVM 3.5)
Target: x86_64-pc-linux-gnu
Thread model: posix

"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
<a href="https://gist.github.com/Keith-S-Thompson/60dc069f4823fb1c3209">https://gist.github.com/Keith-S-Thompson/60dc069f4823fb1c3209</a>
but of course I'll include the information here.

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

<span class="quote">> 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.</span >

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 clang, it prints "inconsistent behavior: ...".

It appears that clang 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 similar behavior with gcc 4.8.2 and 4.9.1, but with the order of
x and y reversed.  That's not directly relevant to this bug report,
but it's mildly interesting.  The gcc bug report is at
<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63611">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63611</a>

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

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

The output on my system is:

x  = 0x7fff7905f820
x0 = 0x7fff7905f820
x1 = 0x7fff7905f8a0
y  = 0x7fff7905f7a0
y0 = 0x7fff7905f7a0
y1 = 0x7fff7905f820
x immediately follows y
inconsistent behavior:
    0x7fff7905f820 !=
    0x7fff7905f820

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");
    }
}</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>