Skip to content

Fix invalid codegen for bool bitfields#727

Merged
tannergooding merged 1 commit into
dotnet:mainfrom
tannergooding:fix-bool-bitfields
Jul 13, 2026
Merged

Fix invalid codegen for bool bitfields#727
tannergooding merged 1 commit into
dotnet:mainfrom
tannergooding:fix-bool-bitfields

Conversation

@tannergooding

Copy link
Copy Markdown
Member

Fixes #508.

A bool bitfield generated fully invalid C#: a bool backing field, bool & int masking, and (bool) casts, e.g.

public bool _bitfield1;
// ...
return (bool)(_bitfield1 & 0x1);                                   // invalid
_bitfield1 = (bool)((_bitfield1 & ~0x1) | (value & 0x1));          // invalid

Fix

Route bool bitfields through the same unsigned-integer path already used for the equivalently-sized integer type (a byte backing store), but keep the public accessor typed bool and convert at the get/set boundary:

  • backing field is an integer (byte),
  • the getter compares the masked value against zero (... != 0),
  • the setter maps the incoming bool to 0/1 (value ? 1 : 0).
public byte _bitfield1;

[NativeTypeName(""bool : 1"")]
public bool a
{
    readonly get => (_bitfield1 & 0x1u) != 0;
    set => _bitfield1 = (byte)((_bitfield1 & ~0x1u) | ((value ? 1 : 0) & 0x1u));
}

Non-bool bitfields are untouched (an adjacent int c : 2 in the test emits identical output to before).

Validation

  • Build: 0 warnings / 0 errors (Release).
  • Generated output for a bool/int mix compiles and round-trips correctly under TreatWarningsAsErrors.
  • Tests: 3710 passed, 0 failed (3708 existing byte-identical + 2 new BooleanBitfieldTest cases covering the readonly get and compatible-code accessor shapes).

Known limitation (pre-existing, out of scope)

Mixing a bool bitfield with a differently-typed bitfield of the same size in a single storage unit (e.g. bool a : 1; char b : 1;) was already emitting invalid code before this change and still is; the common all-bool case and bool mixed with different-sized fields both work.

Note

This PR description and the change were drafted with Copilot.

A bool bitfield previously emitted a bool backing field together with
bool & int arithmetic and (bool) casts, none of which are valid C#. Route
bool bitfields through the same unsigned-integer path used for the
equivalently-sized integer type (a byte backing store), keep the public
accessor typed as bool, and convert at the get/set boundary: the getter
compares the masked value against zero and the setter maps the incoming
bool to 0/1. Non-bool bitfields are unaffected.

Fixes dotnet#508

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tannergooding tannergooding merged commit 8f6e955 into dotnet:main Jul 13, 2026
14 checks passed
@tannergooding tannergooding deleted the fix-bool-bitfields branch July 13, 2026 05:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bitfield generations for bools generate invalid comparison expressions (and errors)

1 participant