Skip to content

Don't emit != 0 when a C comparison or logical operator is returned as bool - #823

Merged
tannergooding merged 3 commits into
dotnet:mainfrom
tannergooding:fix-bool-return-comparison
Jul 18, 2026
Merged

Don't emit != 0 when a C comparison or logical operator is returned as bool#823
tannergooding merged 3 commits into
dotnet:mainfrom
tannergooding:fix-bool-return-comparison

Conversation

@tannergooding

Copy link
Copy Markdown
Member

Fixes #820.

In C, relational (< > <= >= == !=) and logical (&& ||) operators yield int, so returning one from a _Bool function inserts an ImplicitCastExpr<IntegralToBoolean>. The generator emitted (<expr>) != 0 for that cast, but the equivalent C# operators already yield bool, so the != 0 is both redundant and non-compiling (bool != int). C++ never hits this because < etc. already yield bool (no cast inserted).

The CX_CK_IntegralToBoolean handling now omits the != 0 whenever the operand is already a C#-boolean-valued expression -- a comparison, a logical &&/||, or a ! -- and otherwise keeps the existing != 0 coercion (e.g. return someInt;). Bitwise &/| are intentionally left untouched, since (x & mask) != 0 is genuinely int-to-bool.

Regression test added as CTest.BooleanReturnFromComparisonTest covering the comparison, logical, and plain-integer cases.


Not addressed here: the operands of a logical &&/|| with non-bool operands (e.g. int a, b; return a && b;) still emit invalid a && b -- that is a separate, pre-existing issue and out of scope for this fix.

@tannergooding
tannergooding force-pushed the fix-bool-return-comparison branch from 1622a8a to 4159184 Compare July 18, 2026 19:08
…s bool

In C, relational and logical operators yield `int`, so returning one from a `_Bool` function inserts an `IntegralToBoolean` cast. The equivalent C# operators already yield `bool`, making the `!= 0` coercion both redundant and non-compiling.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tannergooding
tannergooding force-pushed the fix-bool-return-comparison branch 2 times, most recently from 2633517 to cc90807 Compare July 18, 2026 19:12
…teger

The inverse of the != 0 case: in C, relational and logical operators yield
int, so their result can be stored in or returned as an integer without a
cast. The equivalent C# operators yield bool, which has no implicit
conversion to an integer, so a ? 1 : 0 coercion must be inserted where such
a value is returned from or assigned to an integer.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tannergooding
tannergooding force-pushed the fix-bool-return-comparison branch from cc90807 to 8ecc7a6 Compare July 18, 2026 19:15
A C &&/|| yields int and promotes a _Bool operand to int, which the
generator rendered as a ? 1 : 0 coercion. Since C#'s logical operators
take bool operands directly, this produced invalid, mis-precedenced output
like (a) ? 1 : 0 && (b) ? 1 : 0; emit the underlying bool instead.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@tannergooding
tannergooding force-pushed the fix-bool-return-comparison branch from 8ecc7a6 to 21401fa Compare July 18, 2026 19:21
@tannergooding
tannergooding merged commit eaf3ab5 into dotnet:main Jul 18, 2026
12 checks passed
@tannergooding
tannergooding deleted the fix-bool-return-comparison branch July 18, 2026 19:28
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.

equality to 0 should be omitted if return type is bool (with -g disable-runtime-marshalling)

1 participant