authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-18 21:34:31+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-18 21:34:31+02:00
logdf5a8120df640de900667624ad8390394f99521f
tree0782386cabd0941025d722e462b3ff86001fc96f
parent7ca53bdfaab59e61c38d0bedb6b16739904f7519
signature Commit is signed but in an unrecognized format.

translate-c: small miscellaneous improvements


3 files changed, 95 insertions(+), 34 deletions(-)

src/translate_c.zig+24-14
...@@ -1219,8 +1219,10 @@ fn transCompoundStmtInline(...@@ -1219,8 +1219,10 @@ fn transCompoundStmtInline(
1219 const end_it = stmt.body_end();1219 const end_it = stmt.body_end();
1220 while (it != end_it) : (it += 1) {1220 while (it != end_it) : (it += 1) {
1221 const result = try transStmt(c, &block.base, it[0], .unused);1221 const result = try transStmt(c, &block.base, it[0], .unused);
1222 if (result.tag() == .declaration) continue;1222 switch (result.tag()) {
1223 try block.statements.append(result);1223 .declaration, .empty_block => {},
1224 else => try block.statements.append(result),
1225 }
1224 }1226 }
1225}1227}
12261228
...@@ -1395,6 +1397,10 @@ fn transImplicitCastExpr(...@@ -1395,6 +1397,10 @@ fn transImplicitCastExpr(
1395 .BuiltinFnToFnPtr => {1397 .BuiltinFnToFnPtr => {
1396 return transExpr(c, scope, sub_expr, result_used);1398 return transExpr(c, scope, sub_expr, result_used);
1397 },1399 },
1400 .ToVoid => {
1401 // Should only appear in the rhs and lhs of a ConditionalOperator
1402 return transExpr(c, scope, sub_expr, .unused);
1403 },
1398 else => |kind| return fail(1404 else => |kind| return fail(
1399 c,1405 c,
1400 error.UnsupportedTranslation,1406 error.UnsupportedTranslation,
...@@ -2032,10 +2038,8 @@ fn transZeroInitExpr(...@@ -2032,10 +2038,8 @@ fn transZeroInitExpr(
2032 typedef_decl.getUnderlyingType().getTypePtr(),2038 typedef_decl.getUnderlyingType().getTypePtr(),
2033 );2039 );
2034 },2040 },
2035 else => {},2041 else => return Tag.std_mem_zeroes.create(c.arena, try transType(c, scope, ty, source_loc)),
2036 }2042 }
2037
2038 return fail(c, error.UnsupportedType, source_loc, "type does not have an implicit init value", .{});
2039}2043}
20402044
2041fn transImplicitValueInitExpr(2045fn transImplicitValueInitExpr(
...@@ -2118,7 +2122,7 @@ fn transDoWhileLoop(...@@ -2118,7 +2122,7 @@ fn transDoWhileLoop(
2118 defer cond_scope.deinit();2122 defer cond_scope.deinit();
2119 const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used);2123 const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used);
2120 const if_not_break = switch (cond.tag()) {2124 const if_not_break = switch (cond.tag()) {
2121 .false_literal => Tag.@"break".init(),2125 .false_literal => return transStmt(c, scope, stmt.getBody(), .unused),
2122 .true_literal => {2126 .true_literal => {
2123 const body_node = try transStmt(c, scope, stmt.getBody(), .unused);2127 const body_node = try transStmt(c, scope, stmt.getBody(), .unused);
2124 return Tag.while_true.create(c.arena, body_node);2128 return Tag.while_true.create(c.arena, body_node);
...@@ -2396,8 +2400,10 @@ fn transSwitchProngStmtInline(...@@ -2396,8 +2400,10 @@ fn transSwitchProngStmtInline(
2396 },2400 },
2397 else => {2401 else => {
2398 const result = try transStmt(c, &block.base, it[0], .unused);2402 const result = try transStmt(c, &block.base, it[0], .unused);
2399 if (result.tag() == .declaration) continue;2403 switch (result.tag()) {
2400 try block.statements.append(result);2404 .declaration, .empty_block => {},
2405 else => try block.statements.append(result),
2406 }
2401 },2407 },
2402 }2408 }
2403 }2409 }
...@@ -2479,8 +2485,10 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:...@@ -2479,8 +2485,10 @@ fn transStmtExpr(c: *Context, scope: *Scope, stmt: *const clang.StmtExpr, used:
2479 const end_it = comp.body_end();2485 const end_it = comp.body_end();
2480 while (it != end_it - 1) : (it += 1) {2486 while (it != end_it - 1) : (it += 1) {
2481 const result = try transStmt(c, &block_scope.base, it[0], .unused);2487 const result = try transStmt(c, &block_scope.base, it[0], .unused);
2482 if (result.tag() == .declaration) continue;2488 switch (result.tag()) {
2483 try block_scope.statements.append(result);2489 .declaration, .empty_block => {},
2490 else => try block_scope.statements.append(result),
2491 }
2484 }2492 }
2485 const break_node = try Tag.break_val.create(c.arena, .{2493 const break_node = try Tag.break_val.create(c.arena, .{
2486 .label = block_scope.label,2494 .label = block_scope.label,
...@@ -3126,12 +3134,12 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi...@@ -3126,12 +3134,12 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi
31263134
3127 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);3135 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
31283136
3129 var then_body = try transExpr(c, scope, true_expr, .used);3137 var then_body = try transExpr(c, scope, true_expr, used);
3130 if (!res_is_bool and isBoolRes(then_body)) {3138 if (!res_is_bool and isBoolRes(then_body)) {
3131 then_body = try Tag.bool_to_int.create(c.arena, then_body);3139 then_body = try Tag.bool_to_int.create(c.arena, then_body);
3132 }3140 }
31333141
3134 var else_body = try transExpr(c, scope, false_expr, .used);3142 var else_body = try transExpr(c, scope, false_expr, used);
3135 if (!res_is_bool and isBoolRes(else_body)) {3143 if (!res_is_bool and isBoolRes(else_body)) {
3136 else_body = try Tag.bool_to_int.create(c.arena, else_body);3144 else_body = try Tag.bool_to_int.create(c.arena, else_body);
3137 }3145 }
...@@ -3141,7 +3149,8 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi...@@ -3141,7 +3149,8 @@ fn transConditionalOperator(c: *Context, scope: *Scope, stmt: *const clang.Condi
3141 .then = then_body,3149 .then = then_body,
3142 .@"else" = else_body,3150 .@"else" = else_body,
3143 });3151 });
3144 return maybeSuppressResult(c, scope, used, if_node);3152 // Clang inserts ImplicitCast(ToVoid)'s to both rhs and lhs so we don't need to supress the result here.
3153 return if_node;
3145}3154}
31463155
3147fn maybeSuppressResult(3156fn maybeSuppressResult(
...@@ -4794,7 +4803,8 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {...@@ -4794,7 +4803,8 @@ fn parseCMulExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!Node {
4794 while (true) {4803 while (true) {
4795 switch (m.next().?) {4804 switch (m.next().?) {
4796 .Asterisk => {4805 .Asterisk => {
4797 if (m.peek().? == .RParen) {4806 const next = m.peek().?;
4807 if (next == .RParen or next == .Nl or next == .Eof) {
4798 // type *)4808 // type *)
47994809
4800 // last token of `node`4810 // last token of `node`
src/translate_c/ast.zig+12-7
...@@ -1891,30 +1891,35 @@ fn addSemicolonIfNeeded(c: *Context, node: Node) !void {...@@ -1891,30 +1891,35 @@ fn addSemicolonIfNeeded(c: *Context, node: Node) !void {
1891 .var_decl, .var_simple, .arg_redecl, .alias, .enum_redecl, .block, .empty_block, .block_single, .@"switch" => {},1891 .var_decl, .var_simple, .arg_redecl, .alias, .enum_redecl, .block, .empty_block, .block_single, .@"switch" => {},
1892 .while_true => {1892 .while_true => {
1893 const payload = node.castTag(.while_true).?.data;1893 const payload = node.castTag(.while_true).?.data;
1894 return addSemicolonIfNotBlock(c, payload);1894 return addSemicolonIfNotBlock(c, payload, .yes_if);
1895 },1895 },
1896 .@"while" => {1896 .@"while" => {
1897 const payload = node.castTag(.@"while").?.data;1897 const payload = node.castTag(.@"while").?.data;
1898 return addSemicolonIfNotBlock(c, payload.body);1898 return addSemicolonIfNotBlock(c, payload.body, .yes_if);
1899 },1899 },
1900 .@"if" => {1900 .@"if" => {
1901 const payload = node.castTag(.@"if").?.data;1901 const payload = node.castTag(.@"if").?.data;
1902 if (payload.@"else") |some|1902 if (payload.@"else") |some|
1903 return addSemicolonIfNotBlock(c, some);1903 return addSemicolonIfNotBlock(c, some, .no_if);
1904 return addSemicolonIfNotBlock(c, payload.then);1904 return addSemicolonIfNotBlock(c, payload.then, .no_if);
1905 },1905 },
1906 else => _ = try c.addToken(.semicolon, ";"),1906 else => _ = try c.addToken(.semicolon, ";"),
1907 }1907 }
1908}1908}
19091909
1910fn addSemicolonIfNotBlock(c: *Context, node: Node) !void {1910fn addSemicolonIfNotBlock(c: *Context, node: Node, if_needs_semicolon: enum{ yes_if, no_if}) !void {
1911 switch (node.tag()) {1911 switch (node.tag()) {
1912 .block, .empty_block, .block_single => {},1912 .block, .empty_block, .block_single => {},
1913 .@"if" => {1913 .@"if" => {
1914 if (if_needs_semicolon == .yes_if) {
1915 _ = try c.addToken(.semicolon, ";");
1916 return;
1917 }
1918
1914 const payload = node.castTag(.@"if").?.data;1919 const payload = node.castTag(.@"if").?.data;
1915 if (payload.@"else") |some|1920 if (payload.@"else") |some|
1916 return addSemicolonIfNotBlock(c, some);1921 return addSemicolonIfNotBlock(c, some, .no_if);
1917 return addSemicolonIfNotBlock(c, payload.then);1922 return addSemicolonIfNotBlock(c, payload.then, .no_if);
1918 },1923 },
1919 else => _ = try c.addToken(.semicolon, ";"),1924 else => _ = try c.addToken(.semicolon, ";"),
1920 }1925 }
test/translate_c.zig+59-13
...@@ -3,6 +3,62 @@ const std = @import("std");...@@ -3,6 +3,62 @@ const std = @import("std");
3const CrossTarget = std.zig.CrossTarget;3const CrossTarget = std.zig.CrossTarget;
44
5pub fn addCases(cases: *tests.TranslateCContext) void {5pub fn addCases(cases: *tests.TranslateCContext) void {
6 cases.add("if as while stmt has semicolon",
7 \\void foo() {
8 \\ while (1) if (1) {
9 \\ int a = 1;
10 \\ } else {
11 \\ int b = 2;
12 \\ }
13 \\}
14 , &[_][]const u8{
15 \\pub export fn foo() void {
16 \\ while (true) if (true) {
17 \\ var a: c_int = 1;
18 \\ } else {
19 \\ var b: c_int = 2;
20 \\ };
21 \\}
22 });
23
24 cases.add("conditional operator cast to void",
25 \\int bar();
26 \\void foo() {
27 \\ int a;
28 \\ a ? a = 2 : bar();
29 \\}
30 , &[_][]const u8{
31 \\pub extern fn bar(...) c_int;
32 \\pub export fn foo() void {
33 \\ var a: c_int = undefined;
34 \\ if (a != 0) a = 2 else _ = bar();
35 \\}
36 });
37
38 cases.add("struct in struct init to zero",
39 \\struct Foo {
40 \\ int a;
41 \\ struct Bar {
42 \\ int a;
43 \\ } b;
44 \\} a = {};
45 \\#define PTR void *
46 , &[_][]const u8{
47 \\pub const struct_Bar = extern struct {
48 \\ a: c_int,
49 \\};
50 \\pub const struct_Foo = extern struct {
51 \\ a: c_int,
52 \\ b: struct_Bar,
53 \\};
54 \\pub export var a: struct_Foo = struct_Foo{
55 \\ .a = 0,
56 \\ .b = @import("std").mem.zeroes(struct_Bar),
57 \\};
58 ,
59 \\pub const PTR = ?*c_void;
60 });
61
6 cases.add("scoped enum",62 cases.add("scoped enum",
7 \\void foo() {63 \\void foo() {
8 \\ enum Foo {64 \\ enum Foo {
...@@ -330,9 +386,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -330,9 +386,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
330 \\pub export fn foo() void {386 \\pub export fn foo() void {
331 \\ while (false) while (false) {};387 \\ while (false) while (false) {};
332 \\ while (true) while (false) {};388 \\ while (true) while (false) {};
333 \\ while (true) while (true) {389 \\ while (true) {}
334 \\ break;
335 \\ };
336 \\}390 \\}
337 });391 });
338392
...@@ -1044,13 +1098,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1044,13 +1098,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1044 \\ ;;;;;1098 \\ ;;;;;
1045 \\}1099 \\}
1046 , &[_][]const u8{1100 , &[_][]const u8{
1047 \\pub export fn foo() void {1101 \\pub export fn foo() void {}
1048 \\ {}
1049 \\ {}
1050 \\ {}
1051 \\ {}
1052 \\ {}
1053 \\}
1054 });1102 });
10551103
1056 if (std.Target.current.os.tag != .windows) {1104 if (std.Target.current.os.tag != .windows) {
...@@ -3050,9 +3098,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -3050,9 +3098,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
3050 \\}3098 \\}
3051 , &[_][]const u8{3099 , &[_][]const u8{
3052 \\pub fn foo() callconv(.C) void {3100 \\pub fn foo() callconv(.C) void {
3053 \\ if (true) while (true) {3101 \\ if (true) {}
3054 \\ break;
3055 \\ };
3056 \\}3102 \\}
3057 });3103 });
30583104