From fbd7665360d259434f378f68cb2680b17d6cab57 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 30 Jun 2022 17:40:00 -0700 Subject: compiler: use correct init order for multi-value initialization Use the correct initialization order for var a = c var b, c = x.(bool) The global c is initialized by the preinit of b, but were missing a dependency of c on b, so a would be initialized to the zero value of c rather than the correct value. Simply adding the dependency of c on b didn't work because the preinit of b refers to c, so that appeared circular. So this patch changes the init order to skip dependencies that only appear on the left hand side of assignments in preinit blocks. Doing that didn't work because the write barrier pass can transform "a = b" into code like "gcWriteBarrier(&a, b)" that is not obviously a simple assigment. So this patch moves the collection of dependencies to just after lowering, before the write barriers are inserted. Making those changes permit relaxing the requirement that we don't warn about self-dependency in preinit blocks, so now we correctly warn for var a, b any = b.(bool) The test case is https://go.dev/cl/415238. Fixes golang/go#53619 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/415594 --- gcc/go/gofrontend/parse.cc | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'gcc/go/gofrontend/parse.cc') diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index e388261..a3c6f63 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -1977,7 +1977,11 @@ Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type, else if (!val_no->is_sink()) { if (val_no->is_variable()) - val_no->var_value()->add_preinit_statement(this->gogo_, s); + { + val_no->var_value()->add_preinit_statement(this->gogo_, s); + if (no->is_variable()) + this->gogo_->record_var_depends_on(no->var_value(), val_no); + } } else if (!no->is_sink()) { @@ -2044,7 +2048,11 @@ Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type, else if (!val_no->is_sink()) { if (val_no->is_variable()) - val_no->var_value()->add_preinit_statement(this->gogo_, s); + { + val_no->var_value()->add_preinit_statement(this->gogo_, s); + if (no->is_variable()) + this->gogo_->record_var_depends_on(no->var_value(), val_no); + } } else if (!no->is_sink()) { @@ -2110,7 +2118,11 @@ Parse::init_vars_from_type_guard(const Typed_identifier_list* vars, else if (!val_no->is_sink()) { if (val_no->is_variable()) - val_no->var_value()->add_preinit_statement(this->gogo_, s); + { + val_no->var_value()->add_preinit_statement(this->gogo_, s); + if (no->is_variable()) + this->gogo_->record_var_depends_on(no->var_value(), val_no); + } } else if (!no->is_sink()) { -- cgit v1.1