https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86259
--- Comment #22 from Martin Sebor <msebor at gcc dot gnu.org> --- In areas where the authors of the proposal find the standard open to interpretation and when they feel it doesn't contradict the surveyed implementation practice they tend to suggest to tighten the requirements on implementations (I think they surveyed mainly Clang and GCC) to make code valid that may be questionable today. Their implementation survey isn't comprehensive and so in some cases they may be suggesting changes that would invalidate some optimizations. It's not entirely clear to me that this is one such case -- they may only be thinking of allocated storage and not auto/static objects as suggested in 2.3.3 Q9b in N2263. WG14 takes a different view from the authors: where we agree that the standard is unclear we would like to tighten the requirements on programs to allow better analysis, better optimization, and better detection of bugs. WG14 has formed a study group to try to come up with the next revision of the proposal that's closer to WG14's goal. With respect to objects and their subobjects, the existing requirements are sufficiently clear and existing practice shows that compilers have been relying on those requirements for some time (GCC well over a decade). For example: struct S { char a[4], b[4]; }; void f (struct S *p, int i) { if (i < 4) i = 4; char b = p->b[0]; p->a[i] = 0; // assumed not to change p->b (undefined otherwise) if (p->b[0] != b) // folded to false __builtin_abort (); // eliminated } In function ‘f’: warning: array subscript 4 is above array bounds of ‘char[4]’ [-Warray-bounds] p->a[i] = 0; // assumed not to change p->b (undefined if it did) ~~~~^~~ ;; Function f (f, funcdef_no=0, decl_uid=1960, cgraph_uid=0, symbol_order=0) f (struct S * p, int i) { <bb 2> [local count: 1073741825]: i_6 = MAX_EXPR <i_2(D), 4>; p_4(D)->a[i_6] = 0; return; } Besides GCC, Intel ICC also performs the same optimization. The test cases in this report are variations on this theme. The only difference is that they use built-in functions to access the elements of the distinct subobjects rather than accessing them directly. GCC has just extended the optimization above to a subset of calls of built-in functions. Besides strlen(), here's another example from GCC 7: struct S { char a[4], b[4]; }; void f (struct S *p, int i) { int n = __builtin_snprintf (0, 0, "%s", p->a); // n must be between 0 and 3 if (n > 3) // folded to false __builtin_abort (); // eliminated }