------- Comment #28 from matz at gcc dot gnu dot org 2010-01-31 20:34 ------- fejj: To see how your initial code is broken, I've transformed it a bit to show you how it already is "miscompiled" with earlier compilers. I've manually unrolled the loop, and hoisted the two malloc calls to the front. You hopefully agree that the function then is completely equivalent to your initial testcase (assuming validity to start with). Like so:
% cat broken.c #include <stdio.h> #include <stdlib.h> typedef struct _node { struct _node *next; int value; } Node; int main (int argc, char **argv) { Node *list, *node, *tail; Node *n1, *n2; int i; n1 = malloc (sizeof (Node)); n2 = malloc (sizeof (Node)); list = NULL; tail = (Node *) &list; node = n1; node->next = NULL; node->value = 0; tail->next = node; tail = node; node = n2; node->next = NULL; node->value = 2; tail->next = node; tail = node; if (list == NULL) printf ("oops, list is null???\n"); return 0; } Compile this with e.g. gcc-4.3 -O2 and see it broken too. From your blog entry I gather that you think this has something to do with the recent gcc@ discussion about interpreting the C standard regarding accesses through unions or similar. This is not the case. The code as written simply is completely unspecified in _any_ interpretation of the standard. To see this, add this statement into the list: tail->value = tail->value; This statement must be harmless iff tail indeed points to enough memory to have a value member. But in the first iteration tail points to list, a Node*, hence it holds only enough memory for one pointer. I.e. would you change the order of the struct members ('value' first, 'next' second) already the access to ->next in your original testcase would overwrite non-existing memory (and depending on circumstance for instance valgrind would complain). The list variables simply is only one pointer long, not two. I hope you see now that we don't even need to invoke aliasing arguments to show that the testcase was invalid: In the first iteration tail points to something that doesn't even have enough space to contain a whole Node. We don't even need to argue about the type of it. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42907