Re: [PATCH] linux/const.h: Explain how __is_constexpr() works

From: Miguel Ojeda
Date: Wed Feb 02 2022 - 19:28:38 EST


On Wed, Feb 2, 2022 at 11:42 PM David Laight <David.Laight@xxxxxxxxxx> wrote:
>
> The compiler needs to find a 'compatible type' either for:
> (void *)x and (int *)8
> or for:
> (void *)0 and (int *)8
>
> In the former it is 'void *' and the latter 'int *' because the (void *)0
> is NULL and thus a valid 'int *' pointer.

I think you are trying to come up with an explanation of how it works
based on compiler outputs (it makes sense to think that the compiler
has to find some reasonable "common" type). But the conditional
operator works case-by-case, slightly differently depending on what
kind of operands you give.

In the two cases involved, there is no "finding a compatible type" /
promotions going on -- the standard gives explicitly that it is a
pointer to void (former case), and the type of the other operand
(latter case). The value is still decided by the condition.

e.g. https://godbolt.org/z/zzE8dc7Ye

0 ? void pointer (1) : pointer to object type (42) = (void *) 0x2a
1 ? void pointer (1) : pointer to object type (42) = (void *) 0x1
0 ? null pointer constant (0) : pointer (42) = ( int *) 0x2a
1 ? null pointer constant (0) : pointer (42) = ( int *) (nil)

> In any case suggesting that it is based on the value before the ? is bogus.

What Rasmus was saying is that which value is selected still depends
on the condition, because the last paragraph of the explanation in the
commit is wrong. It should be something like:

- The ultimate comparison to "sizeof(int)" reduces to either:
sizeof(int) == sizeof(*(int *)0) (x was a constant expression)
sizeof(int) == sizeof(*(void *)0) (x was not a constant expression)

Cheers,
Miguel