]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Correctly handle tuple assignment to _ at global scope.
authorIan Lance Taylor <ian@gcc.gnu.org>
Wed, 22 Dec 2010 23:09:40 +0000 (23:09 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Wed, 22 Dec 2010 23:09:40 +0000 (23:09 +0000)
From-SVN: r168184

gcc/go/gofrontend/parse.cc
gcc/go/gofrontend/parse.h

index a0d87dc8c6a8d8337c90d45553c630f2c073749f..f4b01be8c93452c88fc71e6e804194fb5950c1b7 100644 (file)
@@ -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.
index 5f6e26aedea8277ba5a717c7f608708e3cf70ab1..1fa931957553b93e2cbc3ac109e9182dc3d99f57 100644 (file)
@@ -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();