authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-11 14:32:37-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-03-11 14:32:37-05:00
log4fc6f631e044b5ddfff6c610f04f3619a1bbeb8d
treec692820cc0b740efec91ff7e8f023f44873a4d0a
parentbdb917006c9920f2a0d2091cb0f3d52454e039f0
parenteda1b53723447c0fe0bc15bf29abcee2abe90153
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #8126 from xackus/translate_c_int_literal_promotion

translate-c: promote int literals to bigger types

4 files changed, 178 insertions(+), 49 deletions(-)

lib/std/meta.zig+52
...@@ -1094,6 +1094,58 @@ test "sizeof" {...@@ -1094,6 +1094,58 @@ test "sizeof" {
1094 testing.expect(sizeof(c_void) == 1);1094 testing.expect(sizeof(c_void) == 1);
1095}1095}
10961096
1097pub const CIntLiteralRadix = enum { decimal, octal, hexadecimal };
1098
1099fn PromoteIntLiteralReturnType(comptime SuffixType: type, comptime number: comptime_int, comptime radix: CIntLiteralRadix) type {
1100 const signed_decimal = [_]type{ c_int, c_long, c_longlong };
1101 const signed_oct_hex = [_]type{ c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong };
1102 const unsigned = [_]type{ c_uint, c_ulong, c_ulonglong };
1103
1104 const list: []const type = if (@typeInfo(SuffixType).Int.signedness == .unsigned)
1105 &unsigned
1106 else if (radix == .decimal)
1107 &signed_decimal
1108 else
1109 &signed_oct_hex;
1110
1111 var pos = mem.indexOfScalar(type, list, SuffixType).?;
1112
1113 while (pos < list.len) : (pos += 1) {
1114 if (number >= math.minInt(list[pos]) and number <= math.maxInt(list[pos])) {
1115 return list[pos];
1116 }
1117 }
1118 @compileError("Integer literal is too large");
1119}
1120
1121/// Promote the type of an integer literal until it fits as C would.
1122/// This is for translate-c and is not intended for general use.
1123pub fn promoteIntLiteral(
1124 comptime SuffixType: type,
1125 comptime number: comptime_int,
1126 comptime radix: CIntLiteralRadix,
1127) PromoteIntLiteralReturnType(SuffixType, number, radix) {
1128 return number;
1129}
1130
1131test "promoteIntLiteral" {
1132 const signed_hex = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .hexadecimal);
1133 testing.expectEqual(c_uint, @TypeOf(signed_hex));
1134
1135 if (math.maxInt(c_longlong) == math.maxInt(c_int)) return;
1136
1137 const signed_decimal = promoteIntLiteral(c_int, math.maxInt(c_int) + 1, .decimal);
1138 const unsigned = promoteIntLiteral(c_uint, math.maxInt(c_uint) + 1, .hexadecimal);
1139
1140 if (math.maxInt(c_long) > math.maxInt(c_int)) {
1141 testing.expectEqual(c_long, @TypeOf(signed_decimal));
1142 testing.expectEqual(c_ulong, @TypeOf(unsigned));
1143 } else {
1144 testing.expectEqual(c_longlong, @TypeOf(signed_decimal));
1145 testing.expectEqual(c_ulonglong, @TypeOf(unsigned));
1146 }
1147}
1148
1097/// For a given function type, returns a tuple type which fields will1149/// For a given function type, returns a tuple type which fields will
1098/// correspond to the argument types.1150/// correspond to the argument types.
1099///1151///
src/translate_c.zig+38-10
...@@ -4435,40 +4435,68 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {...@@ -4435,40 +4435,68 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
44354435
4436 switch (m.list[m.i].id) {4436 switch (m.list[m.i].id) {
4437 .IntegerLiteral => |suffix| {4437 .IntegerLiteral => |suffix| {
4438 var radix: []const u8 = "decimal";
4438 if (lit_bytes.len > 2 and lit_bytes[0] == '0') {4439 if (lit_bytes.len > 2 and lit_bytes[0] == '0') {
4439 switch (lit_bytes[1]) {4440 switch (lit_bytes[1]) {
4440 '0'...'7' => {4441 '0'...'7' => {
4441 // Octal4442 // Octal
4442 lit_bytes = try std.fmt.allocPrint(c.arena, "0o{s}", .{lit_bytes});4443 lit_bytes = try std.fmt.allocPrint(c.arena, "0o{s}", .{lit_bytes[1..]});
4444 radix = "octal";
4443 },4445 },
4444 'X' => {4446 'X' => {
4445 // Hexadecimal with capital X, valid in C but not in Zig4447 // Hexadecimal with capital X, valid in C but not in Zig
4446 lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]});4448 lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]});
4449 radix = "hexadecimal";
4450 },
4451 'x' => {
4452 radix = "hexadecimal";
4447 },4453 },
4448 else => {},4454 else => {},
4449 }4455 }
4450 }4456 }
44514457
4452 if (suffix == .none) {
4453 return transCreateNodeNumber(c, lit_bytes, .int);
4454 }
4455
4456 const type_node = try Tag.type.create(c.arena, switch (suffix) {4458 const type_node = try Tag.type.create(c.arena, switch (suffix) {
4459 .none => "c_int",
4457 .u => "c_uint",4460 .u => "c_uint",
4458 .l => "c_long",4461 .l => "c_long",
4459 .lu => "c_ulong",4462 .lu => "c_ulong",
4460 .ll => "c_longlong",4463 .ll => "c_longlong",
4461 .llu => "c_ulonglong",4464 .llu => "c_ulonglong",
4462 else => unreachable,4465 .f => unreachable,
4463 });4466 });
4464 lit_bytes = lit_bytes[0 .. lit_bytes.len - switch (suffix) {4467 lit_bytes = lit_bytes[0 .. lit_bytes.len - switch (suffix) {
4465 .u, .l => @as(u8, 1),4468 .none => @as(u8, 0),
4469 .u, .l => 1,
4466 .lu, .ll => 2,4470 .lu, .ll => 2,
4467 .llu => 3,4471 .llu => 3,
4468 else => unreachable,4472 .f => unreachable,
4469 }];4473 }];
4470 const rhs = try transCreateNodeNumber(c, lit_bytes, .int);4474
4471 return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = rhs });4475 const value = std.fmt.parseInt(i128, lit_bytes, 0) catch math.maxInt(i128);
4476
4477 // make the output less noisy by skipping promoteIntLiteral where
4478 // it's guaranteed to not be required because of C standard type constraints
4479 const guaranteed_to_fit = switch (suffix) {
4480 .none => if (math.cast(i16, value)) |_| true else |_| false,
4481 .u => if (math.cast(u16, value)) |_| true else |_| false,
4482 .l => if (math.cast(i32, value)) |_| true else |_| false,
4483 .lu => if (math.cast(u32, value)) |_| true else |_| false,
4484 .ll => if (math.cast(i64, value)) |_| true else |_| false,
4485 .llu => if (math.cast(u64, value)) |_| true else |_| false,
4486 .f => unreachable,
4487 };
4488
4489 const literal_node = try transCreateNodeNumber(c, lit_bytes, .int);
4490
4491 if (guaranteed_to_fit) {
4492 return Tag.as.create(c.arena, .{ .lhs = type_node, .rhs = literal_node });
4493 } else {
4494 return Tag.std_meta_promoteIntLiteral.create(c.arena, .{
4495 .type = type_node,
4496 .value = literal_node,
4497 .radix = try Tag.enum_literal.create(c.arena, radix),
4498 });
4499 }
4472 },4500 },
4473 .FloatLiteral => |suffix| {4501 .FloatLiteral => |suffix| {
4474 if (lit_bytes[0] == '.')4502 if (lit_bytes[0] == '.')
src/translate_c/ast.zig+29
...@@ -39,6 +39,7 @@ pub const Node = extern union {...@@ -39,6 +39,7 @@ pub const Node = extern union {
39 float_literal,39 float_literal,
40 string_literal,40 string_literal,
41 char_literal,41 char_literal,
42 enum_literal,
42 identifier,43 identifier,
43 @"if",44 @"if",
44 /// if (!operand) break;45 /// if (!operand) break;
...@@ -117,6 +118,7 @@ pub const Node = extern union {...@@ -117,6 +118,7 @@ pub const Node = extern union {
117 /// @intCast(lhs, rhs)118 /// @intCast(lhs, rhs)
118 int_cast,119 int_cast,
119 /// @rem(lhs, rhs)120 /// @rem(lhs, rhs)
121 std_meta_promoteIntLiteral,
120 rem,122 rem,
121 /// @divTrunc(lhs, rhs)123 /// @divTrunc(lhs, rhs)
122 div_trunc,124 div_trunc,
...@@ -312,6 +314,7 @@ pub const Node = extern union {...@@ -312,6 +314,7 @@ pub const Node = extern union {
312 .float_literal,314 .float_literal,
313 .string_literal,315 .string_literal,
314 .char_literal,316 .char_literal,
317 .enum_literal,
315 .identifier,318 .identifier,
316 .warning,319 .warning,
317 .type,320 .type,
...@@ -328,6 +331,7 @@ pub const Node = extern union {...@@ -328,6 +331,7 @@ pub const Node = extern union {
328 .tuple => Payload.TupleInit,331 .tuple => Payload.TupleInit,
329 .container_init => Payload.ContainerInit,332 .container_init => Payload.ContainerInit,
330 .std_meta_cast => Payload.Infix,333 .std_meta_cast => Payload.Infix,
334 .std_meta_promoteIntLiteral => Payload.PromoteIntLiteral,
331 .block => Payload.Block,335 .block => Payload.Block,
332 .c_pointer, .single_pointer => Payload.Pointer,336 .c_pointer, .single_pointer => Payload.Pointer,
333 .array_type => Payload.Array,337 .array_type => Payload.Array,
...@@ -651,6 +655,15 @@ pub const Payload = struct {...@@ -651,6 +655,15 @@ pub const Payload = struct {
651 field_name: []const u8,655 field_name: []const u8,
652 },656 },
653 };657 };
658
659 pub const PromoteIntLiteral = struct {
660 base: Payload,
661 data: struct {
662 value: Node,
663 type: Node,
664 radix: Node,
665 },
666 };
654};667};
655668
656/// Converts the nodes into a Zig ast.669/// Converts the nodes into a Zig ast.
...@@ -821,6 +834,11 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -821,6 +834,11 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
821 const import_node = try renderStdImport(c, "meta", "cast");834 const import_node = try renderStdImport(c, "meta", "cast");
822 return renderCall(c, import_node, &.{ payload.lhs, payload.rhs });835 return renderCall(c, import_node, &.{ payload.lhs, payload.rhs });
823 },836 },
837 .std_meta_promoteIntLiteral => {
838 const payload = node.castTag(.std_meta_promoteIntLiteral).?.data;
839 const import_node = try renderStdImport(c, "meta", "promoteIntLiteral");
840 return renderCall(c, import_node, &.{ payload.type, payload.value, payload.radix });
841 },
824 .std_meta_sizeof => {842 .std_meta_sizeof => {
825 const payload = node.castTag(.std_meta_sizeof).?.data;843 const payload = node.castTag(.std_meta_sizeof).?.data;
826 const import_node = try renderStdImport(c, "meta", "sizeof");844 const import_node = try renderStdImport(c, "meta", "sizeof");
...@@ -988,6 +1006,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {...@@ -988,6 +1006,15 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
988 .data = undefined,1006 .data = undefined,
989 });1007 });
990 },1008 },
1009 .enum_literal => {
1010 const payload = node.castTag(.enum_literal).?.data;
1011 _ = try c.addToken(.period, ".");
1012 return c.addNode(.{
1013 .tag = .enum_literal,
1014 .main_token = try c.addToken(.identifier, payload),
1015 .data = undefined,
1016 });
1017 },
991 .fail_decl => {1018 .fail_decl => {
992 const payload = node.castTag(.fail_decl).?.data;1019 const payload = node.castTag(.fail_decl).?.data;
993 // pub const name = @compileError(msg);1020 // pub const name = @compileError(msg);
...@@ -1982,11 +2009,13 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {...@@ -1982,11 +2009,13 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex {
1982 .typeof,2009 .typeof,
1983 .std_meta_sizeof,2010 .std_meta_sizeof,
1984 .std_meta_cast,2011 .std_meta_cast,
2012 .std_meta_promoteIntLiteral,
1985 .std_mem_zeroinit,2013 .std_mem_zeroinit,
1986 .integer_literal,2014 .integer_literal,
1987 .float_literal,2015 .float_literal,
1988 .string_literal,2016 .string_literal,
1989 .char_literal,2017 .char_literal,
2018 .enum_literal,
1990 .identifier,2019 .identifier,
1991 .field_access,2020 .field_access,
1992 .ptr_cast,2021 .ptr_cast,
test/translate_c.zig+59-39
...@@ -232,12 +232,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -232,12 +232,12 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
232 \\ | (*((unsigned char *)(p) + 1) << 8) \232 \\ | (*((unsigned char *)(p) + 1) << 8) \
233 \\ | (*((unsigned char *)(p) + 2) << 16))233 \\ | (*((unsigned char *)(p) + 2) << 16))
234 , &[_][]const u8{234 , &[_][]const u8{
235 \\pub const FOO = (foo + 2).*;235 \\pub const FOO = (foo + @as(c_int, 2)).*;
236 ,236 ,
237 \\pub const VALUE = ((((1 + (2 * 3)) + (4 * 5)) + 6) << 7) | @boolToInt(8 == 9);237 \\pub const VALUE = ((((@as(c_int, 1) + (@as(c_int, 2) * @as(c_int, 3))) + (@as(c_int, 4) * @as(c_int, 5))) + @as(c_int, 6)) << @as(c_int, 7)) | @boolToInt(@as(c_int, 8) == @as(c_int, 9));
238 ,238 ,
239 \\pub fn _AL_READ3BYTES(p: anytype) callconv(.Inline) @TypeOf((@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + 1).* << 8)) | ((@import("std").meta.cast([*c]u8, p) + 2).* << 16)) {239 \\pub fn _AL_READ3BYTES(p: anytype) callconv(.Inline) @TypeOf((@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16))) {
240 \\ return (@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + 1).* << 8)) | ((@import("std").meta.cast([*c]u8, p) + 2).* << 16);240 \\ return (@import("std").meta.cast([*c]u8, p).* | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 1)).* << @as(c_int, 8))) | ((@import("std").meta.cast([*c]u8, p) + @as(c_int, 2)).* << @as(c_int, 16));
241 \\}241 \\}
242 });242 });
243243
...@@ -312,14 +312,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -312,14 +312,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
312 \\ return type_1;312 \\ return type_1;
313 \\}313 \\}
314 ,314 ,
315 \\pub const LIGHTGRAY = @import("std").mem.zeroInit(CLITERAL(Color), .{ 200, 200, 200, 255 });315 \\pub const LIGHTGRAY = @import("std").mem.zeroInit(CLITERAL(Color), .{ @as(c_int, 200), @as(c_int, 200), @as(c_int, 200), @as(c_int, 255) });
316 ,316 ,
317 \\pub const struct_boom_t = extern struct {317 \\pub const struct_boom_t = extern struct {
318 \\ i1: c_int,318 \\ i1: c_int,
319 \\};319 \\};
320 \\pub const boom_t = struct_boom_t;320 \\pub const boom_t = struct_boom_t;
321 ,321 ,
322 \\pub const FOO = @import("std").mem.zeroInit(boom_t, .{1});322 \\pub const FOO = @import("std").mem.zeroInit(boom_t, .{@as(c_int, 1)});
323 });323 });
324324
325 cases.add("complex switch",325 cases.add("complex switch",
...@@ -343,8 +343,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -343,8 +343,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
343 cases.add("correct semicolon after infixop",343 cases.add("correct semicolon after infixop",
344 \\#define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0)344 \\#define __ferror_unlocked_body(_fp) (((_fp)->_flags & _IO_ERR_SEEN) != 0)
345 , &[_][]const u8{345 , &[_][]const u8{
346 \\pub fn __ferror_unlocked_body(_fp: anytype) callconv(.Inline) @TypeOf((_fp.*._flags & _IO_ERR_SEEN) != 0) {346 \\pub fn __ferror_unlocked_body(_fp: anytype) callconv(.Inline) @TypeOf((_fp.*._flags & _IO_ERR_SEEN) != @as(c_int, 0)) {
347 \\ return (_fp.*._flags & _IO_ERR_SEEN) != 0;347 \\ return (_fp.*._flags & _IO_ERR_SEEN) != @as(c_int, 0);
348 \\}348 \\}
349 });349 });
350350
...@@ -352,11 +352,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -352,11 +352,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
352 \\#define FOO(x) ((x >= 0) + (x >= 0))352 \\#define FOO(x) ((x >= 0) + (x >= 0))
353 \\#define BAR 1 && 2 > 4353 \\#define BAR 1 && 2 > 4
354 , &[_][]const u8{354 , &[_][]const u8{
355 \\pub fn FOO(x: anytype) callconv(.Inline) @TypeOf(@boolToInt(x >= 0) + @boolToInt(x >= 0)) {355 \\pub fn FOO(x: anytype) callconv(.Inline) @TypeOf(@boolToInt(x >= @as(c_int, 0)) + @boolToInt(x >= @as(c_int, 0))) {
356 \\ return @boolToInt(x >= 0) + @boolToInt(x >= 0);356 \\ return @boolToInt(x >= @as(c_int, 0)) + @boolToInt(x >= @as(c_int, 0));
357 \\}357 \\}
358 ,358 ,
359 \\pub const BAR = (1 != 0) and (2 > 4);359 \\pub const BAR = (@as(c_int, 1) != 0) and (@as(c_int, 2) > @as(c_int, 4));
360 });360 });
361361
362 cases.add("struct with aligned fields",362 cases.add("struct with aligned fields",
...@@ -401,15 +401,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -401,15 +401,15 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
401 \\ break :blk bar;401 \\ break :blk bar;
402 \\};402 \\};
403 ,403 ,
404 \\pub fn bar(x: anytype) callconv(.Inline) @TypeOf(baz(1, 2)) {404 \\pub fn bar(x: anytype) callconv(.Inline) @TypeOf(baz(@as(c_int, 1), @as(c_int, 2))) {
405 \\ return blk: {405 \\ return blk: {
406 \\ _ = &x;406 \\ _ = &x;
407 \\ _ = 3;407 \\ _ = @as(c_int, 3);
408 \\ _ = 4 == 4;408 \\ _ = @as(c_int, 4) == @as(c_int, 4);
409 \\ _ = 5 * 6;409 \\ _ = @as(c_int, 5) * @as(c_int, 6);
410 \\ _ = baz(1, 2);410 \\ _ = baz(@as(c_int, 1), @as(c_int, 2));
411 \\ _ = 2 % 2;411 \\ _ = @as(c_int, 2) % @as(c_int, 2);
412 \\ break :blk baz(1, 2);412 \\ break :blk baz(@as(c_int, 1), @as(c_int, 2));
413 \\ };413 \\ };
414 \\}414 \\}
415 });415 });
...@@ -418,9 +418,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -418,9 +418,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
418 \\#define foo 1418 \\#define foo 1
419 \\#define inline 2419 \\#define inline 2
420 , &[_][]const u8{420 , &[_][]const u8{
421 \\pub const foo = 1;421 \\pub const foo = @as(c_int, 1);
422 ,422 ,
423 \\pub const @"inline" = 2;423 \\pub const @"inline" = @as(c_int, 2);
424 });424 });
425425
426 cases.add("macro line continuation",426 cases.add("macro line continuation",
...@@ -507,7 +507,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -507,7 +507,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
507 cases.add("#define hex literal with capital X",507 cases.add("#define hex literal with capital X",
508 \\#define VAL 0XF00D508 \\#define VAL 0XF00D
509 , &[_][]const u8{509 , &[_][]const u8{
510 \\pub const VAL = 0xF00D;510 \\pub const VAL = @import("std").meta.promoteIntLiteral(c_int, 0xF00D, .hexadecimal);
511 });511 });
512512
513 cases.add("anonymous struct & unions",513 cases.add("anonymous struct & unions",
...@@ -878,7 +878,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -878,7 +878,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
878 cases.add("macro with left shift",878 cases.add("macro with left shift",
879 \\#define REDISMODULE_READ (1<<0)879 \\#define REDISMODULE_READ (1<<0)
880 , &[_][]const u8{880 , &[_][]const u8{
881 \\pub const REDISMODULE_READ = 1 << 0;881 \\pub const REDISMODULE_READ = @as(c_int, 1) << @as(c_int, 0);
882 });882 });
883883
884 cases.add("macro with right shift",884 cases.add("macro with right shift",
...@@ -887,7 +887,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -887,7 +887,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
887 , &[_][]const u8{887 , &[_][]const u8{
888 \\pub const FLASH_SIZE = @as(c_ulong, 0x200000);888 \\pub const FLASH_SIZE = @as(c_ulong, 0x200000);
889 ,889 ,
890 \\pub const FLASH_BANK_SIZE = FLASH_SIZE >> 1;890 \\pub const FLASH_BANK_SIZE = FLASH_SIZE >> @as(c_int, 1);
891 });891 });
892892
893 cases.add("double define struct",893 cases.add("double define struct",
...@@ -955,14 +955,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -955,14 +955,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
955 cases.add("#define an unsigned integer literal",955 cases.add("#define an unsigned integer literal",
956 \\#define CHANNEL_COUNT 24956 \\#define CHANNEL_COUNT 24
957 , &[_][]const u8{957 , &[_][]const u8{
958 \\pub const CHANNEL_COUNT = 24;958 \\pub const CHANNEL_COUNT = @as(c_int, 24);
959 });959 });
960960
961 cases.add("#define referencing another #define",961 cases.add("#define referencing another #define",
962 \\#define THING2 THING1962 \\#define THING2 THING1
963 \\#define THING1 1234963 \\#define THING1 1234
964 , &[_][]const u8{964 , &[_][]const u8{
965 \\pub const THING1 = 1234;965 \\pub const THING1 = @as(c_int, 1234);
966 ,966 ,
967 \\pub const THING2 = THING1;967 \\pub const THING2 = THING1;
968 });968 });
...@@ -1008,7 +1008,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1008,7 +1008,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1008 cases.add("macro with parens around negative number",1008 cases.add("macro with parens around negative number",
1009 \\#define LUA_GLOBALSINDEX (-10002)1009 \\#define LUA_GLOBALSINDEX (-10002)
1010 , &[_][]const u8{1010 , &[_][]const u8{
1011 \\pub const LUA_GLOBALSINDEX = -10002;1011 \\pub const LUA_GLOBALSINDEX = -@as(c_int, 10002);
1012 });1012 });
10131013
1014 cases.add(1014 cases.add(
...@@ -1091,8 +1091,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1091,8 +1091,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1091 \\#define foo 1 //foo1091 \\#define foo 1 //foo
1092 \\#define bar /* bar */ 21092 \\#define bar /* bar */ 2
1093 , &[_][]const u8{1093 , &[_][]const u8{
1094 "pub const foo = 1;",1094 "pub const foo = @as(c_int, 1);",
1095 "pub const bar = 2;",1095 "pub const bar = @as(c_int, 2);",
1096 });1096 });
10971097
1098 cases.add("string prefix",1098 cases.add("string prefix",
...@@ -1722,7 +1722,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1722,7 +1722,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1722 cases.add("comment after integer literal",1722 cases.add("comment after integer literal",
1723 \\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */1723 \\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
1724 , &[_][]const u8{1724 , &[_][]const u8{
1725 \\pub const SDL_INIT_VIDEO = 0x00000020;1725 \\pub const SDL_INIT_VIDEO = @as(c_int, 0x00000020);
1726 });1726 });
17271727
1728 cases.add("u integer suffix after hex literal",1728 cases.add("u integer suffix after hex literal",
...@@ -1836,8 +1836,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1836,8 +1836,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1836 , &[_][]const u8{1836 , &[_][]const u8{
1837 \\pub extern var c: c_int;1837 \\pub extern var c: c_int;
1838 ,1838 ,
1839 \\pub fn BASIC(c_1: anytype) callconv(.Inline) @TypeOf(c_1 * 2) {1839 \\pub fn BASIC(c_1: anytype) callconv(.Inline) @TypeOf(c_1 * @as(c_int, 2)) {
1840 \\ return c_1 * 2;1840 \\ return c_1 * @as(c_int, 2);
1841 \\}1841 \\}
1842 ,1842 ,
1843 \\pub fn FOO(L: anytype, b: anytype) callconv(.Inline) @TypeOf(L + b) {1843 \\pub fn FOO(L: anytype, b: anytype) callconv(.Inline) @TypeOf(L + b) {
...@@ -2481,7 +2481,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -2481,7 +2481,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
2481 \\ return array[@intCast(c_uint, index)];2481 \\ return array[@intCast(c_uint, index)];
2482 \\}2482 \\}
2483 ,2483 ,
2484 \\pub const ACCESS = array[2];2484 \\pub const ACCESS = array[@as(c_int, 2)];
2485 });2485 });
24862486
2487 cases.add("cast signed array index to unsigned",2487 cases.add("cast signed array index to unsigned",
...@@ -3097,7 +3097,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3097,7 +3097,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3097 ,3097 ,
3098 \\pub const BAR = @import("std").meta.cast(?*c_void, a);3098 \\pub const BAR = @import("std").meta.cast(?*c_void, a);
3099 ,3099 ,
3100 \\pub const BAZ = @import("std").meta.cast(u32, 2);3100 \\pub const BAZ = @import("std").meta.cast(u32, @as(c_int, 2));
3101 });3101 });
31023102
3103 cases.add("macro with cast to unsigned short, long, and long long",3103 cases.add("macro with cast to unsigned short, long, and long long",
...@@ -3105,9 +3105,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3105,9 +3105,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3105 \\#define CURLAUTH_BASIC ((unsigned long) 1)3105 \\#define CURLAUTH_BASIC ((unsigned long) 1)
3106 \\#define CURLAUTH_BASIC_BUT_ULONGLONG ((unsigned long long) 1)3106 \\#define CURLAUTH_BASIC_BUT_ULONGLONG ((unsigned long long) 1)
3107 , &[_][]const u8{3107 , &[_][]const u8{
3108 \\pub const CURLAUTH_BASIC_BUT_USHORT = @import("std").meta.cast(c_ushort, 1);3108 \\pub const CURLAUTH_BASIC_BUT_USHORT = @import("std").meta.cast(c_ushort, @as(c_int, 1));
3109 \\pub const CURLAUTH_BASIC = @import("std").meta.cast(c_ulong, 1);3109 \\pub const CURLAUTH_BASIC = @import("std").meta.cast(c_ulong, @as(c_int, 1));
3110 \\pub const CURLAUTH_BASIC_BUT_ULONGLONG = @import("std").meta.cast(c_ulonglong, 1);3110 \\pub const CURLAUTH_BASIC_BUT_ULONGLONG = @import("std").meta.cast(c_ulonglong, @as(c_int, 1));
3111 });3111 });
31123112
3113 cases.add("macro conditional operator",3113 cases.add("macro conditional operator",
...@@ -3202,7 +3202,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3202,7 +3202,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3202 \\ bar_1 = 2;3202 \\ bar_1 = 2;
3203 \\}3203 \\}
3204 ,3204 ,
3205 \\pub const bar = 4;3205 \\pub const bar = @as(c_int, 4);
3206 });3206 });
32073207
3208 cases.add("don't export inline functions",3208 cases.add("don't export inline functions",
...@@ -3331,9 +3331,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3331,9 +3331,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3331 \\#define NULL ((void*)0)3331 \\#define NULL ((void*)0)
3332 \\#define FOO ((int)0x8000)3332 \\#define FOO ((int)0x8000)
3333 , &[_][]const u8{3333 , &[_][]const u8{
3334 \\pub const NULL = @import("std").meta.cast(?*c_void, 0);3334 \\pub const NULL = @import("std").meta.cast(?*c_void, @as(c_int, 0));
3335 ,3335 ,
3336 \\pub const FOO = @import("std").meta.cast(c_int, 0x8000);3336 \\pub const FOO = @import("std").meta.cast(c_int, @import("std").meta.promoteIntLiteral(c_int, 0x8000, .hexadecimal));
3337 });3337 });
33383338
3339 if (std.Target.current.abi == .msvc) {3339 if (std.Target.current.abi == .msvc) {
...@@ -3398,4 +3398,24 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3398,4 +3398,24 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3398 \\ unnamed_0: struct_unnamed_2,3398 \\ unnamed_0: struct_unnamed_2,
3399 \\};3399 \\};
3400 });3400 });
3401
3402 cases.add("integer literal promotion",
3403 \\#define GUARANTEED_TO_FIT_1 1024
3404 \\#define GUARANTEED_TO_FIT_2 10241024L
3405 \\#define GUARANTEED_TO_FIT_3 20482048LU
3406 \\#define MAY_NEED_PROMOTION_1 10241024
3407 \\#define MAY_NEED_PROMOTION_2 307230723072L
3408 \\#define MAY_NEED_PROMOTION_3 819281928192LU
3409 \\#define MAY_NEED_PROMOTION_HEX 0x80000000
3410 \\#define MAY_NEED_PROMOTION_OCT 020000000000
3411 , &[_][]const u8{
3412 \\pub const GUARANTEED_TO_FIT_1 = @as(c_int, 1024);
3413 \\pub const GUARANTEED_TO_FIT_2 = @as(c_long, 10241024);
3414 \\pub const GUARANTEED_TO_FIT_3 = @as(c_ulong, 20482048);
3415 \\pub const MAY_NEED_PROMOTION_1 = @import("std").meta.promoteIntLiteral(c_int, 10241024, .decimal);
3416 \\pub const MAY_NEED_PROMOTION_2 = @import("std").meta.promoteIntLiteral(c_long, 307230723072, .decimal);
3417 \\pub const MAY_NEED_PROMOTION_3 = @import("std").meta.promoteIntLiteral(c_ulong, 819281928192, .decimal);
3418 \\pub const MAY_NEED_PROMOTION_HEX = @import("std").meta.promoteIntLiteral(c_int, 0x80000000, .hexadecimal);
3419 \\pub const MAY_NEED_PROMOTION_OCT = @import("std").meta.promoteIntLiteral(c_int, 0o20000000000, .octal);
3420 });
3401}3421}