[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