Commit c6b4fe0066

Evan Haas <evan@lagerdata.com>
2021-11-21 01:03:16
translate-c: coerce boolean results to c_int when negated
Fixes #10175
1 parent 4e5a88b
Changed files (2)
src/translate_c.zig
@@ -3648,7 +3648,13 @@ fn transUnaryOperator(c: *Context, scope: *Scope, stmt: *const clang.UnaryOperat
         .Plus => return transExpr(c, scope, op_expr, used),
         .Minus => {
             if (!qualTypeHasWrappingOverflow(op_expr.getType())) {
-                return Tag.negate.create(c.arena, try transExpr(c, scope, op_expr, .used));
+                const sub_expr_node = try transExpr(c, scope, op_expr, .used);
+                const to_negate = if (isBoolRes(sub_expr_node)) blk: {
+                    const ty_node = try Tag.type.create(c.arena, "c_int");
+                    const int_node = try Tag.bool_to_int.create(c.arena, sub_expr_node);
+                    break :blk try Tag.as.create(c.arena, .{ .lhs = ty_node, .rhs = int_node });
+                } else sub_expr_node;
+                return Tag.negate.create(c.arena, to_negate);
             } else if (cIsUnsignedInteger(op_expr.getType())) {
                 // use -% x for unsigned integers
                 return Tag.negate_wrap.create(c.arena, try transExpr(c, scope, op_expr, .used));
test/run_translated_c.zig
@@ -1796,4 +1796,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
         \\    return 0;
         \\}
     , "");
+
+    cases.add("Boolean expression coerced to int. Issue #10175",
+        \\#include <stdlib.h>
+        \\int sign(int v) {
+        \\    return -(v < 0);
+        \\}
+        \\int main(void) {
+        \\    if (sign(-5) != -1) abort();
+        \\    if (sign(5) != 0) abort();
+        \\    if (sign(0) != 0) abort();
+        \\    return 0;
+        \\}
+    , "");
 }