*This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21
Core Issues List revision 115a.
See http://www.open-std.org/jtc1/sc22/wg21/ for the official
list.*

2024-07-24

[Accepted as a DR at the February, 2023 meeting.]

Consider an example like:

void f(unsigned char i, unsigned ui) { i <=> ui; }

According to 7.6.8 [expr.spaceship] paragraph
4, the usual arithmetic conversions are applied to the
operands. According to 7.4 [expr.arith.conv] bullet
1.5, the integral promotions are performed on both
operands, resulting in `i` being converted from
`unsigned char` to `int`. The operands
are then of types `int` and `unsigned int`,
so bullet 1.5.5 applies, further converting `i`
to type `unsigned int`.

Unfortunately, that latter conversion, from `int`
to `unsigned int`, is a narrowing conversion, which
runs afoul of 7.6.8 [expr.spaceship] bullet 4.1, which
prohibits narrowing conversions other than integral to
floating in three-way comparisons.

__Suggested resolution [SUPERSEDED]:__

Change 7.4 [expr.arith.conv] bullet 1.5 as follows:

Otherwise,

~~the integral promotions (7.3.7 [conv.prom]) shall be performed on both operands~~each operand shall be converted to a common typeC. The integral promotion rules (7.3.7 [conv.prom] shall be used to determine a typeT1and typeT2for each operand.^{50}Then the following rules shall be applied to~~the promoted operands~~determineC:

If

~~both operands have~~T1andT2are the same type,~~no further conversion is needed~~Cshall be that type.Otherwise, if

~~both operands have~~T1andT2are both signed integer types or both~~have~~are unsigned integer types,~~the operand with the type of lesser integer conversion rank shall be converted to the type of the operand~~Cshall be the type with greater rank.Otherwise, if the

~~operand that has~~the typeUthat is an unsigned integer type has rank greater than or equal to the rank of the other type~~of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type~~,Cshall beU.Otherwise, if the type

~~of the operand with~~Sthat is a signed integer type can represent all of the values of the other type~~of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type~~,Cshall beS.Otherwise,

~~both operands shall be converted to~~Cshall be the unsigned integer type corresponding to the~~type of the operand with~~signed integer type.

**Proposed resolution (approved by CWG 2023-02-09):**

Change in 7.4 [expr.arith.conv] bullet 1.3 as follows, adding sub-bullets:

Otherwise,~~the integral promotions (7.3.7 [conv.prom]) are performed on both operands~~each operand is converted to a common type C. The integral promotion rules (7.3.7 [conv.prom]) are used to determine a type T1 and type T2 for each operand. [ Footnote: ... ] Then the following rules are applied to~~the promoted operands~~determine C:

- If
~~both operands have~~T1 and T2 are the same type,~~no further conversion is needed~~C is that type.- Otherwise, if T1 and T2 are both
~~operands have~~signed integer types or are both~~have~~unsigned integer types,~~the operand with the type of lesser integer conversion rank is converted to the type of the operand~~C is the type with greater rank.- Otherwise,
~~if the operand that has~~let U be the unsigned integer type and S be the signed integer type.

- If U has rank greater than or equal to the rank of
~~the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type~~S, C is U.- Otherwise, if
~~the type of the operand with signed integer type~~S can represent all of the values of~~the type of the operand with unsigned integer type, the operand with unsigned integer type is converted to the type of the operand with signed integer type~~U, C is S.- Otherwise,
~~both operands are converted to~~C is the unsigned integer type corresponding to~~the type of the operand with signed integer type~~S.