Title
Underspecified behavior of bit-fields
Status
open
Section
7.6.16 [expr.cond]
Submitter
Jay Ghiron

Created on 2025-11-22.00:00:00 last changed 2 weeks ago

Messages

Date: 2025-11-22.21:10:21

Possible resolution:

  1. Change in 7.5.5.2 [expr.prim.id.unqual] paragraph 12 as follows:

    The expression is an xvalue if it is move-eligible (see below); an lvalue if the entity is a function, variable, structured binding (9.7 [dcl.struct.bind]), result binding (9.4.2 [dcl.contract.res]), data member, or template parameter object; and a prvalue otherwise (7.2.1 [basic.lval]); it is a bit-field of width N if the identifier designates a bit-field of width N.
  2. Change in 7.5.9 [expr.prim.splice] bullet 2.3 and 2.4 as follows:

    • ...
    • Otherwise, if S is an object or a non-static data member, the expression is an lvalue designating S. The expression has the same type as that of S, and is a bit-field of width N if and only if S is a bit-field of width N. [ Note: ... ]
    • Otherwise, if S is a variable or a structured binding, S shall either have static or thread storage duration or shall inhabit a scope enclosing the expression. The expression is an lvalue referring to the object or function X associated with or referenced by S, has the same type as that of S, and is a bit-field of width N if and only if X is a bit-field of width N. [ Note: ... ]
    • ...
  3. Change in 7.6.1.5 [expr.ref] paragraph 7 as follows:

    If E2 designates a bit-field of width N, E1.E2 is a bit-field of width N. The type and value category of E1.E2 are determined as follows. In the remainder of 7.6.1.5 [expr.ref], cq represents either const or the absence of const and vq represents either volatile or the absence of volatile. cv represents an arbitrary set of cv-qualifiers, as defined in 6.9.5 [basic.type.qualifier].
  4. Change in 7.6.16 [expr.cond] bullet 2.1 as follows:

    The second or the third operand (but not both) is a (possibly parenthesized) throw-expression (7.6.18 [expr.throw]); the result is of the type and value category of the other. The conditional-expression is a bit-field of width N if that operand is a bit-field of width N.
  5. Change in 7.6.16 [expr.cond] paragraph 5 as follows:

    If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category and it is a bit-field if . If either the second or the third operand is a bit-field of width N and the other operand is of integer type of width M, or if both operands are bit-fields of widths N and M, respectively, the resulting glvalue is a bit field of width K, where K is the maximum of N and M.
  6. Change in 7.6.19 [expr.assign] paragraph 1 as follows:

    ... The result in all cases is a bit-field of width N if the left operand is a bit-field of width N. ...
  7. Change in 7.6.19 [expr.assign] paragraph 4 as follows:

    When the result of the left operand of an assignment operator is a bit-field of width N and a hypothetical extended integer type with width N and with the same signedness as the bit-field that cannot represent the value of the expression, the resulting value of the bit-field is implementation-defined.
  8. Change in 7.6.20 [expr.comma] paragraph 1 as follows:

    ... The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand, and is a bit-field of width N if its right operand is a bit-field of width N.
  9. Change in 9.7 [dcl.struct.bind] paragraph 8 as follows:

    ... The lvalue is a bit-field of width N if that member is a bit-field of width N.
Date: 2025-11-22.21:10:21

(From submission #820.)

It is unclear how the width of a bit-field propagates through an expression tree. For example:

  struct {
    int x: 3;
    int y: 4;
  } s;

  void f(bool b) {
    (0 ? s.x : s.y) = 7;  // does this store 7 into s.y?
    (b ? s.x : s.y) = 7;
  }

Issue 324 was resolved to propagate the bit-field property across a conditional-expression, but it did not specify the width of the resulting bit-field, even though 7.6.19 [expr.assign] paragraph 4 relies on it.

Beyond assignment (7.6.19 [expr.assign] paragraph 4), the bit-field width of an expression is also relevant for integral promotion (7.3.7 [conv.prom] paragraph 5) and for narrowing checking (9.5.5 [dcl.init.list] bullet 7.4).

There are a number of options here, including making conditional lvalue expressions involving bit-fields ill-formed (at least when the widths of the affected bit-fields differ), thereby reverting issue 324, or applying the lvalue-to-rvalue conversion (which loses the bit-field property), or clarifying the specification that assignment uses the dynamically-chosen width of the involved bit-fields, but integral promotion and narrowing checking uses their maximum width.

There is implementation divergence.

History
Date User Action Args
2025-11-22 18:23:08adminsetmessages: + msg8416
2025-11-22 00:00:00admincreate