This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]