This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

compatibility of structs/unions/enums in the middle end



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.

Best,
Martin


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]