This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Go patch committed: Handle tuple assignment to global _
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org, gofrontend-dev at googlegroups dot com
- Date: Wed, 22 Dec 2010 15:09:45 -0800
- Subject: Go patch committed: Handle tuple assignment to global _
A tuple assignment to _ at global scope sometimes requires special
handling to ensure that the statement which sets the tuple variables is
executed. In a special case like _, _ = m[1] at global scope, we still
need to execute the statement because it should fail if m is nil. This
patch fixes these unusual cases. Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 1137a78e5fe4 go/parse.cc
--- a/go/parse.cc Wed Dec 22 08:47:15 2010 -0800
+++ b/go/parse.cc Wed Dec 22 12:15:26 2010 -0800
@@ -1654,8 +1654,18 @@
if (!this->gogo_->in_global_scope())
this->gogo_->add_statement(s);
+ 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
- val_no->var_value()->add_preinit_statement(s);
+ {
+ // 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 @@
if (!this->gogo_->in_global_scope())
this->gogo_->add_statement(s);
+ 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
- val_no->var_value()->add_preinit_statement(s);
+ {
+ 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 @@
if (!this->gogo_->in_global_scope())
this->gogo_->add_statement(s);
+ 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
- val_no->var_value()->add_preinit_statement(s);
+ {
+ Named_object* dummy = this->create_dummy_global(type, NULL, location);
+ dummy->var_value()->add_preinit_statement(s);
+ }
return true;
}
@@ -1780,17 +1805,7 @@
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 @@
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 -r 1137a78e5fe4 go/parse.h
--- a/go/parse.h Wed Dec 22 08:47:15 2010 -0800
+++ b/go/parse.h Wed Dec 22 12:15:26 2010 -0800
@@ -197,6 +197,7 @@
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();