[PATCH] Fix PR71598, aliasing between enums and compatible types
Michael Matz
matz@suse.de
Mon Mar 18 15:19:00 GMT 2019
Hi,
On Mon, 18 Mar 2019, Richard Biener wrote:
> > Or, because an enum with these properties could be modelled as a struct
> > containing one member of basetype you could also change
> > record_component_aliases(), though that doesn't allow language specific
> > behaviour differences.
>
> No, you can't. I believe that enum X and int being compatible means
> that accessing an enum X object via an lvalue of effective type int
> is OK _and_ accessing an int object via an lvalue of effective type
> enum X is OK.
I agree. But the objects type still remains whatever it was: either an
enum or an int; type equivalence/identity isn't affected by compatiblity.
> That commutativity doesn't hold for struct X { int i; }
> vs. int i and those types are not compatible.
True, but that's not the important aspect that the aliasing subsetting
expresses: if A subsets B or B subsets A, all accesses between an A and a
B conflict. If A is the "struct S1 {int}" and B is "int" that's exactly
right, an access to the struct and one to an int (_access_, where you
don't necessarily know the declared type) conflict. But if we have a C,
an "struct S2 {int}" the direction of the subsetting starts to matter:
A conflict B, and C conflict B, but !(A conflict C). This is exactly the
situation with A and C being different enums as well.
The non-transitivity of the 'conflicts' relation is expressed by having a
direction in the alias subset relation: everything that is (or contains)
and A conflicts with everything that is (or contains) an int, everything
that is (or contains) a C conflicts with int, but nothing that is (or
contains) an A conflicts with anything that is (or contains) a C (if not
for other reasons).
> At least unless Joseph corrects me here and that "type X is compatible
> with type Y" doesn't imply "type Y is compatible with type X"
> (that's not transitivity).
That's not transitivity but symmetry, and that of course holds for
"compatible". X compat Y, and Z compat Y --> X compat Z would be
transitivity and doesn't hold.
> Now, we can't currently model precisely this way of non-transitivity
> of C's notion of "compatibility".
>
> enum X { A };
> enum Y { B };
> void *ptr = malloc (4);
> *(enum X *)ptr = A; // dynamic type is now X
> foo (*(enum Y *)ptr); // undefined, X and Y are not compatible(?)
> foo (*(int *)ptr); // OK, X and int are compatible
> *(int *)ptr = *(enum X *); // dynamic type is now int
> foo (*(enum Y *)ptr); // OK(?), Y and int are compatible
I'm pretty sure this can be expressed, in the way I suggested, making X
subset int, Y subset int (or superset? As said, I'm always confused), and
those above would work.
Ciao,
Michael.
More information about the Gcc-patches
mailing list