zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 2d7b55aa0ac30bd0e85cc43e22ef578c7a0d766c (tree)
parent 135cb529def1d77e2e7e3edb641c37fb0cb47f2e
Author: Matthew Borkowski <matthew.h.borkowski@gmail.com>
Date:   Tue, 19 Oct 2021 03:45:18 -0400

translate_c: prevent a while under an if from stealing the else

Diffstat:
Msrc/translate_c.zig | 32+++++++++++++++++++++++---------
Mtest/run_translated_c.zig | 17+++++++++++++++++
2 files changed, 40 insertions(+), 9 deletions(-)

diff --git a/src/translate_c.zig b/src/translate_c.zig @@ -2808,16 +2808,18 @@ fn maybeBlockify(c: *Context, scope: *Scope, stmt: *const clang.Stmt) TransError .NullStmtClass, .WhileStmtClass, => return transStmt(c, scope, stmt, .unused), - else => { - var block_scope = try Scope.Block.init(c, scope, false); - defer block_scope.deinit(); - const result = try transStmt(c, &block_scope.base, stmt, .unused); - try block_scope.statements.append(result); - return block_scope.complete(c); - }, + else => return blockify(c, scope, stmt), } } +fn blockify(c: *Context, scope: *Scope, stmt: *const clang.Stmt) TransError!Node { + var block_scope = try Scope.Block.init(c, scope, false); + defer block_scope.deinit(); + const result = try transStmt(c, &block_scope.base, stmt, .unused); + try block_scope.statements.append(result); + return block_scope.complete(c); +} + fn transIfStmt( c: *Context, scope: *Scope, @@ -2835,9 +2837,21 @@ fn transIfStmt( const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond()); const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used); - const then_body = try maybeBlockify(c, scope, stmt.getThen()); + const then_stmt = stmt.getThen(); + const else_stmt = stmt.getElse(); + const then_class = then_stmt.getStmtClass(); + // block needed to keep else statement from attaching to inner while + const must_blockify = (else_stmt != null) and switch (then_class) { + .DoStmtClass, .ForStmtClass, .WhileStmtClass => true, + else => false, + }; + + const then_body = if (must_blockify) + try blockify(c, scope, then_stmt) + else + try maybeBlockify(c, scope, then_stmt); - const else_body = if (stmt.getElse()) |expr| + const else_body = if (else_stmt) |expr| try maybeBlockify(c, scope, expr) else null; diff --git a/test/run_translated_c.zig b/test/run_translated_c.zig @@ -1767,4 +1767,21 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { \\ return 0; \\} , ""); + + cases.add("Ensure while loop under an if doesn't steal the else. Issue #9953", + \\#include <stdio.h> + \\void doWork(int id) { } + \\int reallyDelete(int id) { printf("deleted %d\n", id); return 1; } + \\int process(int id, int n, int delete) { + \\ if(!delete) + \\ while(n-- > 0) doWork(id); + \\ else + \\ return reallyDelete(id); + \\ return 0; + \\} + \\int main(void) { + \\ process(99, 3, 0); + \\ return 0; + \\} + , ""); }