https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64601
Marc Glisse <glisse at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #9 from Marc Glisse <glisse at gcc dot gnu.org> --- (In reply to Marc Glisse from comment #8) > The transformation is triggered by dereferences, and compares the types of > objects, not pointers, so it isn't obvious that the issues you were > describing apply to it. It looks like they still do apply. I was just lucky that the folding was done in an order where nothing bad happened in the tests. Your example int *p = &((struct A *)&b)->i; *p = 0; becomes *(int*)&b=0, which is fine. But in a different order, what I wanted could give: (*(struct A *)&b).i=0 (access b as an A) which would be wrong for TBAA. Although I don't see the point of writing that kind of code instead of: int *p = (int*)((char*)&b + offsetof(A, i)); So basically, a struct A * as an argument of a function doesn't carry any more information than a void* :-( It is only if we can see an actual VAR_DECL or similar that we may be able to reconstruct the access, but then we don't often need to... It is strange that [basic.lval] (or 6.5 Expressions in C99) is so lenient. [class.mem] is a little bit more restrictive but still not much. There is a little bit of divergence on function f below: void f(struct A *a){ *&a->i=0; } void g(struct A *a){ int*p=&a->i;*p=0; } void h(struct A *a){ a->i=0; } gcc, intel and oracle handle f like h, while clang is more conservative and handles it like g (I actually tested on a function taking 2 std::pair<int,int> by reference if a.first and b.second could alias). Ok, I am starting to understand vaguely what C/C++ are saying about type aliasing. I am horrified (this is a huge abstraction penalty), but at least I am less confused. I'll close this PR as INVALID (the trick about the same clobbering value is already in several other PRs, no need to keep this one as well) (if you want to remove some current unsafe transformations, it would probably be less confusing to open a different PR). I wonder how feasible it would be to define a dialect where any non-zero struct A* really points to a struct A... (we already have void* and char* for "untyped" pointers)