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.