mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 22:04:21 +00:00
translate_c: prevent a while under an if from stealing the else
This commit is contained in:
parent
135cb529de
commit
2d7b55aa0a
2 changed files with 40 additions and 9 deletions
|
|
@ -2808,16 +2808,18 @@ fn maybeBlockify(c: *Context, scope: *Scope, stmt: *const clang.Stmt) TransError
|
||||||
.NullStmtClass,
|
.NullStmtClass,
|
||||||
.WhileStmtClass,
|
.WhileStmtClass,
|
||||||
=> return transStmt(c, scope, stmt, .unused),
|
=> return transStmt(c, scope, stmt, .unused),
|
||||||
else => {
|
else => return blockify(c, scope, stmt),
|
||||||
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 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(
|
fn transIfStmt(
|
||||||
c: *Context,
|
c: *Context,
|
||||||
scope: *Scope,
|
scope: *Scope,
|
||||||
|
|
@ -2835,9 +2837,21 @@ fn transIfStmt(
|
||||||
const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond());
|
const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond());
|
||||||
const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
|
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)
|
try maybeBlockify(c, scope, expr)
|
||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
|
|
|
||||||
|
|
@ -1767,4 +1767,21 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
|
||||||
\\ return 0;
|
\\ 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;
|
||||||
|
\\}
|
||||||
|
, "");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue