6

The following code prints int when compiled for x86_64 with Clang, and unsigned int with GCC.

I am not sure which (if either) is correct.

#include <stdio.h>
struct s {
    unsigned int x : 1;
};

template<typename T>
void f(T) {}

template<> void f<int>(int) {
    printf("int\n");
}

template<> void f<unsigned int>(unsigned int) {
    printf("unsigned int\n");
}

struct s r;
int main()
{
    f(0 ? r.x : 0);
}

If we replace the conditional with (r.x + 0) both compilers say the type is signed.

The C++ standard section expr.cond has a number of rules for conversion, but none of the cases seem to cover the issue of a conversion between a glvalue and a prvalue of different types.

Is it implementation-defined whether unsigned bitfields are promoted to signed ints?

Tjaden Hess
  • 291
  • 2
  • 11
  • 1
    An `unsigned:1` fits in an `int`. – Eljay Sep 22 '20 at 22:28
  • This: https://stackoverflow.com/questions/8535226/return-type-of-ternary-conditional-operator has an interesting quote from the standard: `It is determined whether the second operand can be converted to match the third operand, and whether the third operand can be converted to match the second operand. If both can be converted, or one can be converted but the conversion is ambiguous, the program is ill-formed. ` – Vlad Feinstein Sep 22 '20 at 22:51
  • 1
    @VladFeinstein The context for that is "Otherwise, if the second and third operand have different types and either has (possibly cv-qualified) class type, or if both are glvalues of the same value category and the same type except for cv-qualification, an attempt is made to form an implicit conversion sequence (16.3.3.1) from each of those operands to the type of the other." Neither operand is of class type in this case. – Tjaden Hess Sep 23 '20 at 01:15

1 Answers1

1

Clang is correct: the usual arithmetic conversions are applied just as for + ([expr.cond]/7.2) and promote the bit-field to int because it can represent all its values ([expr.arith.conv]/1.5, [conv.prom]/5, noting that the lvalue-to-rvalue conversion has already been applied ([expr.cond]/7, before the bullets)).

Davis Herring
  • 36,443
  • 4
  • 48
  • 76