From 5aa993cd617e0ae3cabc9c626e45a748857e2f2a Mon Sep 17 00:00:00 2001 From: Vexu Date: Sun, 8 Mar 2020 11:26:53 +0200 Subject: [PATCH] translate-c fix nested loops without blocks. --- src-self-hosted/translate_c.zig | 51 +++++++++++++-------------------- test/translate_c.zig | 28 ++++++++++++++---- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index d24001cf9..b2eb96f2a 100644 --- a/src-self-hosted/translate_c.zig +++ b/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 => { diff --git a/test/translate_c.zig b/test/translate_c.zig index 3d0843d27..a791d0cca 100644 --- a/test/translate_c.zig +++ b/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",