diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index f14ebe330..934ed3634 100644 --- a/src-self-hosted/translate_c.zig +++ b/src-self-hosted/translate_c.zig @@ -560,7 +560,7 @@ fn visitVarDecl(c: *Context, var_decl: *const ZigClangVarDecl) Error!void { // TODO https://github.com/ziglang/zig/issues/3756 // TODO https://github.com/ziglang/zig/issues/1802 - const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{var_name, c.getMangle()}) else var_name; + const checked_name = if (isZigPrimitiveType(var_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ var_name, c.getMangle() }) else var_name; const var_decl_loc = ZigClangVarDecl_getLocation(var_decl); const qual_type = ZigClangVarDecl_getTypeSourceInfo_getType(var_decl); @@ -677,7 +677,7 @@ fn transTypeDef(c: *Context, typedef_decl: *const ZigClangTypedefNameDecl, top_l // TODO https://github.com/ziglang/zig/issues/3756 // TODO https://github.com/ziglang/zig/issues/1802 - const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{typedef_name, c.getMangle()}) else typedef_name; + const checked_name = if (isZigPrimitiveType(typedef_name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ typedef_name, c.getMangle() }) else typedef_name; if (mem.eql(u8, checked_name, "uint8_t")) return transTypeDefAsBuiltin(c, typedef_decl, "u8") @@ -4871,7 +4871,7 @@ fn transPreprocessorEntities(c: *Context, unit: *ZigClangASTUnit) Error!void { const name = try c.str(raw_name); // TODO https://github.com/ziglang/zig/issues/3756 // TODO https://github.com/ziglang/zig/issues/1802 - const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{name, c.getMangle()}) else name; + const mangled_name = if (isZigPrimitiveType(name)) try std.fmt.allocPrint(c.a(), "{}_{}", .{ name, c.getMangle() }) else name; if (scope.containsNow(mangled_name)) { continue; } @@ -5560,12 +5560,63 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, } } +fn macroBoolToInt(c: *Context, node: *ast.Node) !*ast.Node { + if (!isBoolRes(node)) { + if (node.id != .InfixOp) return node; + + const group_node = try c.a().create(ast.Node.GroupedExpression); + group_node.* = .{ + .lparen = try appendToken(c, .LParen, "("), + .expr = node, + .rparen = try appendToken(c, .RParen, ")"), + }; + return &group_node.base; + } + + const builtin_node = try transCreateNodeBuiltinFnCall(c, "@boolToInt"); + try builtin_node.params.push(node); + builtin_node.rparen_token = try appendToken(c, .RParen, ")"); + return &builtin_node.base; +} + +fn macroIntToBool(c: *Context, node: *ast.Node) !*ast.Node { + if (isBoolRes(node)) { + if (node.id != .InfixOp) return node; + + const group_node = try c.a().create(ast.Node.GroupedExpression); + group_node.* = .{ + .lparen = try appendToken(c, .LParen, "("), + .expr = node, + .rparen = try appendToken(c, .RParen, ")"), + }; + return &group_node.base; + } + + const op_token = try appendToken(c, .BangEqual, "!="); + const zero = try transCreateNodeInt(c, 0); + const res = try c.a().create(ast.Node.InfixOp); + res.* = .{ + .op_token = op_token, + .lhs = node, + .op = .BangEqual, + .rhs = zero, + }; + const group_node = try c.a().create(ast.Node.GroupedExpression); + group_node.* = .{ + .lparen = try appendToken(c, .LParen, "("), + .expr = &res.base, + .rparen = try appendToken(c, .RParen, ")"), + }; + return &group_node.base; +} + fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, source_loc: ZigClangSourceLocation, scope: *Scope) ParseError!*ast.Node { var node = try parseCPrimaryExpr(c, it, source, source_loc, scope); while (true) { const tok = it.next().?; var op_token: ast.TokenIndex = undefined; var op_id: ast.Node.InfixOp.Op = undefined; + var bool_op = false; switch (tok.id) { .Period => { const name_tok = it.next().?; @@ -5654,10 +5705,12 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, .AmpersandAmpersand => { op_token = try appendToken(c, .Keyword_and, "and"); op_id = .BoolAnd; + bool_op = true; }, .PipePipe => { op_token = try appendToken(c, .Keyword_or, "or"); op_id = .BoolOr; + bool_op = true; }, .AngleBracketRight => { op_token = try appendToken(c, .AngleBracketRight, ">"); @@ -5740,12 +5793,14 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8, return node; }, } + const rhs_node = try parseCPrefixOpExpr(c, it, source, source_loc, scope); const op_node = try c.a().create(ast.Node.InfixOp); + const cast_fn = if (bool_op) macroIntToBool else macroBoolToInt; op_node.* = .{ .op_token = op_token, - .lhs = node, + .lhs = try cast_fn(c, node), .op = op_id, - .rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope), + .rhs = try cast_fn(c, rhs_node), }; node = &op_node.base; } diff --git a/test/translate_c.zig b/test/translate_c.zig index e21c3c49a..29b07b86a 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -3,6 +3,17 @@ const std = @import("std"); const CrossTarget = std.zig.CrossTarget; pub fn addCases(cases: *tests.TranslateCContext) void { + cases.add("c booleans are just ints", + \\#define FOO(x) ((x >= 0) + (x >= 0)) + \\#define BAR 1 && 2 > 4 + , &[_][]const u8{ + \\pub inline fn FOO(x: var) @TypeOf(@boolToInt(x >= 0) + @boolToInt(x >= 0)) { + \\ return @boolToInt(x >= 0) + @boolToInt(x >= 0); + \\} + , + \\pub const BAR = (1 != 0) and (2 > 4); + }); + cases.add("struct with aligned fields", \\struct foo { \\ __attribute__((aligned(1))) short bar;