C++ Logo

std-proposals

Advanced search

[std-proposals] Problematic integral promotions on bitfields

From: Johnston, Daniel <daniel.johnston_at_[hidden]>
Date: Fri, 2 Dec 2022 20:04:08 +0000
Reference: https://github.com/llvm/llvm-project/issues/59306

Short version, this code seems to be undefined behavior:

//==============================================================
struct Foo
{
      uint64_t Stuff : 6;
      uint64_t Value: 27;
      uint64_t OtherStuff: 31;
};

Foo f;
f.Value = (uint64_t(1) << 27) - 1;

// Caution UB here due to integral promotion of bitifields!
uint64_t shiftedValue = f.Value << 6;
uint64_t maskedValue = reinterpret_cast<uint64_t&>(f) & (((uint64_t(1) << 27) - 1) << 6);

assert(shiftedValue == maskedValue); // this may fail depending on compiler
//==============================================================

In the above scenario, a bitwidth for Value of 32 or higher guarantees correct operation. A bitwidth of less than (32 - shift amount) works as well. A bitwidth that exactly matches (32 - shift amount) could *sign extend* the result even though it should be unsigned.

This seems like a defect in the standard and has caused bugs for us when simulating HW that requires structures with these bit layouts.

Can we fix the standard to disallow integral promotion of bitfields completely? I *always* want the type of the bitfield value to match what was specified.

Thank you,

-dan

Received on 2022-12-02 20:04:41