On Tue, Oct 1, 2019 at 7:49 PM Uecker, Martin <martin.uec...@med.uni-goettingen.de> wrote: > > > > Hi, > > I have a proposal for making changes to the rules for > compatibility of tagged types in C2X (N2366). This was > received with interest by WG14, so there is a chance > that this could get accepted into C2X. > > In particular, the idea is to make structs (+ unions, enums) > with the same tag and the same members compatible. The > current C standards says that such structs are compatible > between different TUs but not inside the same TU, which > is very strange and - as pointed out by Joseph > in DR314 - this leads to "interesting" scenarios > where types across different TU cannot be partitioned > into equivalence classes in a consistent way. > > The new rules would fix these inconsistencies and also > make some useful programming patterns possible: E.g. one > could declare structs/union/enums types in a macro so > that another invocation produces a compatible type. > For example: > > #define MAYBE(T) struct foo_##T { _Bool flag; T value }; > > MAYBE(int) x = { true, 0 }; > MAYBE(int) y = x; > > > I am working on a patch for GCC which adds this as an > optional feature. So far, I have a working patch to the > C front end which changes the concept of type compatibility > to match the proposed model. It uses the existing code > for type compatibility, so is relatively simple. > > The question is now how this should interact with the > middle end. So far, I have to insert some VIEW_CONVERT_EXPR > to avoid "useless type conversion" errors during gimple > verification. > > I am also wonder how to make TBAA do the right thing > for the new rules. Currently, GCC assumes 's1p' and 's2p' > cannot alias in the following example and outputs '2' > in 'f', but this would not be true anymore according > to the proposal. > > > #include <stdio.h> > > typedef struct { int i; } st1; > typedef struct { int i; } st2; > > void f(void* s1v, void* s2v) > { > st1 *s1p = s1v; > st2 *s2p = s2v; > s1p->i = 2; > s2p->i = 3; > printf("f: s1p->i = %i\n", s1p->i); > } > > int main() > { > st1 s = { .i = 1 }; > f(&s, &s); > printf("s.i = %i\n", s.i); > } > > BTW: According to current rules when 'f' is > moved into a different TU, there is no UB. > As both 'st1' > and 'st2' in one TU are compatible > to both 'st1' and 'st2' in the other TU there > is no UB. Still, GCC > incorrectly assumes that > 's1p' and 's1p' do not alias. > > > I would appreciate any information about how to > approach this.
The frontend either needs to have the same internal type representation for both or provide the middle-end with unification of compatible types via the TYPE_CANONICAL mechanism (that's what the C++ FE does in similar circumstances). That is, the TBAA machinery relies on TYPE_CANONICAL (TYPE_MAIN_VARIANT (st1)) == TYPE_CANONICAL (TYPE_MAIN_VARIANT (st2)) (or requivalent TYPE_MAIN_VARIANT if that's already the case). Richard. > > Best, > Martin >