mirror of
https://github.com/ziglang/zig.git
synced 2026-02-20 16:24:51 +00:00
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
This commit is contained in:
parent
61bcac108c
commit
d98f09e4f6
@ -1438,30 +1438,25 @@ fn transBinaryOperator(
|
||||
switch (op) {
|
||||
.Assign => return try transCreateNodeAssign(rp, scope, result_used, stmt.getLHS(), stmt.getRHS()),
|
||||
.Comma => {
|
||||
const block_scope = try scope.findBlockScope(rp.c);
|
||||
const expr = block_scope.base.parent == scope;
|
||||
const lparen = if (expr) try appendToken(rp.c, .LParen, "(") else undefined;
|
||||
var block_scope = try Scope.Block.init(rp.c, scope, true);
|
||||
const lparen = try appendToken(rp.c, .LParen, "(");
|
||||
|
||||
const lhs = try transExpr(rp, &block_scope.base, stmt.getLHS(), .unused, .r_value);
|
||||
try block_scope.statements.append(lhs);
|
||||
|
||||
const rhs = try transExpr(rp, &block_scope.base, stmt.getRHS(), .used, .r_value);
|
||||
if (expr) {
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs);
|
||||
try block_scope.statements.append(&break_node.base);
|
||||
const block_node = try block_scope.complete(rp.c);
|
||||
const rparen = try appendToken(rp.c, .RParen, ")");
|
||||
const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
|
||||
grouped_expr.* = .{
|
||||
.lparen = lparen,
|
||||
.expr = block_node,
|
||||
.rparen = rparen,
|
||||
};
|
||||
return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
|
||||
} else {
|
||||
return maybeSuppressResult(rp, scope, result_used, rhs);
|
||||
}
|
||||
_ = try appendToken(rp.c, .Semicolon, ";");
|
||||
const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs);
|
||||
try block_scope.statements.append(&break_node.base);
|
||||
const block_node = try block_scope.complete(rp.c);
|
||||
const rparen = try appendToken(rp.c, .RParen, ")");
|
||||
const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
|
||||
grouped_expr.* = .{
|
||||
.lparen = lparen,
|
||||
.expr = block_node,
|
||||
.rparen = rparen,
|
||||
};
|
||||
return maybeSuppressResult(rp, scope, result_used, &grouped_expr.base);
|
||||
},
|
||||
.Div => {
|
||||
if (cIsSignedInteger(qt)) {
|
||||
|
||||
@ -909,4 +909,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
|
||||
\\ return 1 != 1;
|
||||
\\}
|
||||
, "");
|
||||
|
||||
cases.add("Comma operator should create new scope; issue #7989",
|
||||
\\#include <stdlib.h>
|
||||
\\#include <stdio.h>
|
||||
\\int main(void) {
|
||||
\\ if (1 || (abort(), 1)) {}
|
||||
\\ if (0 && (1, printf("do not print\n"))) {}
|
||||
\\ int x = 0;
|
||||
\\ x = (x = 3, 4, x + 1);
|
||||
\\ if (x != 4) abort();
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "");
|
||||
}
|
||||
|
||||
@ -1723,11 +1723,17 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\}
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo() c_int {
|
||||
\\ _ = @as(c_int, 2);
|
||||
\\ _ = @as(c_int, 4);
|
||||
\\ _ = @as(c_int, 2);
|
||||
\\ _ = @as(c_int, 4);
|
||||
\\ return @as(c_int, 6);
|
||||
\\ _ = (blk: {
|
||||
\\ _ = @as(c_int, 2);
|
||||
\\ break :blk @as(c_int, 4);
|
||||
\\ });
|
||||
\\ return (blk: {
|
||||
\\ _ = (blk_1: {
|
||||
\\ _ = @as(c_int, 2);
|
||||
\\ break :blk_1 @as(c_int, 4);
|
||||
\\ });
|
||||
\\ break :blk @as(c_int, 6);
|
||||
\\ });
|
||||
\\}
|
||||
});
|
||||
|
||||
@ -1774,8 +1780,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ while (true) {
|
||||
\\ var a_1: c_int = 4;
|
||||
\\ a_1 = 9;
|
||||
\\ _ = @as(c_int, 6);
|
||||
\\ return a_1;
|
||||
\\ return (blk: {
|
||||
\\ _ = @as(c_int, 6);
|
||||
\\ break :blk a_1;
|
||||
\\ });
|
||||
\\ }
|
||||
\\ while (true) {
|
||||
\\ var a_1: c_int = 2;
|
||||
@ -1805,9 +1813,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
\\ var b: c_int = 4;
|
||||
\\ while ((i + @as(c_int, 2)) != 0) : (i = 2) {
|
||||
\\ var a: c_int = 2;
|
||||
\\ a = 6;
|
||||
\\ _ = @as(c_int, 5);
|
||||
\\ _ = @as(c_int, 7);
|
||||
\\ _ = (blk: {
|
||||
\\ _ = (blk_1: {
|
||||
\\ a = 6;
|
||||
\\ break :blk_1 @as(c_int, 5);
|
||||
\\ });
|
||||
\\ break :blk @as(c_int, 7);
|
||||
\\ });
|
||||
\\ }
|
||||
\\ }
|
||||
\\ var i: u8 = @bitCast(u8, @truncate(i8, @as(c_int, 2)));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user