translate-c: do not try to get rid of do while loop
It might contain breaks and continues. Closes #11994
This commit is contained in:
@@ -2945,7 +2945,6 @@ fn transDoWhileLoop(
|
||||
defer cond_scope.deinit();
|
||||
const cond = try transBoolExpr(c, &cond_scope.base, @ptrCast(*const clang.Expr, stmt.getCond()), .used);
|
||||
const if_not_break = switch (cond.tag()) {
|
||||
.false_literal => return transStmt(c, scope, stmt.getBody(), .unused),
|
||||
.true_literal => {
|
||||
const body_node = try maybeBlockify(c, scope, stmt.getBody());
|
||||
return Tag.while_true.create(c.arena, body_node);
|
||||
@@ -2953,7 +2952,11 @@ fn transDoWhileLoop(
|
||||
else => try Tag.if_not_break.create(c.arena, cond),
|
||||
};
|
||||
|
||||
const body_node = if (stmt.getBody().getStmtClass() == .CompoundStmtClass) blk: {
|
||||
var body_node = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
|
||||
if (body_node.isNoreturn(true)) {
|
||||
// The body node ends in a noreturn statement. Simply put it in a while (true)
|
||||
// in case it contains breaks or continues.
|
||||
} else if (stmt.getBody().getStmtClass() == .CompoundStmtClass) {
|
||||
// there's already a block in C, so we'll append our condition to it.
|
||||
// c: do {
|
||||
// c: a;
|
||||
@@ -2964,12 +2967,10 @@ fn transDoWhileLoop(
|
||||
// zig: b;
|
||||
// zig: if (!cond) break;
|
||||
// zig: }
|
||||
const node = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
|
||||
const block = node.castTag(.block).?;
|
||||
const block = body_node.castTag(.block).?;
|
||||
block.data.stmts.len += 1; // This is safe since we reserve one extra space in Scope.Block.complete.
|
||||
block.data.stmts[block.data.stmts.len - 1] = if_not_break;
|
||||
break :blk node;
|
||||
} else blk: {
|
||||
} else {
|
||||
// the C statement is without a block, so we need to create a block to contain it.
|
||||
// c: do
|
||||
// c: a;
|
||||
@@ -2979,10 +2980,10 @@ fn transDoWhileLoop(
|
||||
// zig: if (!cond) break;
|
||||
// zig: }
|
||||
const statements = try c.arena.alloc(Node, 2);
|
||||
statements[0] = try transStmt(c, &loop_scope, stmt.getBody(), .unused);
|
||||
statements[0] = body_node;
|
||||
statements[1] = if_not_break;
|
||||
break :blk try Tag.block.create(c.arena, .{ .label = null, .stmts = statements });
|
||||
};
|
||||
body_node = try Tag.block.create(c.arena, .{ .label = null, .stmts = statements });
|
||||
}
|
||||
return Tag.while_true.create(c.arena, body_node);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,53 @@ const CrossTarget = std.zig.CrossTarget;
|
||||
pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
const default_enum_type = if (builtin.abi == .msvc) "c_int" else "c_uint";
|
||||
|
||||
cases.add("do while with breaks",
|
||||
\\void foo(int a) {
|
||||
\\ do {
|
||||
\\ if (a) break;
|
||||
\\ } while (4);
|
||||
\\ do {
|
||||
\\ if (a) break;
|
||||
\\ } while (0);
|
||||
\\ do {
|
||||
\\ if (a) break;
|
||||
\\ } while (a);
|
||||
\\ do {
|
||||
\\ break;
|
||||
\\ } while (3);
|
||||
\\ do {
|
||||
\\ break;
|
||||
\\ } while (0);
|
||||
\\ do {
|
||||
\\ break;
|
||||
\\ } while (a);
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(arg_a: c_int) void {
|
||||
\\ var a = arg_a;
|
||||
\\ while (true) {
|
||||
\\ if (a != 0) break;
|
||||
\\ }
|
||||
\\ while (true) {
|
||||
\\ if (a != 0) break;
|
||||
\\ if (!false) break;
|
||||
\\ }
|
||||
\\ while (true) {
|
||||
\\ if (a != 0) break;
|
||||
\\ if (!(a != 0)) break;
|
||||
\\ }
|
||||
\\ while (true) {
|
||||
\\ break;
|
||||
\\ }
|
||||
\\ while (true) {
|
||||
\\ break;
|
||||
\\ }
|
||||
\\ while (true) {
|
||||
\\ break;
|
||||
\\ }
|
||||
\\}
|
||||
});
|
||||
|
||||
cases.add("variables check for opaque demotion",
|
||||
\\struct A {
|
||||
\\ _Atomic int a;
|
||||
@@ -441,7 +488,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\pub export fn foo() void {
|
||||
\\ while (false) while (false) {};
|
||||
\\ while (true) while (false) {};
|
||||
\\ while (true) {}
|
||||
\\ while (true) while (true) {
|
||||
\\ if (!false) break;
|
||||
\\ };
|
||||
\\}
|
||||
});
|
||||
|
||||
@@ -3229,7 +3278,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub fn foo() callconv(.C) void {
|
||||
\\ if (true) {}
|
||||
\\ if (true) while (true) {
|
||||
\\ if (!false) break;
|
||||
\\ };
|
||||
\\}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user