On Mon, Apr 19, 2021 at 12:21:39PM +0200, Aurélien Aptel wrote: > Hi, > > If the <then> and <else> expression in the ?: ternary operator have > different signedness they will both be implicitely casted to unsigned. > > When the result is stored in a variable with a storage capable of > holding both values, this is very unexpected. Consider this example: > > int rc = -1; > unsigned int foo = 123; > long x = y ? foo : rc; > > If one of the branch of the ?: is unsigned, then the compiler will cast > both branch to unsigned _before_ storing it in x. Despite long being > able to store INT_MIN, INT_MAX, UINT_MAX (assuming 64b long/32b int). > > So if y is 0, it's basically doing > > long x = (long)((unsigned int)-1); > > Which will result in storing 0x00000000ffffffff (4294967295) instead of > expected 0xffffffffffffffff (-1). Hmmm, I'm wondering what you would be warned about: - about 'y ? foo : rc' becoming unsigned? - about the cast 'unsigned int' -> '(signed) long' doing an zero-extension and not a sign extension? In both cases, it's not very different than: int rc = -1; unsigned int foo = 0; long x = foo + rc; and it boils down to the difference between: long x = (long)((unsigned int)-1); and long x = (long)((int)-1); > I thought we hit some sort of weird compiler bug but after reducing the > problem to the simple example above and trying it GCC, clang, ICC and > MSVC they all do the same thing: https://godbolt.org/z/P5Ts7o1df > > So it is most likely a C quirk. Standard reads 6.5.15. 5) > > If both the second and third operands have arithmetic type, the result > > type that would be determined by the usual arithmetic conversions, were > > they applied to those two operands, is the type of the result. Yes, it' also what Sparse is doing. Cheers, -- Luc