Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

minmax: fix up min3() and max3() too

David Laight pointed out that we should deal with the min3() and max3()
mess too, which still does excessive expansion.

And our current macros are actually rather broken.

In particular, the macros did this:

#define min3(x, y, z) min((typeof(x))min(x, y), z)
#define max3(x, y, z) max((typeof(x))max(x, y), z)

and that not only is a nested expansion of possibly very complex
arguments with all that involves, the typing with that "typeof()" cast
is completely wrong.

For example, imagine what happens in max3() if 'x' happens to be a
'unsigned char', but 'y' and 'z' are 'unsigned long'. The types are
compatible, and there's no warning - but the result is just random
garbage.

No, I don't think we've ever hit that issue in practice, but since we
now have sane infrastructure for doing this right, let's just use it.
It fixes any excessive expansion, and also avoids these kinds of broken
type issues.

Requested-by: David Laight <David.Laight@aculab.com>
Acked-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+10 -2
+10 -2
include/linux/minmax.h
··· 152 152 #define umax(x, y) \ 153 153 __careful_cmp(max, (x) + 0u + 0ul + 0ull, (y) + 0u + 0ul + 0ull) 154 154 155 + #define __careful_op3(op, x, y, z, ux, uy, uz) ({ \ 156 + __auto_type ux = (x); __auto_type uy = (y);__auto_type uz = (z);\ 157 + BUILD_BUG_ON_MSG(!__types_ok3(x,y,z,ux,uy,uz), \ 158 + #op"3("#x", "#y", "#z") signedness error"); \ 159 + __cmp(op, ux, __cmp(op, uy, uz)); }) 160 + 155 161 /** 156 162 * min3 - return minimum of three values 157 163 * @x: first value 158 164 * @y: second value 159 165 * @z: third value 160 166 */ 161 - #define min3(x, y, z) min((typeof(x))min(x, y), z) 167 + #define min3(x, y, z) \ 168 + __careful_op3(min, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_)) 162 169 163 170 /** 164 171 * max3 - return maximum of three values ··· 173 166 * @y: second value 174 167 * @z: third value 175 168 */ 176 - #define max3(x, y, z) max((typeof(x))max(x, y), z) 169 + #define max3(x, y, z) \ 170 + __careful_op3(max, x, y, z, __UNIQUE_ID(x_), __UNIQUE_ID(y_), __UNIQUE_ID(z_)) 177 171 178 172 /** 179 173 * min_not_zero - return the minimum that is _not_ zero, unless both are zero