At least that's what I'm suspecting. Consider following example:
struct __attribute__((may_alias)) tag_si {
int y;
};
struct __attribute__((may_alias)) tag_s {
int x;
struct tag_si *pi;
struct tag_s *p;
};
int main(void)
{
struct tag_s test = {0};
struct tag_si **ppi;
struct tag_s **pp;
ppi = &test.pi;
pp = &test.p;
return 0;
}
The "problem" with the above example, is that pp assignment will cause
compiler to emit:
test.c: In function 'main':
test.c:18:12: warning: assignment from incompatible pointer type
[enabled by default]
pp = &test.p;
^
At the same time analogous ppi assignment gives no issues.
This can be workarounded with a simple typedef and a cast (not
necessarily adding to the readabilty though) if one wants to avoid the
warning, e.g.:
typedef struct tag_s *tag_t_pa __attribute__((may_alias));
tag_t_pa *pp;
pp = (tag_t_pa *)&test.p;
Also - simple forward declaration will have no effect, e.g.
struct __attribute__((may_alias)) tag_s;
To sum up - as far as I can understand:
tag_si is defined earlier - so everything works as expected while being
used in the definition of tag_s.
tag_s on the other hand - while being referenced inside its own
definition - "forgets" may_alias and causes incompatible type warning.
Is this expected behaviour ? Shouldn't may_alias be always used
(including inside-definition references) once after it's been seen for
the first time on the definition ? Or is there something else I'm
missing ...