authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-04 21:42:28+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-04 21:56:54+03:00
log050fef3c236e67cf425331e51063c6194421e8ac
tree3b3d2c04f54d8b9b497161ce91802c69fa53fb79
parent314ce5465dfdc9f4d1e2d178704b47666d541fc4

translate-c: do not try to get rid of do while loop

It might contain breaks and continues. Closes #11994

2 files changed, 63 insertions(+), 11 deletions(-)

src/translate_c.zig+10-9
......@@ -2945,7 +2945,6 @@ fn transDoWhileLoop(
29452945 defer cond_scope.deinit();
29462946 const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used);
29472947 const if_not_break = switch (cond.tag()) {
2948 .false_literal => return transStmt(c, scope, stmt.getBody(), .unused),
29492948 .true_literal => {
29502949 const body_node = try maybeBlockify(c, scope, stmt.getBody());
29512950 return Tag.while_true.create(c.arena, body_node);
......@@ -2953,7 +2952,11 @@ fn transDoWhileLoop(
29532952 else => try Tag.if_not_break.create(c.arena, cond),
29542953 };
29552954
2956 const body_node = if (stmt.getBody().getStmtClass() == .CompoundStmtClass) blk: {
2955 var body_node = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
2956 if (body_node.isNoreturn(true)) {
2957 // The body node ends in a noreturn statement. Simply put it in a while (true)
2958 // in case it contains breaks or continues.
2959 } else if (stmt.getBody().getStmtClass() == .CompoundStmtClass) {
29572960 // there's already a block in C, so we'll append our condition to it.
29582961 // c: do {
29592962 // c: a;
......@@ -2964,12 +2967,10 @@ fn transDoWhileLoop(
29642967 // zig: b;
29652968 // zig: if (!cond) break;
29662969 // zig: }
2967 const node = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
2968 const block = node.castTag(.block).?;
2970 const block = body_node.castTag(.block).?;
29692971 block.data.stmts.len += 1; // This is safe since we reserve one extra space in Scope.Block.complete.
29702972 block.data.stmts[block.data.stmts.len - 1] = if_not_break;
2971 break :blk node;
2972 } else blk: {
2973 } else {
29732974 // the C statement is without a block, so we need to create a block to contain it.
29742975 // c: do
29752976 // c: a;
......@@ -2979,10 +2980,10 @@ fn transDoWhileLoop(
29792980 // zig: if (!cond) break;
29802981 // zig: }
29812982 const statements = try c.arena.alloc(Node, 2);
2982 statements[0] = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
2983 statements[0] = body_node;
29832984 statements[1] = if_not_break;
2984 break :blk try Tag.block.create(c.arena, .{ .label = null, .stmts = statements });
2985 };
2985 body_node = try Tag.block.create(c.arena, .{ .label = null, .stmts = statements });
2986 }
29862987 return Tag.while_true.create(c.arena, body_node);
29872988}
29882989
test/translate_c.zig+53-2
......@@ -6,6 +6,53 @@ const CrossTarget = std.zig.CrossTarget;
66pub fn addCases(cases: *tests.TranslateCContext) void {
77 const default_enum_type = if (builtin.abi == .msvc) "c_int" else "c_uint";
88
9 cases.add("do while with breaks",
10 \\void foo(int a) {
11 \\ do {
12 \\ if (a) break;
13 \\ } while (4);
14 \\ do {
15 \\ if (a) break;
16 \\ } while (0);
17 \\ do {
18 \\ if (a) break;
19 \\ } while (a);
20 \\ do {
21 \\ break;
22 \\ } while (3);
23 \\ do {
24 \\ break;
25 \\ } while (0);
26 \\ do {
27 \\ break;
28 \\ } while (a);
29 \\}
30 , &[_][]const u8{
31 \\pub export fn foo(arg_a: c_int) void {
32 \\ var a = arg_a;
33 \\ while (true) {
34 \\ if (a != 0) break;
35 \\ }
36 \\ while (true) {
37 \\ if (a != 0) break;
38 \\ if (!false) break;
39 \\ }
40 \\ while (true) {
41 \\ if (a != 0) break;
42 \\ if (!(a != 0)) break;
43 \\ }
44 \\ while (true) {
45 \\ break;
46 \\ }
47 \\ while (true) {
48 \\ break;
49 \\ }
50 \\ while (true) {
51 \\ break;
52 \\ }
53 \\}
54 });
55
956 cases.add("variables check for opaque demotion",
1057 \\struct A {
1158 \\ _Atomic int a;
......@@ -441,7 +488,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
441488 \\pub export fn foo() void {
442489 \\ while (false) while (false) {};
443490 \\ while (true) while (false) {};
444 \\ while (true) {}
491 \\ while (true) while (true) {
492 \\ if (!false) break;
493 \\ };
445494 \\}
446495 });
447496
......@@ -3229,7 +3278,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
32293278 \\}
32303279 , &[_][]const u8{
32313280 \\pub fn foo() callconv(.C) void {
3232 \\ if (true) {}
3281 \\ if (true) while (true) {
3282 \\ if (!false) break;
3283 \\ };
32333284 \\}
32343285 });
32353286