aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2010-12-22 23:09:40 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2010-12-22 23:09:40 +0000
commit8332d80edb206e7de917f8a9f01ab6eec3ce8231 (patch)
treefa5330368071f721abd72882ca2f588bb8a56dbb /gcc/go
parent0bfe3fa10f5d5f3dfdc854f5991f83b469e54603 (diff)
downloadgcc-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.cc59
-rw-r--r--gcc/go/gofrontend/parse.h1
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();