This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[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 operandseach operand shall be converted to a common type C. The integral promotion rules (7.3.7 [conv.prom] shall be used to determine a type T1 and type T2 for each operand.50 Then the following rules shall be applied tothe promoted operandsdetermine C:
If
both operands haveT1 and T2 are the same type,no further conversion is neededC shall be that type.Otherwise, if
both operands haveT1 and T2 are both signed integer types or bothhaveare unsigned integer types,the operand with the type of lesser integer conversion rank shall be converted to the type of the operandC shall be the type with greater rank.Otherwise, if the
operand that hasthe type U that is an unsigned integer type has rank greater than or equal to the rank of the other typeof the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type, C shall be U.Otherwise, if the type
of the operand withS that is a signed integer type can represent all of the values of the other typeof 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, C shall be S.Otherwise,
both operands shall be converted toC shall be the unsigned integer type corresponding to thetype of the operand withsigned 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 operandseach 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 tothe promoted operandsdetermine C:
- If
both operands haveT1 and T2 are the same type,no further conversion is neededC is that type.- Otherwise, if T1 and T2 are both
operands havesigned integer types or are bothhaveunsigned integer types,the operand with the type of lesser integer conversion rank is converted to the type of the operandC is the type with greater rank.- Otherwise,
if the operand that haslet 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 typeS, C is U.- Otherwise, if
the type of the operand with signed integer typeS can represent all of the values ofthe 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 typeU, C is S.- Otherwise,
both operands are converted toC is the unsigned integer type corresponding tothe type of the operand with signed integer typeS.