Commit 51e430fac0

LemonBoy <thatlemon@gmail.com>
2020-01-04 11:06:28
Fix edge case in hex-literal translation
1 parent 6ea1939
Changed files (3)
src-self-hosted/c_tokenizer.zig
@@ -659,6 +659,16 @@ fn next(ctx: *Context, loc: ZigClangSourceLocation, name: []const u8, chars: [*:
                         try failDecl(ctx, loc, name, "macro tokenizing failed: invalid digit '{c}' in octal number", .{c});
                         return error.TokenizingFailed;
                     },
+                    'u', 'U' => {
+                        state = .NumLitIntSuffixU;
+                        result.num_lit_suffix = .U;
+                        result.bytes = chars[begin_index..i.*];
+                    },
+                    'l', 'L' => {
+                        state = .NumLitIntSuffixL;
+                        result.num_lit_suffix = .L;
+                        result.bytes = chars[begin_index..i.*];
+                    },
                     else => {
                         result.bytes = chars[begin_index..i.*];
                         return result;
src-self-hosted/translate_c.zig
@@ -2125,7 +2125,8 @@ fn transForLoop(
         block_scope = try Scope.Block.init(rp.c, scope, null);
         block_scope.?.block_node = try transCreateNodeBlock(rp.c, null);
         loop_scope.parent = &block_scope.?.base;
-        _ = try transStmt(rp, &loop_scope, init, .unused, .r_value);
+        const init_stmt = try transStmt(rp, &loop_scope, init, .unused, .r_value);
+        try block_scope.?.block_node.statements.push(init_stmt);
     }
     var cond_scope = Scope{
         .parent = scope,
@@ -4720,18 +4721,26 @@ fn parseCExpr(c: *Context, it: *ctok.TokenList.Iterator, source_loc: ZigClangSou
 
 fn parseCNumLit(c: *Context, tok: *CToken, source_loc: ZigClangSourceLocation) ParseError!*ast.Node {
     if (tok.id == .NumLitInt) {
-        if (tok.num_lit_suffix == .None) {
-            if (tok.bytes.len > 2 and tok.bytes[0] == '0') {
-                switch (tok.bytes[1]) {
-                    '0'...'7' => {
-                        // octal
-                        return transCreateNodeInt(c, try std.fmt.allocPrint(c.a(), "0o{}", .{tok.bytes}));
-                    },
-                    else => {},
-                }
+        var lit_bytes = tok.bytes;
+
+        if (tok.bytes.len > 2 and tok.bytes[0] == '0') {
+            switch (tok.bytes[1]) {
+                '0'...'7' => {
+                    // Octal
+                    lit_bytes = try std.fmt.allocPrint(c.a(), "0o{}", .{tok.bytes});
+                },
+                'X' => {
+                    // Hexadecimal with capital X, valid in C but not in Zig
+                    lit_bytes = try std.fmt.allocPrint(c.a(), "0x{}", .{tok.bytes[2..]});
+                },
+                else => {},
             }
-            return transCreateNodeInt(c, tok.bytes);
         }
+
+        if (tok.num_lit_suffix == .None) {
+            return transCreateNodeInt(c, lit_bytes);
+        }
+
         const cast_node = try transCreateNodeBuiltinFnCall(c, "@as");
         try cast_node.params.push(try transCreateNodeIdentifier(c, switch (tok.num_lit_suffix) {
             .U => "c_uint",
@@ -4742,7 +4751,7 @@ fn parseCNumLit(c: *Context, tok: *CToken, source_loc: ZigClangSourceLocation) P
             else => unreachable,
         }));
         _ = try appendToken(c, .Comma, ",");
-        try cast_node.params.push(try transCreateNodeInt(c, tok.bytes));
+        try cast_node.params.push(try transCreateNodeInt(c, lit_bytes));
         cast_node.rparen_token = try appendToken(c, .RParen, ")");
         return &cast_node.base;
     } else if (tok.id == .NumLitFloat) {
test/translate_c.zig
@@ -2,6 +2,12 @@ const tests = @import("tests.zig");
 const builtin = @import("builtin");
 
 pub fn addCases(cases: *tests.TranslateCContext) void {
+    cases.add("#define hex literal with capital X",
+        \\#define VAL 0XF00D
+    , &[_][]const u8{
+        \\pub const VAL = 0xF00D;
+    });
+
     cases.add("union initializer",
         \\union { int x; char c[4]; }
         \\  ua = {1},