authorgravatar for 94326797+riverbl@users.noreply.github.comriverbl <94326797+riverbl@users.noreply.github.com> 2022-01-14 23:11:20+00:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-01-17 16:49:46+02:00
logaa5514fcf2305233c468b358d22ab171f377aef9
tree7c85e4a710786963c5a05c0f3d62159c832c606b
parent0d0f277954e8809ac537d11ff536639aed8f2724

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

2 files changed, 35 insertions(+), 1 deletions(-)

src/translate_c.zig+19-1
...@@ -5603,7 +5603,25 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {...@@ -5603,7 +5603,25 @@ fn parseCNumLit(c: *Context, m: *MacroCtx) ParseError!Node {
5603 .FloatLiteral => |suffix| {5603 .FloatLiteral => |suffix| {
5604 if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1];5604 if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1];
56055605
5606 if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| {5606 if (lit_bytes.len >= 2 and std.ascii.eqlIgnoreCase(lit_bytes[0..2], "0x")) {
5607 if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| {
5608 if (dot_index == 2) {
5609 lit_bytes = try std.fmt.allocPrint(c.arena, "0x0{s}", .{lit_bytes[2..]});
5610 } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isXDigit(lit_bytes[dot_index + 1])) {
5611 // If the literal lacks a digit after the `.`, we need to
5612 // add one since `0x1.p10` would be invalid syntax in Zig.
5613 lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}0{s}", .{
5614 lit_bytes[2 .. dot_index + 1],
5615 lit_bytes[dot_index + 1 ..],
5616 });
5617 }
5618 }
5619
5620 if (lit_bytes[1] == 'X') {
5621 // Hexadecimal with capital X, valid in C but not in Zig
5622 lit_bytes = try std.fmt.allocPrint(c.arena, "0x{s}", .{lit_bytes[2..]});
5623 }
5624 } else if (mem.indexOfScalar(u8, lit_bytes, '.')) |dot_index| {
5607 if (dot_index == 0) {5625 if (dot_index == 0) {
5608 lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});5626 lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes});
5609 } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isDigit(lit_bytes[dot_index + 1])) {5627 } else if (dot_index + 1 == lit_bytes.len or !std.ascii.isDigit(lit_bytes[dot_index + 1])) {
test/translate_c.zig+16
...@@ -1137,6 +1137,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1137,6 +1137,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1137 \\#define BAR .123451137 \\#define BAR .12345
1138 \\#define baz 1e11138 \\#define baz 1e1
1139 \\#define BAZ 42e-3f1139 \\#define BAZ 42e-3f
1140 \\#define foobar -73.L
1140 , &[_][]const u8{1141 , &[_][]const u8{
1141 "pub const foo = @as(f32, 3.14);",1142 "pub const foo = @as(f32, 3.14);",
1142 "pub const bar = @as(c_longdouble, 16.0e-2);",1143 "pub const bar = @as(c_longdouble, 16.0e-2);",
...@@ -1144,6 +1145,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1144,6 +1145,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1144 "pub const BAR = 0.12345;",1145 "pub const BAR = 0.12345;",
1145 "pub const baz = 1e1;",1146 "pub const baz = 1e1;",
1146 "pub const BAZ = @as(f32, 42e-3);",1147 "pub const BAZ = @as(f32, 42e-3);",
1148 "pub const foobar = -@as(c_longdouble, 73.0);",
1149 });
1150
1151 cases.add("macro defines hexadecimal float",
1152 \\#define FOO 0xf7p38
1153 \\#define BAR -0X8F.BP5F
1154 \\#define FOOBAR 0X0P+0
1155 \\#define BAZ -0x.0a5dp+12
1156 \\#define FOOBAZ 0xfE.P-1l
1157 , &[_][]const u8{
1158 "pub const FOO = 0xf7p38;",
1159 "pub const BAR = -@as(f32, 0x8F.BP5);",
1160 "pub const FOOBAR = 0x0P+0;",
1161 "pub const BAZ = -0x0.0a5dp+12;",
1162 "pub const FOOBAZ = @as(c_longdouble, 0xfE.0P-1);",
1147 });1163 });
11481164
1149 cases.add("comments",1165 cases.add("comments",