Commit 5aa993cd61

Vexu <git@vexu.eu>
2020-03-08 10:26:53
translate-c fix nested loops without blocks.
1 parent 9e60c89
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -2237,6 +2237,7 @@ fn transWhileLoop(
         .id = .Loop,
     };
     while_node.body = try transStmt(rp, &loop_scope, ZigClangWhileStmt_getBody(stmt), .unused, .r_value);
+    _ = try appendToken(rp.c, .Semicolon, ";");
     return &while_node.base;
 }
 
@@ -2346,8 +2347,10 @@ fn transForLoop(
         try block_scope.?.block_node.statements.push(&while_node.base);
         block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
         return &block_scope.?.block_node.base;
-    } else
+    } else {
+        _ = try appendToken(rp.c, .Semicolon, ";");
         return &while_node.base;
+    }
 }
 
 fn transSwitch(
@@ -5431,6 +5434,8 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             //else
             //    @as(dest, x)
 
+            const lparen = try appendToken(c, .LParen, "(");
+
             const if_1 = try transCreateNodeIf(c);
             const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeInfo");
             const type_of_1 = try transCreateNodeBuiltinFnCall(c, "@TypeOf");
@@ -5492,7 +5497,13 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             as.rparen_token = try appendToken(c, .RParen, ")");
             else_2.body = &as.base;
 
-            return &if_1.base;
+            const group_node = try c.a().create(ast.Node.GroupedExpression);
+            group_node.* = .{
+                .lparen = lparen,
+                .expr = &if_1.base,
+                .rparen = try appendToken(c, .RParen, ")"),
+            };
+            return &group_node.base;
         },
         else => {
             const first_tok = it.list.at(0);
@@ -5545,14 +5556,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
                     );
                     return error.ParseError;
                 }
-                // deref is often used together with casts so we group the lhs expression
-                const group = try c.a().create(ast.Node.GroupedExpression);
-                group.* = .{
-                    .lparen = try appendToken(c, .LParen, "("),
-                    .expr = node,
-                    .rparen = try appendToken(c, .RParen, ")"),
-                };
-                const deref = try transCreateNodePtrDeref(c, &group.base);
+                const deref = try transCreateNodePtrDeref(c, node);
                 node = try transCreateNodeFieldAccess(c, deref, source[name_tok.start..name_tok.end]);
                 continue;
             },
@@ -5596,7 +5600,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             },
             .Ampersand => {
                 op_token = try appendToken(c, .Ampersand, "&");
-                op_id .BitAnd;
+                op_id= .BitAnd;
             },
             .Plus => {
                 op_token = try appendToken(c, .Plus, "+");
@@ -5604,7 +5608,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             },
             .Minus => {
                 op_token = try appendToken(c, .Minus, "-");
-                op_id .Sub;
+                op_id= .Sub;
             },
             .AmpersandAmpersand => {
                 op_token = try appendToken(c, .Keyword_and, "and");
@@ -5676,19 +5680,17 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             },
             .BangEqual => {
                 op_token = try appendToken(c, .BangEqual, "!=");
-                op_id =  .BangEqual;
+                op_id = .BangEqual;
             },
             .EqualEqual => {
                 op_token = try appendToken(c, .EqualEqual, "==");
                 op_id = .EqualEqual;
             },
             .Slash => {
-                // unsigned/float division uses the operator
                 op_id = .Div;
                 op_token = try appendToken(c, .Slash, "/");
             },
             .Percent => {
-                // unsigned/float division uses the operator
                 op_id = .Mod;
                 op_token = try appendToken(c, .Percent, "%");
             },
@@ -5729,25 +5731,12 @@ fn parseCPrefixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
             return &node.base;
         },
         .Asterisk => {
-            // deref is often used together with casts so we group the lhs expression
-            const group = try c.a().create(ast.Node.GroupedExpression);
-            group.* = .{
-                .lparen = try appendToken(c, .LParen, "("),
-                .expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
-                .rparen = try appendToken(c, .RParen, ")"),
-            };
-            return try transCreateNodePtrDeref(c, &group.base);
+            const node = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
+            return try transCreateNodePtrDeref(c, node);
         },
         .Ampersand => {
-            // address of is often used together with casts so we group the rhs expression
             const node = try transCreateNodePrefixOp(c, .AddressOf, .Ampersand, "&");
-            const group = try c.a().create(ast.Node.GroupedExpression);
-            group.* = .{
-                .lparen = try appendToken(c, .LParen, "("),
-                .expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
-                .rparen = try appendToken(c, .RParen, ")"),
-            };
-            node.rhs = &group.base;
+            node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
             return &node.base;
         },
         else => {
test/translate_c.zig
@@ -3,6 +3,22 @@ const std = @import("std");
 const CrossTarget = std.zig.CrossTarget;
 
 pub fn addCases(cases: *tests.TranslateCContext) void {
+    cases.add("nested loops without blocks",
+        \\void foo() {
+        \\    while (0) while (0) {}
+        \\    for (;;) while (0);
+        \\    for (;;) do {} while (0);
+        \\}
+    , &[_][]const u8{
+        \\pub export fn foo() void {
+        \\    while (@as(c_int, 0) != 0) while (@as(c_int, 0) != 0) {};
+        \\    while (true) while (@as(c_int, 0) != 0) {};
+        \\    while (true) while (true) {
+        \\        if (!(@as(c_int, 0) != 0)) break;
+        \\    };
+        \\}
+    });
+
     cases.add("macro comma operator",
         \\#define foo (foo, bar)
         \\#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2))
@@ -14,7 +30,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
     ,
         \\pub inline fn bar(x: var) @TypeOf(baz(1, 2)) {
         \\    return blk: {
-        \\        _ = &(x);
+        \\        _ = &x;
         \\        _ = 3;
         \\        _ = 4 == 4;
         \\        _ = 5 * 6;
@@ -1404,7 +1420,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
     cases.add("macro pointer cast",
         \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
     , &[_][]const u8{
-        \\pub const NRF_GPIO = if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE);
+        \\pub const NRF_GPIO = (if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Pointer) @ptrCast([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeInfo(@TypeOf(NRF_GPIO_BASE)) == .Int) @intToPtr([*c]NRF_GPIO_Type, NRF_GPIO_BASE) else @as([*c]NRF_GPIO_Type, NRF_GPIO_BASE));
     });
 
     cases.add("basic macro function",
@@ -1993,7 +2009,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
     ,
         \\pub const DOT = a.b;
     ,
-        \\pub const ARROW = (a).*.b;
+        \\pub const ARROW = a.*.b;
     });
 
     cases.add("array access",
@@ -2588,11 +2604,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\#define FOO(bar) baz((void *)(baz))
         \\#define BAR (void*) a
     , &[_][]const u8{
-        \\pub inline fn FOO(bar: var) @TypeOf(baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz))) {
-        \\    return baz(if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz));
+        \\pub inline fn FOO(bar: var) @TypeOf(baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)))) {
+        \\    return baz((if (@typeInfo(@TypeOf(baz)) == .Pointer) @ptrCast(*c_void, baz) else if (@typeInfo(@TypeOf(baz)) == .Int) @intToPtr(*c_void, baz) else @as(*c_void, baz)));
         \\}
     ,
-        \\pub const BAR = if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a);
+        \\pub const BAR = (if (@typeInfo(@TypeOf(a)) == .Pointer) @ptrCast(*c_void, a) else if (@typeInfo(@TypeOf(a)) == .Int) @intToPtr(*c_void, a) else @as(*c_void, a));
     });
 
     cases.add("macro conditional operator",