Skip to content

Commit dbc886f

Browse files
cfillionVexu
authored andcommitted
translate-c: fix division and modulo of >8-bit stdint.h types in macros
Broke in c616141 and e64eef3
1 parent 84cdb62 commit dbc886f

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

lib/std/zig/c_translation.zig

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -436,15 +436,24 @@ pub const Macros = struct {
436436
/// Integer promotion described in C11 6.3.1.1.2
437437
fn PromotedIntType(comptime T: type) type {
438438
return switch (T) {
439-
bool, u8, i8, c_short => c_int,
439+
bool, c_short => c_int,
440440
c_ushort => if (@sizeOf(c_ushort) == @sizeOf(c_int)) c_uint else c_int,
441441
c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong => T,
442-
else => if (T == comptime_int) {
443-
@compileError("Cannot promote `" ++ @typeName(T) ++ "`; a fixed-size number type is required");
444-
} else if (@typeInfo(T) == .int) {
445-
@compileError("Cannot promote `" ++ @typeName(T) ++ "`; a C ABI type is required");
446-
} else {
447-
@compileError("Attempted to promote invalid type `" ++ @typeName(T) ++ "`");
442+
else => switch (@typeInfo(T)) {
443+
.comptime_int => @compileError("Cannot promote `" ++ @typeName(T) ++ "`; a fixed-size number type is required"),
444+
// promote to c_int if it can represent all values of T
445+
.int => |int_info| if (int_info.bits < @bitSizeOf(c_int))
446+
c_int
447+
// otherwise, restore the original C type
448+
else if (int_info.bits == @bitSizeOf(c_int))
449+
if (int_info.signedness == .unsigned) c_uint else c_int
450+
else if (int_info.bits <= @bitSizeOf(c_long))
451+
if (int_info.signedness == .unsigned) c_ulong else c_long
452+
else if (int_info.bits <= @bitSizeOf(c_longlong))
453+
if (int_info.signedness == .unsigned) c_ulonglong else c_longlong
454+
else
455+
@compileError("Cannot promote `" ++ @typeName(T) ++ "`; a C ABI type is required"),
456+
else => @compileError("Attempted to promote invalid type `" ++ @typeName(T) ++ "`"),
448457
},
449458
};
450459
}
@@ -533,6 +542,16 @@ test "ArithmeticConversion" {
533542
try Test.checkPromotion(c_uint, c_long, c_long);
534543

535544
try Test.checkPromotion(c_ulong, c_longlong, c_ulonglong);
545+
546+
// stdint.h
547+
try Test.checkPromotion(u8, i8, c_int);
548+
try Test.checkPromotion(u16, i16, c_int);
549+
try Test.checkPromotion(i32, c_int, c_int);
550+
try Test.checkPromotion(u32, c_int, c_uint);
551+
try Test.checkPromotion(i64, c_int, c_long);
552+
try Test.checkPromotion(u64, c_int, c_ulong);
553+
try Test.checkPromotion(isize, c_int, c_long);
554+
try Test.checkPromotion(usize, c_int, c_ulong);
536555
}
537556

538557
pub const MacroArithmetic = struct {

test/c_import/macros.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ test "Macro that uses division operator. Issue #13162" {
167167
true,
168168
),
169169
);
170+
170171
try expectEqual(
171172
@as(c_int, 21),
172173
h.DIVIDE_ARGS(
@@ -175,6 +176,14 @@ test "Macro that uses division operator. Issue #13162" {
175176
),
176177
);
177178

179+
try expectEqual(
180+
@as(c_uint, 21),
181+
h.DIVIDE_ARGS(
182+
@as(u32, 42),
183+
@as(u32, 2),
184+
),
185+
);
186+
178187
try expectEqual(
179188
@as(c_int, 21),
180189
h.DIVIDE_ARGS(

0 commit comments

Comments
 (0)