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 tree-optimization/86259] [8/9 Regression] min(4, strlen(s)) optimized to strlen(s) with -flto


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

--- Comment #21 from Davin McCall <davmac at davmac dot org> ---
Looking at this further, the proposal actually states, for the address-of
operator:

> When the operand designates an object, the result has the single provenance of the outermost object containing that object.

That's "outermost" object; it implies that taking the address of an
inner/contained object, and manipulating it to point at other parts of the
containing object, should actually be fine (adding an integer offset with empty
provenance should not affect the provenance of the pointer, according to the
proposal). Martin Sebor: doesn't that contradict what you said in comment #8 ?
In any case it seems it should allow the case I was concerned about, i.e
calculating the containing object address from a contained object address.

While we can agree that it is anyway not allowed to advance a pointer past the
end of an array, including an "array" consisting of a single object not
actually declared as an array, surely casting the pointer to an integer type
should get around that problem - but doesn't, in the program below, for which
GCC 8.1 bizarrely generates code that prints "NO" (indicating that it has
determined that len != 7) and then returns 7 (indicating that len == 7).
Clearly this could only be "correct" if there is undefined behaviour - though
it is somewhat bad handling even then - however I cannot see the U.B. in this
program and no warnings are generated (which is at least a QOI issue). Note
that by the provenance proposal the 'sp_ip' variable should have the provenance
of the containing object, 'u', and so when cast to char * should be perfectly
capable of navigating the entire union object:

---8>---
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>

struct S {
    char a[4];
    char b[4];
    char c[4];
};

union U {
    struct S s;
    char xx[12];
};

int main()
{
    union U u;
    u.s = (struct S){0, 0, 0};
    char *bp = u.s.b;
    uintptr_t sp_ip = (uintptr_t)bp - offsetof(struct S,b);
    strcpy(u.xx, "abcdefghijk");
    size_t len = strlen((char *)(union U *)sp_ip + 4);
    puts(len == 7 ? "YES" : "NO");
    return len;
}
---<8---

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