From dbdd96f2ee1c4517f819ddfcc4888388b8c36010 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 5 Dec 2023 20:34:37 +0200 Subject: [PATCH] checker, cgen: fix `@[if xyz?] fn init() {}`, add tests (#20096) --- vlib/v/checker/fn.v | 25 +++++++++-------- vlib/v/gen/c/cgen.v | 27 ++++++++++++------- .../init_fn_with_if_attr_defined.c.must_have | 2 ++ .../testdata/init_fn_with_if_attr_defined.out | 2 ++ .../testdata/init_fn_with_if_attr_defined.vv | 10 +++++++ ...it_fn_with_if_attr_not_defined.c.must_have | 1 + .../init_fn_with_if_attr_not_defined.out | 1 + .../init_fn_with_if_attr_not_defined.vv | 10 +++++++ 8 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.c.must_have create mode 100644 vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.out create mode 100644 vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.vv create mode 100644 vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.c.must_have create mode 100644 vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.out create mode 100644 vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.vv diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 334cdc6d1..61eefde13 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -413,20 +413,23 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) { } node.source_file = c.file - if node.name in c.table.fns && node.name != 'main.main' { - mut dep_names := []string{} - for stmt in node.stmts { - dnames := c.table.dependent_names_in_stmt(stmt) - for dname in dnames { - if dname in dep_names { - continue + if node.name in c.table.fns { + if node.name != 'main.main' { + mut dep_names := []string{} + for stmt in node.stmts { + dnames := c.table.dependent_names_in_stmt(stmt) + for dname in dnames { + if dname in dep_names { + continue + } + dep_names << dname } - dep_names << dname + } + if dep_names.len > 0 { + c.table.fns[node.name].dep_names = dep_names } } - if dep_names.len > 0 { - c.table.fns[node.name].dep_names = dep_names - } + c.table.fns[node.name].source_fn = voidptr(node) } // vweb checks diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 671900f6e..4dbe661b2 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5869,14 +5869,14 @@ fn (mut g Gen) write_init_function() { // ignore v.reflection already initialized above continue } - mut is_empty := true + mut const_section_header_shown := false // write globals and consts init later for var_name in g.sorted_global_const_names { if var := g.global_const_defs[var_name] { if var.mod == mod_name && var.init.len > 0 { - if is_empty { - is_empty = false - g.writeln('\t// Initializations for module ${mod_name}') + if !const_section_header_shown { + g.writeln('\t// Initializations of consts for module ${mod_name}') + const_section_header_shown = true } g.writeln(var.init) } @@ -5885,12 +5885,21 @@ fn (mut g Gen) write_init_function() { init_fn_name := '${mod_name}.init' if initfn := g.table.find_fn(init_fn_name) { if initfn.return_type == ast.void_type && initfn.params.len == 0 { - if is_empty { - g.writeln('\t// Initializations for module ${mod_name}') + mut should_be_skipped := false + if initfn.source_fn != unsafe { nil } { + fndecl := unsafe { &ast.FnDecl(initfn.source_fn) } + if fndecl.should_be_skipped { + should_be_skipped = fndecl.should_be_skipped + } + } + if should_be_skipped { + g.writeln('\t// Skipping fn init() for module ${mod_name}') + } else { + g.writeln('\t// Calling fn init() for module ${mod_name}') + mod_c_name := util.no_dots(mod_name) + init_fn_c_name := '${mod_c_name}__init' + g.writeln('\t${init_fn_c_name}();') } - mod_c_name := util.no_dots(mod_name) - init_fn_c_name := '${mod_c_name}__init' - g.writeln('\t${init_fn_c_name}();') } } cleanup_fn_name := '${mod_name}.cleanup' diff --git a/vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.c.must_have b/vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.c.must_have new file mode 100644 index 000000000..d9196d5ce --- /dev/null +++ b/vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.c.must_have @@ -0,0 +1,2 @@ +// Calling fn init() for module main +main__init(); diff --git a/vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.out b/vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.out new file mode 100644 index 000000000..8b8966ecb --- /dev/null +++ b/vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.out @@ -0,0 +1,2 @@ +hi from init +hi from main diff --git a/vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.vv b/vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.vv new file mode 100644 index 000000000..db2d910e3 --- /dev/null +++ b/vlib/v/gen/c/testdata/init_fn_with_if_attr_defined.vv @@ -0,0 +1,10 @@ +// vtest vflags: -d init_on + +@[if init_on ?] +fn init() { + println('hi from init') +} + +fn main() { + println('hi from main') +} diff --git a/vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.c.must_have b/vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.c.must_have new file mode 100644 index 000000000..b898d5cf0 --- /dev/null +++ b/vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.c.must_have @@ -0,0 +1 @@ +// Skipping fn init() for module main diff --git a/vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.out b/vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.out new file mode 100644 index 000000000..d4bf7a8d0 --- /dev/null +++ b/vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.out @@ -0,0 +1 @@ +hi from main diff --git a/vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.vv b/vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.vv new file mode 100644 index 000000000..d5fa28658 --- /dev/null +++ b/vlib/v/gen/c/testdata/init_fn_with_if_attr_not_defined.vv @@ -0,0 +1,10 @@ +// vtest vflags: -d init_is_not_defined + +@[if init_on ?] +fn init() { + println('hi from init') +} + +fn main() { + println('hi from main') +} -- 2.39.5