From 2d7b55aa0ac30bd0e85cc43e22ef578c7a0d766c Mon Sep 17 00:00:00 2001 From: Matthew Borkowski Date: Tue, 19 Oct 2021 03:45:18 -0400 Subject: [PATCH] translate_c: prevent a while under an if from stealing the else --- src/translate_c.zig | 32 +++++++++++++++++++++++--------- test/run_translated_c.zig | 17 +++++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/translate_c.zig b/src/translate_c.zig index 7247ed50a9..e83755ad47 100644 --- 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 else_body = if (stmt.getElse()) |expr| + const then_body = if (must_blockify) + try blockify(c, scope, then_stmt) + else + try maybeBlockify(c, scope, then_stmt); + + 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 index c222a00eb7..91e6cc9cfd 100644 --- 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 + \\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; + \\} + , ""); }