From 193a99d1e75f7603771fbe4b330a1e0c1d9ff444 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 3 Jun 2024 17:19:59 +0300 Subject: [PATCH] all: @[freed] attribute for assign statements --- vlib/v/ast/ast.v | 1 + vlib/v/checker/assign.v | 5 +++++ vlib/v/checker/checker.v | 1 + vlib/v/checker/errors.v | 4 ++++ vlib/v/fmt/fmt.v | 3 +++ vlib/v/fmt/tests/stmt_attr_keep.vv | 7 +++++++ vlib/v/parser/assign.v | 9 +++++++++ 7 files changed, 30 insertions(+) create mode 100644 vlib/v/fmt/tests/stmt_attr_keep.vv diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index ac2f6df04..27308b32a 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1312,6 +1312,7 @@ pub mut: is_volatile bool // for disabling variable access optimisations (needed for hardware drivers) is_simple bool // `x+=2` in `for x:=1; ; x+=2` has_cross_var bool + attr Attr } // `expr as Ident` diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 9b17a7f40..ee8741935 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -8,6 +8,11 @@ import v.ast fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { prev_inside_assign := c.inside_assign c.inside_assign = true + if node.attr.name != '' { + c.assign_stmt_attr = node.attr.name + } else { + c.assign_stmt_attr = '' + } c.expected_type = ast.none_type // TODO: a hack to make `x := if ... work` defer { c.expected_type = ast.void_type diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 2b06d5118..40f983ae9 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -135,6 +135,7 @@ mut: orm_table_fields map[string][]ast.StructField // known table structs // v_current_commit_hash string // same as old C.V_CURRENT_COMMIT_HASH + assign_stmt_attr string // for `x := [1,2,3] @[freed]` } pub fn new_checker(table &ast.Table, pref_ &pref.Preferences) &Checker { diff --git a/vlib/v/checker/errors.v b/vlib/v/checker/errors.v index e3305c15c..c5b9bf9da 100644 --- a/vlib/v/checker/errors.v +++ b/vlib/v/checker/errors.v @@ -33,6 +33,10 @@ fn (mut c Checker) warn(s string, pos token.Pos) { } fn (mut c Checker) warn_alloc(s string, pos token.Pos) { + if c.assign_stmt_attr == 'freed' { + return + } + if !c.is_builtin_mod && c.mod !in ['strings', 'math', 'math.bits', 'builtin', 'strconv'] { c.warn('allocation (${s})', pos) } diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 8c48b6a0f..e553382e4 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -879,6 +879,9 @@ pub fn (mut f Fmt) assign_stmt(node ast.AssignStmt) { f.write(', ') } } + if node.attr.name != '' { + f.write(' @[${node.attr.name}]') + } f.comments(node.end_comments, has_nl: false, same_line: true, level: .keep) if !f.single_line_if { f.writeln('') diff --git a/vlib/v/fmt/tests/stmt_attr_keep.vv b/vlib/v/fmt/tests/stmt_attr_keep.vv new file mode 100644 index 000000000..68c93bdab --- /dev/null +++ b/vlib/v/fmt/tests/stmt_attr_keep.vv @@ -0,0 +1,7 @@ +fn foo() { + x := [1, 2, 3] @[freed] + unsafe { + x.free() + } + println('x is freed') +} diff --git a/vlib/v/parser/assign.v b/vlib/v/parser/assign.v index d5f52fc5e..81c747cbe 100644 --- a/vlib/v/parser/assign.v +++ b/vlib/v/parser/assign.v @@ -285,6 +285,14 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr) ast.Stmt { } } } + mut attr := ast.Attr{} + // This assign stmt has an attribute e.g. `x := [1,2,3] @[freed]` + if p.tok.kind == .at && p.tok.line_nr == p.prev_tok.line_nr { + p.check(.at) + p.check(.lsbr) + attr = p.parse_attr(true) + p.check(.rsbr) + } pos.update_last_line(p.prev_tok.line_nr) p.expr_mod = '' return ast.AssignStmt{ @@ -297,5 +305,6 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr) ast.Stmt { is_simple: p.inside_for && p.tok.kind == .lcbr is_static: is_static is_volatile: is_volatile + attr: attr } } -- 2.39.5