[Bug c/43637] [4.4/4.5 regression] miscompilation in strict-aliasing optimization
jengelh at medozas dot de
gcc-bugzilla@gcc.gnu.org
Wed May 26 21:44:00 GMT 2010
------- Comment #3 from jengelh at medozas dot de 2010-05-26 21:44 -------
>You are accessing {lh,clh}.{next,prev} through a pointer to type struct item.
Thank you for your time.
I do have a few questions. I wonder where exactly I am doing that access. In
the first part of the for clause,
(pos) = list_entry((head)->next, typeof(*(pos)), member);
head->next is valid, so only pos is punned. The second part is
&(pos)->member != (void *)(head);
This I can imagine blowing up; as pos will point to a non-existing memory block
once the end of the list is reached. I thus replace that by the reverse of
containerof to avoid dereferencing pos (/or accessing member/next through a
pointer of the wrong type), IOW
#define s_member(var, type, member) \
((type *)((char *)var + offsetof(typeof(*var), member)))
s_member(pos, struct list_head, member) != (void *)(head)
On an empty list, the condition is not met, so the for loop stops and the third
part of the for() is not evaluated. On a non-empty list, pos points to a valid
memory region as long as it loops, so that the pos->member.next in 3rd part,
(pos) = list_entry((pos)->member.next, typeof(*(pos)), member))
should be valid. Please correct me if I am wrong.
Though I also have to employ s_member in the third case
(pos) = list_entry(s_member((pos), struct list_head, member)->next,
typeof(*(pos)), member))
to get rid of any visible artifacts (such as segfaults), but I suspect the
underlying problem isn't eliminated.
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43637
More information about the Gcc-bugs
mailing list