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

--- Comment #35 from Alexander Cherepanov <ch3root at openwall dot com> ---
What remains in this pr is the original problem.

1. The best way to demonstrate that there is indeed a bug here is probably to
compare representation of pointers directly:

----------------------------------------------------------------------
#include <string.h>
#include <stdio.h>

__attribute__((noipa)) // imagine it in a separate TU
static void *opaque(void *p) { return p; }

int main()
{
    int x[5];
    int y[2];

    void *p = &x;
    void *q = &y + 1;

    printf("val1: %d\n", p == q);
    printf("repr: %d\n", memcmp(&p, &q, sizeof(void *)) == 0);

    opaque(&p); // move the next comparison to runtime
    printf("val2: %d\n", p == q);

    opaque(q);
}
----------------------------------------------------------------------
$ gcc -std=c11 -pedantic -Wall -Wextra -O3 test.c && ./a.out
val1: 0
repr: 1
val2: 1
----------------------------------------------------------------------
gcc x86-64 version: gcc (GCC) 10.0.0 20191229 (experimental)
----------------------------------------------------------------------

C11, 6.2.6.1p4: "Two values (other than NaNs) with the same object
representation compare equal". Our pointers are not NaNs and have the same
representation so should compare equal.

DR 260 allows one to argue that representation of these pointers could change
right between the checks but IMHO this part of DR 260 is just wrong as it makes
copying objects byte-by-byte impossible. See
https://bugs.llvm.org/show_bug.cgi?id=44188 for a nice illustration.

While at it, the testcase also demonstrates that the comparison `p == q` is
unstable.

I'm not taking sides here, just stating that the standard and the compiler
disagree.

2. C++ at some point made results of the discussed comparison unspecified --
https://eel.is/c++draft/expr.eq#3.1 . According to the DR linked to in comment
27, it's done to make the definition usable at compile time. Perhaps
harmonization of the standards should move in this direction, not vice versa.

3. OTOH clang was fixed to be complying with C11.

4. What seems missing in the discussion is a clear description of benefits of
the current gcc's approach. Does it make some optimizations easier to
implement? Does it enable other optimizations?
Obviously, it could be used to fold `a + i == b` to `0` if `a` and `b` are two
different known arrays and `i` is unknown (or known to be exactly the length of
`a`). But this is probably not helpful for aliasing analysis as AA doesn't deal
with past-the-end pointers. And optimization of loops like in comment 19 is
probably not superhelpful too:-)

Reply via email to