authorgravatar for evan@lagerdata.comEvan Haas <evan@lagerdata.com> 2021-02-11 09:43:30-08:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-02-12 01:40:43+02:00
logd98f09e4f67fb2848be6052466db035450326605
tree736c6f57967ddaaa9e386026d0114c66c1dba5fd
parent61bcac108cecba0ab8e1b442bd71c51306c0e9fc

translate-c: comma operator should introduce a new scope

This prevents inadvertent side-effects when an expression is not evaluated due to boolean short-circuiting Fixes #7989

3 files changed, 49 insertions(+), 29 deletions(-)

src/translate_c.zig+14-19
......@@ -1438,30 +1438,25 @@ fn transBinaryOperator(
14381438 switch (op) {
14391439 .Assign => return try transCreateNodeAssign(rp, scope, result_used, stmt.getLHS(), stmt.getRHS()),
14401440 .Comma => {
1441 const block_scope = try scope.findBlockScope(rp.c);
1442 const expr = block_scope.base.parent == scope;
1443 const lparen = if (expr) try appendToken(rp.c, .LParen, "(") else undefined;
1441 var block_scope = try Scope.Block.init(rp.c, scope, true);
1442 const lparen = try appendToken(rp.c, .LParen, "(");
14441443
14451444 const lhs = try transExpr(rp, &block_scope.base, stmt.getLHS(), .unused, .r_value);
14461445 try block_scope.statements.append(lhs);
14471446
14481447 const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value);
1449 if (expr) {
1450 _ = try appendToken(rp.c, .Semicolon, ";");
1451 const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs);
1452 try block_scope.statements.append(&break_node.base);
1453 const block_node = try block_scope.complete(rp.c);
1454 const rparen = try appendToken(rp.c, .RParen, ")");
1455 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
1456 grouped_expr.* = .{
1457 .lparen = lparen,
1458 .expr = block_node,
1459 .rparen = rparen,
1460 };
1461 return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
1462 } else {
1463 return maybeSuppressResult(rp, scope, result_used, rhs);
1464 }
1448 _ = try appendToken(rp.c, .Semicolon, ";");
1449 const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs);
1450 try block_scope.statements.append(&break_node.base);
1451 const block_node = try block_scope.complete(rp.c);
1452 const rparen = try appendToken(rp.c, .RParen, ")");
1453 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
1454 grouped_expr.* = .{
1455 .lparen = lparen,
1456 .expr = block_node,
1457 .rparen = rparen,
1458 };
1459 return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
14651460 },
14661461 .Div => {
14671462 if (cIsSignedInteger(qt)) {
test/run_translated_c.zig+13
......@@ -909,4 +909,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
909909 \\ return 1 != 1;
910910 \\}
911911 , "");
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 , "");
912925}
test/translate_c.zig+22-10
......@@ -1723,11 +1723,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17231723 \\}
17241724 , &[_][]const u8{
17251725 \\pub export fn foo() c_int {
1726 \\ _ = @as(c_int, 2);
1727 \\ _ = @as(c_int, 4);
1728 \\ _ = @as(c_int, 2);
1729 \\ _ = @as(c_int, 4);
1730 \\ return @as(c_int, 6);
1726 \\ _ = (blk: {
1727 \\ _ = @as(c_int, 2);
1728 \\ break :blk @as(c_int, 4);
1729 \\ });
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 \\ });
17311737 \\}
17321738 });
17331739
......@@ -1774,8 +1780,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17741780 \\ while (true) {
17751781 \\ var a_1: c_int = 4;
17761782 \\ a_1 = 9;
1777 \\ _ = @as(c_int, 6);
1778 \\ return a_1;
1783 \\ return (blk: {
1784 \\ _ = @as(c_int, 6);
1785 \\ break :blk a_1;
1786 \\ });
17791787 \\ }
17801788 \\ while (true) {
17811789 \\ var a_1: c_int = 2;
......@@ -1805,9 +1813,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18051813 \\ var b: c_int = 4;
18061814 \\ while ((i + @as(c_int, 2)) != 0) : (i = 2) {
18071815 \\ var a: c_int = 2;
1808 \\ a = 6;
1809 \\ _ = @as(c_int, 5);
1810 \\ _ = @as(c_int, 7);
1816 \\ _ = (blk: {
1817 \\ _ = (blk_1: {
1818 \\ a = 6;
1819 \\ break :blk_1 @as(c_int, 5);
1820 \\ });
1821 \\ break :blk @as(c_int, 7);
1822 \\ });
18111823 \\ }
18121824 \\ }
18131825 \\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 2)));