From: Ian Lance Taylor Date: Wed, 22 Dec 2010 23:09:40 +0000 (+0000) Subject: Correctly handle tuple assignment to _ at global scope. X-Git-Tag: releases/gcc-4.6.0~1653 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8332d80edb206e7de917f8a9f01ab6eec3ce8231;p=thirdparty%2Fgcc.git Correctly handle tuple assignment to _ at global scope. From-SVN: r168184 --- diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index a0d87dc8c6a8..f4b01be8c934 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -1654,8 +1654,18 @@ Parse::init_vars_from_map(const Typed_identifier_list* vars, Type* type, if (!this->gogo_->in_global_scope()) this->gogo_->add_statement(s); - else + else if (!val_no->is_sink()) val_no->var_value()->add_preinit_statement(s); + else if (!no->is_sink()) + no->var_value()->add_preinit_statement(s); + else + { + // Execute the map index expression just so that we can fail if + // the map is nil. + Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(), + NULL, location); + dummy->var_value()->add_preinit_statement(s); + } return true; } @@ -1705,8 +1715,16 @@ Parse::init_vars_from_receive(const Typed_identifier_list* vars, Type* type, if (!this->gogo_->in_global_scope()) this->gogo_->add_statement(s); - else + else if (!val_no->is_sink()) val_no->var_value()->add_preinit_statement(s); + else if (!no->is_sink()) + no->var_value()->add_preinit_statement(s); + else + { + Named_object* dummy = this->create_dummy_global(Type::lookup_bool_type(), + NULL, location); + dummy->var_value()->add_preinit_statement(s); + } return true; } @@ -1757,8 +1775,15 @@ Parse::init_vars_from_type_guard(const Typed_identifier_list* vars, if (!this->gogo_->in_global_scope()) this->gogo_->add_statement(s); - else + else if (!val_no->is_sink()) val_no->var_value()->add_preinit_statement(s); + else if (!no->is_sink()) + no->var_value()->add_preinit_statement(s); + else + { + Named_object* dummy = this->create_dummy_global(type, NULL, location); + dummy->var_value()->add_preinit_statement(s); + } return true; } @@ -1780,17 +1805,7 @@ Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init, if (!this->gogo_->in_global_scope()) this->gogo_->add_statement(Statement::make_statement(init)); else - { - // Create a dummy global variable to force the - // initializer to be run in the right place. - Variable* var = new Variable(type, init, true, false, false, - location); - static int count; - char buf[30]; - snprintf(buf, sizeof buf, "_.%d", count); - ++count; - return this->gogo_->add_variable(buf, var); - } + return this->create_dummy_global(type, init, location); } return this->gogo_->add_sink(); } @@ -1818,6 +1833,22 @@ Parse::init_var(const Typed_identifier& tid, Type* type, Expression* init, return this->gogo_->add_variable(tid.name(), var); } +// Create a dummy global variable to force an initializer to be run in +// the right place. This is used when a sink variable is initialized +// at global scope. + +Named_object* +Parse::create_dummy_global(Type* type, Expression* init, + source_location location) +{ + Variable* var = new Variable(type, init, true, false, false, location); + static int count; + char buf[30]; + snprintf(buf, sizeof buf, "_.%d", count); + ++count; + return this->gogo_->add_variable(buf, var); +} + // SimpleVarDecl = identifier ":=" Expression . // We've already seen the identifier. diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h index 5f6e26aedea8..1fa931957553 100644 --- a/gcc/go/gofrontend/parse.h +++ b/gcc/go/gofrontend/parse.h @@ -197,6 +197,7 @@ class Parse source_location); Named_object* init_var(const Typed_identifier&, Type*, Expression*, bool is_coloneq, bool type_from_init, bool* is_new); + Named_object* create_dummy_global(Type*, Expression*, source_location); void simple_var_decl_or_assignment(const std::string&, source_location, Range_clause*, Type_switch*); void function_decl();