From 010df176b83db90164aa7eb3f1665d3b29a25c0a Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 21 Apr 2026 15:40:26 +0300 Subject: [PATCH] cgen: fix -(-2) translated into --2 (fixes #26813) --- .gitignore | 2 ++ vlib/v/gen/c/cgen.v | 29 +++++++++++++++++++ .../nested_unary_minus_regression.out | 1 + .../testdata/nested_unary_minus_regression.vv | 4 +++ 4 files changed, 36 insertions(+) create mode 100644 vlib/v/gen/c/testdata/nested_unary_minus_regression.out create mode 100644 vlib/v/gen/c/testdata/nested_unary_minus_regression.vv diff --git a/.gitignore b/.gitignore index 1a88525cd..f2d37c36b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ # unignore checker test files !vlib/v/checker/tests/*.vv !vlib/v/checker/tests/*.out +!vlib/v/gen/c/testdata/nested_unary_minus_regression.vv +!vlib/v/gen/c/testdata/nested_unary_minus_regression.out # unignore vlib/x/markdown !vlib/x/markdown/** diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 80e964c90..b043a49e7 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5834,11 +5834,20 @@ fn (mut g Gen) expr(node_ ast.Expr) { if node.right.is_auto_deref_var() && node.op !in [.amp, .mul, .arrow] { g.write('*') } + // Keep nested unary +/- parenthesized so C does not collapse them into ++/-- + // when the parser has preserved a nested prefix node or folded a signed literal. + needs_nested_prefix_parens := prefix_expr_operand_needs_parens(node) + if needs_nested_prefix_parens { + g.write('(') + } if tmp_var == '' { g.expr(node.right) } else { g.write(tmp_var) } + if needs_nested_prefix_parens { + g.write(')') + } if has_slice_call { g.write(')') } @@ -5936,6 +5945,26 @@ fn (mut g Gen) char_literal(node ast.CharLiteral) { g.write("'${node.val}'") } +fn prefix_expr_operand_needs_parens(node ast.PrefixExpr) bool { + if node.op !in [.plus, .minus] { + return false + } + return match node.right { + ast.PrefixExpr { + true + } + ast.FloatLiteral { + node.right.val.starts_with(node.op.str()) + } + ast.IntegerLiteral { + node.right.val.starts_with(node.op.str()) + } + else { + false + } + } +} + // T.name, typeof(expr).name fn (mut g Gen) type_name(raw_type ast.Type) { typ := g.get_type(raw_type) diff --git a/vlib/v/gen/c/testdata/nested_unary_minus_regression.out b/vlib/v/gen/c/testdata/nested_unary_minus_regression.out new file mode 100644 index 000000000..0cfbf0888 --- /dev/null +++ b/vlib/v/gen/c/testdata/nested_unary_minus_regression.out @@ -0,0 +1 @@ +2 diff --git a/vlib/v/gen/c/testdata/nested_unary_minus_regression.vv b/vlib/v/gen/c/testdata/nested_unary_minus_regression.vv new file mode 100644 index 000000000..2f4591b49 --- /dev/null +++ b/vlib/v/gen/c/testdata/nested_unary_minus_regression.vv @@ -0,0 +1,4 @@ +fn main() { + i := -(-2) + println(i) +} -- 2.39.5