[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