Thread (7 messages) 7 messages, 4 authors, 2017-01-16

Re: llist code relies on undefined behaviour, upsets llvm/clang

flat view

From: Peter Zijlstra <peterz@infradead.org>
Date: 2017-01-16 16:25:37
Also in: lkml

On Mon, Jan 16, 2017 at 02:34:43PM +0000, David Laight wrote:
From: Anton Blanchard
quoted
Sent: 15 January 2017 21:36
I was debugging a hang on a ppc64le kernel built with clang, and it
looks to be undefined behaviour with pointer wrapping in the llist code.

A test case is below. llist_for_each_entry() does container_of() on a
NULL pointer, which wraps our pointer negative, then adds the same
offset back in and expects to get back to NULL. Unfortunately clang
decides that this can never be NULL and optimises it into an infinite
loop.
...
quoted
#define llist_for_each_entry(pos, node, member)                         \
        for ((pos) = llist_entry((node), typeof(*(pos)), member);       \
             &(pos)->member != NULL;                                    \
             (pos) = llist_entry((pos)->member.next, typeof(*(pos)), member))
Maybe the above could be rewritten as (untested):
		for ((pos) = NULL; (!(pos) ? (node) : ((pos)->member.next) || (pos) = 0) && \
			(((pos) = !(pos) ? llist_entry((node), typeof(*(pos)), member) \
					: llist_entry((pos)->member.next, typeof(*(pos)), member)),1); )
Provided the compiler assumes that the loop body is never executed with 'pos == 0'
it should generate the same code.
That's far uglier code and to what point? The compiler should simply not
assume silly things.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help