I really appreciate your efforts.
I have a working version, using a union in a way that I think is
incorrect, but this is the same concept I used last time I fixed one of
these issues.
Everything I've tried so far with __attribute__((__may_alias__)) has
failed. I'd really like to know how to make that work.
Working code:
union { DAT* pp; std::size_t dummy; } no_strict_alias;
no_strict_alias.pp =foo();
reinterpret_cast<DAT_PTR*>(&no_strict_alias.pp)->bar(x);
Notice that dummy is never used. Notice that the reinterpret_cast is
essentially unchanged (from the version that doesn't work). The union
is just doing what I would have expected the attribute to do, marking
pp as an object for which strict aliasing optimizations should not be used.
The last time I fixed one of these, I didn't try as hard to get the
attribute to work before giving up. For very different reasons in the
previous case, I also couldn't use a union correctly and in that case
there were multiple reinterpret_casts, such that the misused union
wasn't involved at all in the read side. (The value was written through
a reinterpret_cast to the union and read through an unrelated
reinterpret_cast in distant code that was brought together only by
compiler inlining.).
Ian Lance Taylor wrote:
When you can't use a union, another option is memcpy.
That's a pretty ugly choice.
The may_alias attribute should be on the type to which things point. SO
you want something like
typedef DAT __attribute__ ((__may_alias__)) DAT_ALIAS;
and then use DAT_ALIAS*.
I tried that, even though it makes no sense to me (it protects the wrong
level of indirection). It didn't work.
The three levels of indirection here:
0) The DAT object: That is always a DAT object, no change in
interpretation.
1) pp: That is sometimes a DAT* and sometimes a DAT_PTR. That is the
heart of the problem.
2) &pp: That is reinterpreted from a DAT** to a DAT_PTR*
I would think the attribute should apply to the level whose type
actually changes, which is level 1 in this case, as in the working union
code where I have a DAT* in the union, not a DAT.
In my sample code, foo() is a method that returns a DAT*. bar() is a
member function in the class DAT_PTR, not the class DAT.