| author | |
| committer | |
| log | bc90a2a083847e061581ad2420274379878b6137 |
| tree | c3d9ac9ae4eceaa12fe575fff89824135a8c197c |
| parent | 1e6de105c8e9dd3152526c680c33518e2502a31e |
* 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.0p02 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 | 5603 | .FloatLiteral => |suffix| { |
| 5604 | 5604 | if (suffix != .none) lit_bytes = lit_bytes[0 .. lit_bytes.len - 1]; |
| 5605 | 5605 | |
| 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 | 5625 | if (dot_index == 0) { |
| 5608 | 5626 | lit_bytes = try std.fmt.allocPrint(c.arena, "0{s}", .{lit_bytes}); |
| 5609 | 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 | 1137 | \\#define BAR .12345 |
| 1138 | 1138 | \\#define baz 1e1 |
| 1139 | 1139 | \\#define BAZ 42e-3f |
| 1140 | \\#define foobar -73.L | |
| 1140 | 1141 | , &[_][]const u8{ |
| 1141 | 1142 | "pub const foo = @as(f32, 3.14);", |
| 1142 | 1143 | "pub const bar = @as(c_longdouble, 16.0e-2);", |
| ... | ... | @@ -1144,6 +1145,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1144 | 1145 | "pub const BAR = 0.12345;", |
| 1145 | 1146 | "pub const baz = 1e1;", |
| 1146 | 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 | }); |
| 1148 | 1164 | |
| 1149 | 1165 | cases.add("comments", |