Paolo Bonzini wrote:
foo->bar = make_a_bar();
foo->bar->none = value;
being rendered as:
call make_a_bar
foo->bar->none = value
foo->bar = <result of make_a_bar()>
You are not describing a C compiler.
Um, I'm describing what gcc did?
I think he meant
x = make_a_bar ();
x->none = value;
foo->bar = x;
I don't know if this is a valid optimization, but I wouldn't be
surprised if it is.
Maybe he forgot the delicate details? The issue may happen if this
example was incomplete (my "completion" may need some tweaking to make
it more realistic):
#define make_a_bar(ppInstance)
*(unsigned**)(&ppInstance)=make_a_uint(sizeof(struct bar))
make_a_bar(foo->bar);
foo->bar->none = value;
In this case strict-aliasing starts its act. The store to foo->bar is
done through a different type (pointer to unsigned), which tells gcc
that foo->bar->none accesses one object (type bar), while the
construction of foo->bar accesses a different object type (unsigned
int). In this case this code is undefined and the compiler can reorder
these two lines.
I am not sure if the following would break as well:
#define make_a_bar() (struct bar*)make_a_uint(sizeof(struct bar))
foo->bar=make_a_bar();
foo->bar->none = value;
Since gcc should know that foo->bar of type "struct bar" has been
updated before "value" gets written to "none" which is a field on object
of type "struct bar".
Michael