diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-22 23:09:40 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-22 23:09:40 +0000 |
commit | 8332d80edb206e7de917f8a9f01ab6eec3ce8231 (patch) | |
tree | fa5330368071f721abd72882ca2f588bb8a56dbb /gcc/go | |
parent | 0bfe3fa10f5d5f3dfdc854f5991f83b469e54603 (diff) | |
download | gcc-8332d80edb206e7de917f8a9f01ab6eec3ce8231.zip gcc-8332d80edb206e7de917f8a9f01ab6eec3ce8231.tar.gz gcc-8332d80edb206e7de917f8a9f01ab6eec3ce8231.tar.bz2 |
Correctly handle tuple assignment to _ at global scope.
From-SVN: r168184
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/parse.cc | 59 | ||||
-rw-r--r-- | gcc/go/gofrontend/parse.h | 1 |
2 files changed, 46 insertions, 14 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index a0d87dc..f4b01be 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 5f6e26a..1fa9319 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(); |