diff --git a/lib/std/zig/c_translation.zig b/lib/std/zig/c_translation.zig index 664cb09ae4..ed78d4c4d6 100644 --- a/lib/std/zig/c_translation.zig +++ b/lib/std/zig/c_translation.zig @@ -570,6 +570,22 @@ pub const MacroArithmetic = struct { else => unreachable, } } + + pub fn rem(a: anytype, b: anytype) ArithmeticConversion(@TypeOf(a), @TypeOf(b)) { + const ResType = ArithmeticConversion(@TypeOf(a), @TypeOf(b)); + const a_casted = cast(ResType, a); + const b_casted = cast(ResType, b); + switch (@typeInfo(ResType)) { + .Int => { + if (@typeInfo(ResType).Int.signedness == .signed) { + return signedRemainder(a_casted, b_casted); + } else { + return a_casted % b_casted; + } + }, + else => unreachable, + } + } }; test "Macro suffix functions" { diff --git a/src/translate_c.zig b/src/translate_c.zig index 693f274e8e..3fffdd65b1 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -6237,7 +6237,7 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node { .Percent => { const lhs = try macroBoolToInt(c, node); const rhs = try macroBoolToInt(c, try parseCCastExpr(c, m, scope)); - node = try Tag.mod.create(c.arena, .{ .lhs = lhs, .rhs = rhs }); + node = try Tag.macro_arithmetic.create(c.arena, .{ .op = .rem, .lhs = lhs, .rhs = rhs }); }, else => { m.i -= 1; diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig index 4a64c13ce7..e54e986056 100644 --- a/src/translate_c/ast.zig +++ b/src/translate_c/ast.zig @@ -726,9 +726,7 @@ pub const Payload = struct { rhs: Node, }, - pub const Operator = enum { - div, - }; + pub const Operator = enum { div, rem }; }; }; diff --git a/test/behavior/translate_c_macros.h b/test/behavior/translate_c_macros.h index fc9aaaaf52..181c6cc2ad 100644 --- a/test/behavior/translate_c_macros.h +++ b/test/behavior/translate_c_macros.h @@ -56,3 +56,6 @@ typedef _Bool uintptr_t; #define DIVIDE_CONSTANT(version) (version / 1000) #define DIVIDE_ARGS(A, B) (A / B) + +#define REMAINDER_CONSTANT(version) (version % 10000) +#define REMAINDER_ARGS(A, B) (A % B) \ No newline at end of file diff --git a/test/behavior/translate_c_macros.zig b/test/behavior/translate_c_macros.zig index 51f7993cc2..5271a413c8 100644 --- a/test/behavior/translate_c_macros.zig +++ b/test/behavior/translate_c_macros.zig @@ -171,3 +171,37 @@ test "Macro that uses division operator. Issue #13162" { ), ); } + +test "Macro that uses remainder operator. Issue #13346" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + + try expectEqual(@as(c_int, 2_010), h.REMAINDER_CONSTANT(@as(c_int, 42_010))); + try expectEqual(@as(c_uint, 2_030), h.REMAINDER_CONSTANT(@as(c_uint, 42_030))); + + try expectEqual( + @as(c_int, 7), + h.REMAINDER_ARGS( + @as(i8, 17), + @as(i8, 10), + ), + ); + + try expectEqual( + @as(c_int, 5), + h.REMAINDER_ARGS( + @as(c_ushort, 25), + @as(c_ushort, 20), + ), + ); + + try expectEqual( + @as(c_int, 1), + h.REMAINDER_ARGS( + @as(c_int, 5), + @as(c_int, -2), + ), + ); +} diff --git a/test/translate_c.zig b/test/translate_c.zig index 81d1308c95..9f35f5ebc9 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -511,7 +511,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ _ = @as(c_int, 4) == @as(c_int, 4); \\ _ = @as(c_int, 5) * @as(c_int, 6); \\ _ = baz(@as(c_int, 1), @as(c_int, 2)); - \\ _ = @as(c_int, 2) % @as(c_int, 2); + \\ _ = @import("std").zig.c_translation.MacroArithmetic.rem(@as(c_int, 2), @as(c_int, 2)); \\ break :blk_1 baz(@as(c_int, 1), @as(c_int, 2)); \\ }; \\}