Skip to content

C# Compiler is not consistent with the CLR for the underlying representation of bool #24652

@tannergooding

Description

@tannergooding

Issue

Today the C# compiler does not emit code handling for bool that is consistent with the underlying representation of bool in the CLR.

The C# specification states:

The bool type represents boolean logical quantities. The possible values of type bool are true and false.

The spec also indicates that it is 1-byte. Specifically that the result of the sizeof(bool) expression is 1.

While the ECMA 335 specification states:

A CLI Boolean type occupies 1 byte in memory. A bit pattern of all zeroes denotes a value of
false. A bit pattern with any one or more bits set (analogous to a non-zero integer) denotes a
value of true. For the purpose of stack operations boolean values are treated as unsigned 1-byte
integers (§III.1.1.1).

This can lead to confusion about the handling and cause various inconsistencies in various edge cases (see dotnet/coreclr#16138 (comment), for such a thread).

Proposal

It would be good to determine:

  • Should the spec be updated?
    • The spec would explicitly list the expected values of true/false so that two implementations don't behave differently
  • Can the compiler be updated?
    • Given that we are emitting for the CLR, we would make our handling match the expected representations for the two boolean values (0/not 0) of the underlying platform

Current Behavior

The majority of the behaviors below actually match the CLR expectation that a bool can be more than just 0 or 1. However some of the behaviors (such as &&) does not match this expectation and can cause issues when interoping with any code that would assume otherwise (generally this is some kind of interop or unsafe code).

  • !value
ldarg.1
ldc.i4.0
ceq
  • left == right
ldarg.1
ldarg.2
ceq
  • left != right
ldarg.1
ldarg.2
ceq
ldc.i4.0
ceq
  • left & right
ldarg.1
ldarg.2
and
  • left | right
ldarg.1
ldarg.2
or
  • left ^ right
ldarg.1
ldarg.2
xor
  • left && right
ldarg.1
ldarg.2
and
  • left || right
ldarg.1
ldarg.2
or
  • value ? "true" : "false"
ldarg.1
brtrue.s

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions