From aa5514fcf2305233c468b358d22ab171f377aef9 Mon Sep 17 00:00:00 2001 From: riverbl <94326797+riverbl@users.noreply.github.com> Date: Fri, 14 Jan 2022 23:11:20 +0000 Subject: [PATCH] translate-c: Fix issues translating macro define of hex float constant * Fix incorrect result when the first digit after the decimal point is not 0-9 - eg 0x0.ap0 * Fix compiler panic when the number starts with `0X` with a capital `X` - eg 0X0p0 * Fix compiler panic when the number has a decimal point immediately after `0x` - eg 0x.0p0 --- src/translate_c.zig | 20 +++++++++++++++++++- test/translate_c.zig | 16 ++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/translate_c.zig b/src/translate_c.zig index 668d6c7cc4..b8f5116a75 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -5603,7 +5603,25 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node { .FloatLiteral => |suffix| { if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1]; - if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| { + if (lit_bytes.len >= 2 and std.ascii.eqlIgnoreCase(lit_bytes[0..2], "0x")) { + if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| { + if (dot_index == 2) { + lit_bytes = try std.fmt.allocPrint(c.arena, "0x0{s}", .{lit_bytes[2..]}); + } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isXDigit(lit_bytes[dot_index + 1])) { + // If the literal lacks a digit after the `.`, we need to + // add one since `0x1.p10` would be invalid syntax in Zig. + lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}0{s}", .{ + lit_bytes[2 .. dot_index + 1], + lit_bytes[dot_index + 1 ..], + }); + } + } + + if (lit_bytes[1] == 'X') { + // Hexadecimal with capital X, valid in C but not in Zig + lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]}); + } + } else if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| { if (dot_index == 0) { lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes}); } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isDigit(lit_bytes[dot_index + 1])) { diff --git a/test/translate_c.zig b/test/translate_c.zig index dc559c126c..bd83f8034b 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -1137,6 +1137,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\#define BAR .12345 \\#define baz 1e1 \\#define BAZ 42e-3f + \\#define foobar -73.L , &[_][]const u8{ "pub const foo = @as(f32, 3.14);", "pub const bar = @as(c_longdouble, 16.0e-2);", @@ -1144,6 +1145,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void { "pub const BAR = 0.12345;", "pub const baz = 1e1;", "pub const BAZ = @as(f32, 42e-3);", + "pub const foobar = -@as(c_longdouble, 73.0);", + }); + + cases.add("macro defines hexadecimal float", + \\#define FOO 0xf7p38 + \\#define BAR -0X8F.BP5F + \\#define FOOBAR 0X0P+0 + \\#define BAZ -0x.0a5dp+12 + \\#define FOOBAZ 0xfE.P-1l + , &[_][]const u8{ + "pub const FOO = 0xf7p38;", + "pub const BAR = -@as(f32, 0x8F.BP5);", + "pub const FOOBAR = 0x0P+0;", + "pub const BAZ = -0x0.0a5dp+12;", + "pub const FOOBAZ = @as(c_longdouble, 0xfE.0P-1);", }); cases.add("comments",