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---