From b909e2eb374b5b9307b54d356abecebf5458b483 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 29 Jun 2025 01:29:29 -0300 Subject: [PATCH] parser, cgen: fix `static` and `volatile` var deref (fix #24778) (fix #24779) (#24807) --- cmd/tools/vast/vast.v | 2 ++ vlib/v/ast/ast.v | 2 ++ vlib/v/gen/c/assign.v | 10 ++++++-- vlib/v/gen/c/fn.v | 6 +++++ vlib/v/parser/assign.v | 2 ++ vlib/v/tests/defer/defer_static_test.v | 35 ++++++++++++++++++++++++++ 6 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/defer/defer_static_test.v diff --git a/cmd/tools/vast/vast.v b/cmd/tools/vast/vast.v index 120af05ef0..c336dc2f3a 100644 --- a/cmd/tools/vast/vast.v +++ b/cmd/tools/vast/vast.v @@ -956,6 +956,8 @@ fn (t Tree) var(node ast.Var) &Node { obj.add_terse('expr', t.expr(node.expr)) obj.add_terse('is_arg', t.bool_node(node.is_arg)) obj.add_terse('is_mut', t.bool_node(node.is_mut)) + obj.add_terse('is_static', t.bool_node(node.is_static)) + obj.add_terse('is_volatile', t.bool_node(node.is_volatile)) obj.add('is_used', t.bool_node(node.is_used)) obj.add('is_changed', t.bool_node(node.is_changed)) obj.add_terse('ct_type_var', t.enum_node(node.ct_type_var)) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index e696a215ce..ae01e099a4 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -904,6 +904,8 @@ pub: name string share ShareType is_mut bool + is_static bool + is_volatile bool is_autofree_tmp bool is_inherited bool has_inherited bool diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index 9c5f1cde78..daf27b2044 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -179,9 +179,15 @@ fn (mut g Gen) expr_with_opt(expr ast.Expr, expr_typ ast.Type, ret_typ ast.Type) fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { mut node := unsafe { node_ } if node.is_static { - g.write('static ') + is_defer_var := node.left[0] is ast.Ident && node.left[0].name in g.defer_vars + if is_defer_var && node.op == .decl_assign { + return + } + if !is_defer_var { + g.write('static ') + } } - if node.is_volatile { + if node.is_volatile && node.left[0] is ast.Ident && node.left[0].name !in g.defer_vars { g.write('volatile ') } mut return_type := ast.void_type diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index ec7ac511b5..4d7e0ce077 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -444,6 +444,12 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) { } info := var.obj as ast.Var if g.table.sym(info.typ).kind != .function { + if info.is_static { + g.write('static ') + } + if info.is_volatile { + g.write('volatile ') + } g.writeln('${g.styp(info.typ)}${deref} ${c_name(var.name)};') } } diff --git a/vlib/v/parser/assign.v b/vlib/v/parser/assign.v index 7bd0beada1..c6a34d778f 100644 --- a/vlib/v/parser/assign.v +++ b/vlib/v/parser/assign.v @@ -224,6 +224,8 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr) ast.Stmt { expr: if left.len == right.len { right[i] } else { ast.empty_expr } share: share is_mut: lx.is_mut || p.inside_for + is_static: is_static + is_volatile: is_volatile pos: lx.pos is_stack_obj: p.inside_for } diff --git a/vlib/v/tests/defer/defer_static_test.v b/vlib/v/tests/defer/defer_static_test.v new file mode 100644 index 0000000000..0837de5fdc --- /dev/null +++ b/vlib/v/tests/defer/defer_static_test.v @@ -0,0 +1,35 @@ +@[unsafe] +fn g() { + mut static levels := 0 + levels++ + defer { levels-- } +} + +fn f(depth int) { + if depth == 0 { + return + } + unsafe { + mut static levels := 0 + levels++ + defer { levels-- } + if depth == 3 { + assert levels == 1 + } + if depth == 2 { + assert levels == 2 + } + if depth == 1 { + assert levels == 3 + } + println('levels: ${levels} | depth: ${depth}') + } + f(depth - 1) +} + +fn test_main() { + f(3) + f(3) + + unsafe { g() } +}