| author | |
| committer | |
| log | d98f09e4f67fb2848be6052466db035450326605 |
| tree | 736c6f57967ddaaa9e386026d0114c66c1dba5fd |
| parent | 61bcac108cecba0ab8e1b442bd71c51306c0e9fc |
This prevents inadvertent side-effects when an expression is not evaluated
due to boolean short-circuiting
Fixes #79893 files changed, 49 insertions(+), 29 deletions(-)
src/translate_c.zig+14-19| ... | @@ -1438,30 +1438,25 @@ fn transBinaryOperator( | ... | @@ -1438,30 +1438,25 @@ fn transBinaryOperator( |
| 1438 | switch (op) { | 1438 | switch (op) { |
| 1439 | .Assign => return try transCreateNodeAssign(rp, scope, result_used, stmt.getLHS(), stmt.getRHS()), | 1439 | .Assign => return try transCreateNodeAssign(rp, scope, result_used, stmt.getLHS(), stmt.getRHS()), |
| 1440 | .Comma => { | 1440 | .Comma => { |
| 1441 | const block_scope = try scope.findBlockScope(rp.c); | 1441 | var block_scope = try Scope.Block.init(rp.c, scope, true); |
| 1442 | const expr = block_scope.base.parent == scope; | 1442 | const lparen = try appendToken(rp.c, .LParen, "("); |
| 1443 | const lparen = if (expr) try appendToken(rp.c, .LParen, "(") else undefined; | ||
| 1444 | 1443 | ||
| 1445 | const lhs = try transExpr(rp, &block_scope.base, stmt.getLHS(), .unused, .r_value); | 1444 | const lhs = try transExpr(rp, &block_scope.base, stmt.getLHS(), .unused, .r_value); |
| 1446 | try block_scope.statements.append(lhs); | 1445 | try block_scope.statements.append(lhs); |
| 1447 | 1446 | ||
| 1448 | const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value); | 1447 | const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value); |
| 1449 | if (expr) { | 1448 | _ = try appendToken(rp.c, .Semicolon, ";"); |
| 1450 | _ = try appendToken(rp.c, .Semicolon, ";"); | 1449 | const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs); |
| 1451 | const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs); | 1450 | try block_scope.statements.append(&break_node.base); |
| 1452 | try block_scope.statements.append(&break_node.base); | 1451 | const block_node = try block_scope.complete(rp.c); |
| 1453 | const block_node = try block_scope.complete(rp.c); | 1452 | const rparen = try appendToken(rp.c, .RParen, ")"); |
| 1454 | const rparen = try appendToken(rp.c, .RParen, ")"); | 1453 | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); |
| 1455 | const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression); | 1454 | grouped_expr.* = .{ |
| 1456 | grouped_expr.* = .{ | 1455 | .lparen = lparen, |
| 1457 | .lparen = lparen, | 1456 | .expr = block_node, |
| 1458 | .expr = block_node, | 1457 | .rparen = rparen, |
| 1459 | .rparen = rparen, | 1458 | }; |
| 1460 | }; | 1459 | return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base); |
| 1461 | return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base); | ||
| 1462 | } else { | ||
| 1463 | return maybeSuppressResult(rp, scope, result_used, rhs); | ||
| 1464 | } | ||
| 1465 | }, | 1460 | }, |
| 1466 | .Div => { | 1461 | .Div => { |
| 1467 | if (cIsSignedInteger(qt)) { | 1462 | if (cIsSignedInteger(qt)) { |
test/run_translated_c.zig+13| ... | @@ -909,4 +909,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { | ... | @@ -909,4 +909,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void { |
| 909 | \\ return 1 != 1; | 909 | \\ return 1 != 1; |
| 910 | \\} | 910 | \\} |
| 911 | , ""); | 911 | , ""); |
| 912 | |||
| 913 | cases.add("Comma operator should create new scope; issue #7989", | ||
| 914 | \\#include <stdlib.h> | ||
| 915 | \\#include <stdio.h> | ||
| 916 | \\int main(void) { | ||
| 917 | \\ if (1 || (abort(), 1)) {} | ||
| 918 | \\ if (0 && (1, printf("do not print\n"))) {} | ||
| 919 | \\ int x = 0; | ||
| 920 | \\ x = (x = 3, 4, x + 1); | ||
| 921 | \\ if (x != 4) abort(); | ||
| 922 | \\ return 0; | ||
| 923 | \\} | ||
| 924 | , ""); | ||
| 912 | } | 925 | } |
test/translate_c.zig+22-10| ... | @@ -1723,11 +1723,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1723,11 +1723,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1723 | \\} | 1723 | \\} |
| 1724 | , &[_][]const u8{ | 1724 | , &[_][]const u8{ |
| 1725 | \\pub export fn foo() c_int { | 1725 | \\pub export fn foo() c_int { |
| 1726 | \\ _ = @as(c_int, 2); | 1726 | \\ _ = (blk: { |
| 1727 | \\ _ = @as(c_int, 4); | 1727 | \\ _ = @as(c_int, 2); |
| 1728 | \\ _ = @as(c_int, 2); | 1728 | \\ break :blk @as(c_int, 4); |
| 1729 | \\ _ = @as(c_int, 4); | 1729 | \\ }); |
| 1730 | \\ return @as(c_int, 6); | 1730 | \\ return (blk: { |
| 1731 | \\ _ = (blk_1: { | ||
| 1732 | \\ _ = @as(c_int, 2); | ||
| 1733 | \\ break :blk_1 @as(c_int, 4); | ||
| 1734 | \\ }); | ||
| 1735 | \\ break :blk @as(c_int, 6); | ||
| 1736 | \\ }); | ||
| 1731 | \\} | 1737 | \\} |
| 1732 | }); | 1738 | }); |
| 1733 | 1739 | ||
| ... | @@ -1774,8 +1780,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1774,8 +1780,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1774 | \\ while (true) { | 1780 | \\ while (true) { |
| 1775 | \\ var a_1: c_int = 4; | 1781 | \\ var a_1: c_int = 4; |
| 1776 | \\ a_1 = 9; | 1782 | \\ a_1 = 9; |
| 1777 | \\ _ = @as(c_int, 6); | 1783 | \\ return (blk: { |
| 1778 | \\ return a_1; | 1784 | \\ _ = @as(c_int, 6); |
| 1785 | \\ break :blk a_1; | ||
| 1786 | \\ }); | ||
| 1779 | \\ } | 1787 | \\ } |
| 1780 | \\ while (true) { | 1788 | \\ while (true) { |
| 1781 | \\ var a_1: c_int = 2; | 1789 | \\ var a_1: c_int = 2; |
| ... | @@ -1805,9 +1813,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { | ... | @@ -1805,9 +1813,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1805 | \\ var b: c_int = 4; | 1813 | \\ var b: c_int = 4; |
| 1806 | \\ while ((i + @as(c_int, 2)) != 0) : (i = 2) { | 1814 | \\ while ((i + @as(c_int, 2)) != 0) : (i = 2) { |
| 1807 | \\ var a: c_int = 2; | 1815 | \\ var a: c_int = 2; |
| 1808 | \\ a = 6; | 1816 | \\ _ = (blk: { |
| 1809 | \\ _ = @as(c_int, 5); | 1817 | \\ _ = (blk_1: { |
| 1810 | \\ _ = @as(c_int, 7); | 1818 | \\ a = 6; |
| 1819 | \\ break :blk_1 @as(c_int, 5); | ||
| 1820 | \\ }); | ||
| 1821 | \\ break :blk @as(c_int, 7); | ||
| 1822 | \\ }); | ||
| 1811 | \\ } | 1823 | \\ } |
| 1812 | \\ } | 1824 | \\ } |
| 1813 | \\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 2))); | 1825 | \\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 2))); |