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

Martin Uecker <uecker at eecs dot berkeley.edu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |uecker at eecs dot berkeley.edu

--- Comment #1 from Martin Uecker <uecker at eecs dot berkeley.edu> ---
Here are some additional comments, which may help to analyze this (or not). 

The optimization also works without struct Y, the initialization, and the
memcpy in which case the example is not undefined by itself (see case 1 below).
From a C language point of view (I can't comment about GIMPLE), the
optimization seems legal as from the access p->c one can infer the effective
type. In case 3, one cannot infer the effective type and gcc also does not
optimize this case. Case 2 is interesting. I think using p->c to construct a
pointer to c implies that the storage at p must have correct effective type,
but I am not entirely sure. For strlen, case 1 and case 2 are optimized, but
not case 3. (tested with gcc from recent git). 

#include <string.h>
#include <stddef.h>
#include <stdlib.h>

struct X { int i; char c[4]; int j;};

void f(struct X *p)
{
        int n = 0;
#if 1
        // case 1
        while (p->c[n]) // uncond. abort
                ++n;
#else
#if 1
        // case 2
        char* pc = p->c; // no uncond. abort
#else
        // case 3
        char* pc = (char*)p + offsetof(struct X, c); // no uncond. abort
#endif
        while (pc[n])
                ++n;
#endif
        if (n < 7)
                abort();
}

void g(struct X *p)
{
        int n = 0;
#if 1
        // case 1
        n = strlen(p->c); // uncond. abort
#else
#if 1
        // case 2
        char* pc = p->c; // uncond. abort
#else
        // case 3
        char* pc = (char*)p + offsetof(struct X, c); // no uncond. abort
#endif
        n = strlen(pc);
#endif
        if (n < 7)
                abort();
}

Reply via email to