authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-10-19 03:45:18-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-19 13:48:09-04:00
log2d7b55aa0ac30bd0e85cc43e22ef578c7a0d766c
tree16190c4617d3d8b97c776343a8b7e5eb47195439
parent135cb529def1d77e2e7e3edb641c37fb0cb47f2e

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


2 files changed, 40 insertions(+), 9 deletions(-)

src/translate_c.zig+23-9
......@@ -2808,16 +2808,18 @@ fn maybeBlockify(c: *Context, scope: *Scope, stmt: *const clang.Stmt) TransError
28082808 .NullStmtClass,
28092809 .WhileStmtClass,
28102810 => return transStmt(c, scope, stmt, .unused),
2811 else => {
2812 var block_scope = try Scope.Block.init(c, scope, false);
2813 defer block_scope.deinit();
2814 const result = try transStmt(c, &block_scope.base, stmt, .unused);
2815 try block_scope.statements.append(result);
2816 return block_scope.complete(c);
2817 },
2811 else => return blockify(c, scope, stmt),
28182812 }
28192813}
28202814
2815fn blockify(c: *Context, scope: *Scope, stmt: *const clang.Stmt) TransError!Node {
2816 var block_scope = try Scope.Block.init(c, scope, false);
2817 defer block_scope.deinit();
2818 const result = try transStmt(c, &block_scope.base, stmt, .unused);
2819 try block_scope.statements.append(result);
2820 return block_scope.complete(c);
2821}
2822
28212823fn transIfStmt(
28222824 c: *Context,
28232825 scope: *Scope,
......@@ -2835,9 +2837,21 @@ fn transIfStmt(
28352837 const cond_expr = @ptrCast(*const clang.Expr, stmt.getCond());
28362838 const cond = try transBoolExpr(c, &cond_scope.base, cond_expr, .used);
28372839
2838 const then_body = try maybeBlockify(c, scope, stmt.getThen());
2840 const then_stmt = stmt.getThen();
2841 const else_stmt = stmt.getElse();
2842 const then_class = then_stmt.getStmtClass();
2843 // block needed to keep else statement from attaching to inner while
2844 const must_blockify = (else_stmt != null) and switch (then_class) {
2845 .DoStmtClass, .ForStmtClass, .WhileStmtClass => true,
2846 else => false,
2847 };
2848
2849 const then_body = if (must_blockify)
2850 try blockify(c, scope, then_stmt)
2851 else
2852 try maybeBlockify(c, scope, then_stmt);
28392853
2840 const else_body = if (stmt.getElse()) |expr|
2854 const else_body = if (else_stmt) |expr|
28412855 try maybeBlockify(c, scope, expr)
28422856 else
28432857 null;
test/run_translated_c.zig+17
......@@ -1767,4 +1767,21 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
17671767 \\ return 0;
17681768 \\}
17691769 , "");
1770
1771 cases.add("Ensure while loop under an if doesn't steal the else. Issue #9953",
1772 \\#include <stdio.h>
1773 \\void doWork(int id) { }
1774 \\int reallyDelete(int id) { printf("deleted %d\n", id); return 1; }
1775 \\int process(int id, int n, int delete) {
1776 \\ if(!delete)
1777 \\ while(n-- > 0) doWork(id);
1778 \\ else
1779 \\ return reallyDelete(id);
1780 \\ return 0;
1781 \\}
1782 \\int main(void) {
1783 \\ process(99, 3, 0);
1784 \\ return 0;
1785 \\}
1786 , "");
17701787}