translate-c fix nested loops without blocks.

This commit is contained in:
Vexu 2020-03-08 11:26:53 +02:00
parent 9e60c89601
commit 5aa993cd61
No known key found for this signature in database
GPG Key ID: 59AEB8936E16A6AC
2 changed files with 42 additions and 37 deletions

View File

@ -2237,6 +2237,7 @@ fn transWhileLoop(
.id = .Loop, .id = .Loop,
}; };
while_node.body = try transStmt(rp, &loop_scope, ZigClangWhileStmt_getBody(stmt), .unused, .r_value); while_node.body = try transStmt(rp, &loop_scope, ZigClangWhileStmt_getBody(stmt), .unused, .r_value);
_ = try appendToken(rp.c, .Semicolon, ";");
return &while_node.base; return &while_node.base;
} }
@ -2346,8 +2347,10 @@ fn transForLoop(
try block_scope.?.block_node.statements.push(&while_node.base); try block_scope.?.block_node.statements.push(&while_node.base);
block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}"); block_scope.?.block_node.rbrace = try appendToken(rp.c, .RBrace, "}");
return &block_scope.?.block_node.base; return &block_scope.?.block_node.base;
} else } else {
_ = try appendToken(rp.c, .Semicolon, ";");
return &while_node.base; return &while_node.base;
}
} }
fn transSwitch( fn transSwitch(
@ -5431,6 +5434,8 @@ fn parseCPrimaryExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
//else //else
// @as(dest, x) // @as(dest, x)
const lparen = try appendToken(c, .LParen, "(");
const if_1 = try transCreateNodeIf(c); const if_1 = try transCreateNodeIf(c);
const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeInfo"); const type_id_1 = try transCreateNodeBuiltinFnCall(c, "@typeInfo");
const type_of_1 = try transCreateNodeBuiltinFnCall(c, "@TypeOf"); 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, ")"); as.rparen_token = try appendToken(c, .RParen, ")");
else_2.body = &as.base; 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 => { else => {
const first_tok = it.list.at(0); const first_tok = it.list.at(0);
@ -5545,14 +5556,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
); );
return error.ParseError; return error.ParseError;
} }
// deref is often used together with casts so we group the lhs expression const deref = try transCreateNodePtrDeref(c, node);
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);
node = try transCreateNodeFieldAccess(c, deref, source[name_tok.start..name_tok.end]); node = try transCreateNodeFieldAccess(c, deref, source[name_tok.start..name_tok.end]);
continue; continue;
}, },
@ -5596,7 +5600,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
}, },
.Ampersand => { .Ampersand => {
op_token = try appendToken(c, .Ampersand, "&"); op_token = try appendToken(c, .Ampersand, "&");
op_id .BitAnd; op_id= .BitAnd;
}, },
.Plus => { .Plus => {
op_token = try appendToken(c, .Plus, "+"); op_token = try appendToken(c, .Plus, "+");
@ -5604,7 +5608,7 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
}, },
.Minus => { .Minus => {
op_token = try appendToken(c, .Minus, "-"); op_token = try appendToken(c, .Minus, "-");
op_id .Sub; op_id= .Sub;
}, },
.AmpersandAmpersand => { .AmpersandAmpersand => {
op_token = try appendToken(c, .Keyword_and, "and"); op_token = try appendToken(c, .Keyword_and, "and");
@ -5676,19 +5680,17 @@ fn parseCSuffixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
}, },
.BangEqual => { .BangEqual => {
op_token = try appendToken(c, .BangEqual, "!="); op_token = try appendToken(c, .BangEqual, "!=");
op_id = .BangEqual; op_id = .BangEqual;
}, },
.EqualEqual => { .EqualEqual => {
op_token = try appendToken(c, .EqualEqual, "=="); op_token = try appendToken(c, .EqualEqual, "==");
op_id = .EqualEqual; op_id = .EqualEqual;
}, },
.Slash => { .Slash => {
// unsigned/float division uses the operator
op_id = .Div; op_id = .Div;
op_token = try appendToken(c, .Slash, "/"); op_token = try appendToken(c, .Slash, "/");
}, },
.Percent => { .Percent => {
// unsigned/float division uses the operator
op_id = .Mod; op_id = .Mod;
op_token = try appendToken(c, .Percent, "%"); op_token = try appendToken(c, .Percent, "%");
}, },
@ -5729,25 +5731,12 @@ fn parseCPrefixOpExpr(c: *Context, it: *CTokenList.Iterator, source: []const u8,
return &node.base; return &node.base;
}, },
.Asterisk => { .Asterisk => {
// deref is often used together with casts so we group the lhs expression const node = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
const group = try c.a().create(ast.Node.GroupedExpression); return try transCreateNodePtrDeref(c, node);
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);
}, },
.Ampersand => { .Ampersand => {
// address of is often used together with casts so we group the rhs expression
const node = try transCreateNodePrefixOp(c, .AddressOf, .Ampersand, "&"); const node = try transCreateNodePrefixOp(c, .AddressOf, .Ampersand, "&");
const group = try c.a().create(ast.Node.GroupedExpression); node.rhs = try parseCPrefixOpExpr(c, it, source, source_loc, scope);
group.* = .{
.lparen = try appendToken(c, .LParen, "("),
.expr = try parseCPrefixOpExpr(c, it, source, source_loc, scope),
.rparen = try appendToken(c, .RParen, ")"),
};
node.rhs = &group.base;
return &node.base; return &node.base;
}, },
else => { else => {

View File

@ -3,6 +3,22 @@ const std = @import("std");
const CrossTarget = std.zig.CrossTarget; const CrossTarget = std.zig.CrossTarget;
pub fn addCases(cases: *tests.TranslateCContext) void { 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", cases.add("macro comma operator",
\\#define foo (foo, bar) \\#define foo (foo, bar)
\\#define bar(x) (&x, +3, 4 == 4, 5 * 6, baz(1, 2), 2 % 2, baz(1,2)) \\#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)) { \\pub inline fn bar(x: var) @TypeOf(baz(1, 2)) {
\\ return blk: { \\ return blk: {
\\ _ = &(x); \\ _ = &x;
\\ _ = 3; \\ _ = 3;
\\ _ = 4 == 4; \\ _ = 4 == 4;
\\ _ = 5 * 6; \\ _ = 5 * 6;
@ -1404,7 +1420,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("macro pointer cast", cases.add("macro pointer cast",
\\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE) \\#define NRF_GPIO ((NRF_GPIO_Type *) NRF_GPIO_BASE)
, &[_][]const u8{ , &[_][]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", cases.add("basic macro function",
@ -1993,7 +2009,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
, ,
\\pub const DOT = a.b; \\pub const DOT = a.b;
, ,
\\pub const ARROW = (a).*.b; \\pub const ARROW = a.*.b;
}); });
cases.add("array access", cases.add("array access",
@ -2588,11 +2604,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define FOO(bar) baz((void *)(baz)) \\#define FOO(bar) baz((void *)(baz))
\\#define BAR (void*) a \\#define BAR (void*) a
, &[_][]const u8{ , &[_][]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))) { \\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)); \\ 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", cases.add("macro conditional operator",