From 91ade5bf8c5be651d912e43e31670305ffa0beb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=A4schle?= Date: Fri, 6 Aug 2021 04:11:03 +0200 Subject: [PATCH] cgen: fix shared field init (#11061) --- vlib/v/gen/c/cgen.v | 16 ++++++++++++++++ vlib/v/tests/shared_lock_test.v | 25 +++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 71c3db9ad6..154c14a53b 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2004,7 +2004,10 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ } else { g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.mtx = {0}, .val =') } + old_is_shared := g.is_shared + g.is_shared = false g.expr(expr) + g.is_shared = old_is_shared g.writeln('}, sizeof($shared_styp))') return } @@ -5241,7 +5244,11 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { } // User set fields mut initialized := false + mut old_is_shared := g.is_shared for i, field in struct_init.fields { + if !field.typ.has_flag(.shared_f) { + g.is_shared = false + } inited_fields[field.name] = i if sym.kind != .struct_ { field_name := if sym.language == .v { c_name(field.name) } else { field.name } @@ -5273,7 +5280,9 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { } initialized = true } + g.is_shared = old_is_shared } + g.is_shared = old_is_shared // The rest of the fields are zeroed. // `inited_fields` is a list of fields that have been init'ed, they are skipped mut nr_fields := 1 @@ -5284,6 +5293,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { verror('union must not have more than 1 initializer') } if !info.is_union { + old_is_shared2 := g.is_shared mut used_embed_fields := []string{} init_field_names := info.fields.map(it.name) // fields that are initialized but belong to the embedding @@ -5311,10 +5321,14 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { initialized = true } } + g.is_shared = old_is_shared2 } // g.zero_struct_fields(info, inited_fields) // nr_fields = info.fields.len for mut field in info.fields { + if !field.typ.has_flag(.shared_f) { + g.is_shared = false + } if mut sym.info is ast.Struct { mut found_equal_fields := 0 for mut sifield in sym.info.fields { @@ -5391,7 +5405,9 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { g.write(',') } initialized = true + g.is_shared = old_is_shared } + g.is_shared = old_is_shared } if is_multiline { g.indent-- diff --git a/vlib/v/tests/shared_lock_test.v b/vlib/v/tests/shared_lock_test.v index 84177e5b03..3e232c4300 100644 --- a/vlib/v/tests/shared_lock_test.v +++ b/vlib/v/tests/shared_lock_test.v @@ -50,3 +50,28 @@ fn test_shared_lock() { assert x.a == 7 && y.a == 5 } } + +struct App { + id string = 'test' +mut: + app_data shared AppData +} + +fn (mut a App) init_server_direct() { + lock a.app_data { + a.app_data = AppData{} + } +} + +struct AppData { + id string = 'foo' +} + +fn test_shared_field_init() { + mut app1 := App{} + app1.init_server_direct() + id := rlock app1.app_data { + app1.app_data.id + } + assert id == 'foo' +}