Search code examples
c++visual-studio-2015language-lawyerbit-fieldsinteger-promotion

Should bit-fields less than int in size be the subject of integral promotion?


Let's say I have following struct:

struct A
{
    unsigned int a : 1;
    unsigned int b : 1;
};

What interests me is the type of expression a + b. While technically bit-fields have "type" with size less than int so integral promotion probably should happen and then result is int like it happens to be in gcc and clang.

But since it's impossible to extract the exact type of bit-field itself and it will always be deduced to be its "big" type (i.e. unsigned int in this case) is it correct that integral promotion should happen? Because we can't actually talk about exact types and their sizes for bit-fields except them being deduced as unsigned int in which case integral promotion shouldn't happen.

(Once again my question stems from the fact that MSVC happens to think that unsigned int is type of such expression)


Solution

  • If we go to the draft C++ standard: N4140 section 5 it says:

    Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows

    and the following bullet applies:

    • Otherwise, the integral promotions (4.5) shall be performed on both operands.61 Then the following rules shall be applied to the promoted operands:

    and section 4.5 which says (emphasis mine):

    A prvalue for an integral bit-field (9.6) can be converted to a prvalue of type int if int can represent all the values of the bit-field; otherwise, it can be converted to unsigned int if unsigned int can represent all the values of the bit-field. If the bit-field is larger yet, no integral promotion applies to it. If the bit-field has an enumerated type, it is treated as any other value of that type for promotion purposes.

    So gcc and clang are correct, a and b should be promoted to int.