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(); }