Commit 2d7b55aa0a
Changed files (2)
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;
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;
+ \\}
+ , "");
}