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]

[gccgo] Fix setting global vars with map/receive/type assertion tuples


There was a bug in gcco that if you initialize a pair of global
variables with an expression that returns a tuple, as in
	var v, ok = m[1]
the compiler would get confused.  I committed this patch to fix it.

Ian

diff -r 9e69aedf77d3 go/gogo-tree.cc
--- a/go/gogo-tree.cc	Fri Jan 29 18:19:20 2010 -0800
+++ b/go/gogo-tree.cc	Fri Jan 29 21:22:27 2010 -0800
@@ -354,7 +354,8 @@
 {
   Find_var::Seen_objects seen_objects;
   Find_var find_var(var, &seen_objects);
-  Expression::traverse(&expr, &find_var);
+  if (expr != NULL)
+    Expression::traverse(&expr, &find_var);
   if (preinit != NULL)
     preinit->traverse(&find_var);
   
@@ -469,8 +470,10 @@
 	{
 	  // VAR does not depends upon any other initialization expressions.
 
-	  // Check for a loop of VAR on itself.
-	  if (expression_requires(init, preinit, var))
+	  // Check for a loop of VAR on itself.  We only do this if
+	  // INIT is not NULL; when INIT is NULL, it means that
+	  // PREINIT sets VAR, which we will interpret as a loop.
+	  if (init != NULL && expression_requires(init, preinit, var))
 	    error_at(var->location(),
 		     "initialization expression for %qs depends upon itself",
 		     Gogo::unpack_hidden_name(var->name()).c_str());
@@ -600,7 +603,8 @@
 
 	  if (var_init_tree != NULL_TREE)
 	    {
-	      if (no->var_value()->init() == NULL)
+	      if (no->var_value()->init() == NULL
+		  && !no->var_value()->has_pre_init())
 		append_to_statement_list(var_init_tree, &init_stmt_list);
 	      else
 		var_inits.push_back(Var_init(no, var_init_tree));
@@ -991,17 +995,23 @@
   if (TREE_CODE(statements) == TRY_FINALLY_EXPR)
     statements = TREE_OPERAND(statements, 0);
 
-  tree rhs_tree = this->init_->get_tree(&context);
-  if (var_decl == NULL_TREE)
-    append_to_statement_list(rhs_tree, &statements);
-  else
-    {
-      tree val = Expression::convert_for_assignment(&context, this->type(),
-						    this->init_->type(),
-						    rhs_tree, this->location());
-      tree set = fold_build2_loc(this->location(), MODIFY_EXPR, void_type_node,
-				 var_decl, val);
-      append_to_statement_list(set, &statements);
+  // It's possible to have pre-init statements without an initializer
+  // if the pre-init statements set the variable.
+  if (this->init_ != NULL)
+    {
+      tree rhs_tree = this->init_->get_tree(&context);
+      if (var_decl == NULL_TREE)
+	append_to_statement_list(rhs_tree, &statements);
+      else
+	{
+	  tree val = Expression::convert_for_assignment(&context, this->type(),
+							this->init_->type(),
+							rhs_tree,
+							this->location());
+	  tree set = fold_build2_loc(this->location(), MODIFY_EXPR,
+				     void_type_node, var_decl, val);
+	  append_to_statement_list(set, &statements);
+	}
     }
 
   return block_tree;
diff -r 9e69aedf77d3 go/parse.cc
--- a/go/parse.cc	Fri Jan 29 18:19:20 2010 -0800
+++ b/go/parse.cc	Fri Jan 29 21:22:27 2010 -0800
@@ -1567,17 +1567,18 @@
   bool any_new = false;
   Typed_identifier_list::const_iterator p = vars->begin();
   Expression* init = type == NULL ? index : NULL;
-  Named_object* no = this->init_var(*p, type, init, is_coloneq, type == NULL,
-				    &any_new);
-  if (type == NULL && any_new && no->is_variable())
-    no->var_value()->set_type_from_init_tuple();
-  Expression* val_var = Expression::make_var_reference(no, location);
+  Named_object* val_no = this->init_var(*p, type, init, is_coloneq,
+					type == NULL, &any_new);
+  if (type == NULL && any_new && val_no->is_variable())
+    val_no->var_value()->set_type_from_init_tuple();
+  Expression* val_var = Expression::make_var_reference(val_no, location);
 
   ++p;
   Type* var_type = type;
   if (var_type == NULL)
     var_type = Type::lookup_bool_type();
-  no = this->init_var(*p, var_type, NULL, is_coloneq, false, &any_new);
+  Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
+				    &any_new);
   Expression* present_var = Expression::make_var_reference(no, location);
 
   if (!any_new)
@@ -1586,7 +1587,10 @@
   Statement* s = Statement::make_tuple_map_assignment(val_var, present_var,
 						      index, location);
 
-  this->gogo_->add_statement(s);
+  if (!this->gogo_->in_global_scope())
+    this->gogo_->add_statement(s);
+  else
+    val_no->var_value()->add_preinit_statement(s);
 
   return true;
 }
@@ -1612,17 +1616,18 @@
   bool any_new = false;
   Typed_identifier_list::const_iterator p = vars->begin();
   Expression* init = type == NULL ? receive : NULL;
-  Named_object* no = this->init_var(*p, type, init, is_coloneq, type == NULL,
-				    &any_new);
-  if (type == NULL && any_new && no->is_variable())
-    no->var_value()->set_type_from_init_tuple();
-  Expression* val_var = Expression::make_var_reference(no, location);
+  Named_object* val_no = this->init_var(*p, type, init, is_coloneq,
+					type == NULL, &any_new);
+  if (type == NULL && any_new && val_no->is_variable())
+    val_no->var_value()->set_type_from_init_tuple();
+  Expression* val_var = Expression::make_var_reference(val_no, location);
 
   ++p;
   Type* var_type = type;
   if (var_type == NULL)
     var_type = Type::lookup_bool_type();
-  no = this->init_var(*p, var_type, NULL, is_coloneq, false, &any_new);
+  Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
+				    &any_new);
   Expression* received_var = Expression::make_var_reference(no, location);
 
   if (!any_new)
@@ -1633,7 +1638,10 @@
 							  receive->channel(),
 							  location);
 
-  this->gogo_->add_statement(s);
+  if (!this->gogo_->in_global_scope())
+    this->gogo_->add_statement(s);
+  else
+    val_no->var_value()->add_preinit_statement(s);
 
   return true;
 }
@@ -1661,15 +1669,16 @@
   Type* var_type = type;
   if (var_type == NULL)
     var_type = type_guard->type();
-  Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
-				    &any_new);
-  Expression* val_var = Expression::make_var_reference(no, location);
+  Named_object* val_no = this->init_var(*p, var_type, NULL, is_coloneq, false,
+					&any_new);
+  Expression* val_var = Expression::make_var_reference(val_no, location);
 
   ++p;
   var_type = type;
   if (var_type == NULL)
     var_type = Type::lookup_bool_type();
-  no = this->init_var(*p, var_type, NULL, is_coloneq, false, &any_new);
+  Named_object* no = this->init_var(*p, var_type, NULL, is_coloneq, false,
+				    &any_new);
   Expression* ok_var = Expression::make_var_reference(no, location);
 
   Expression* texpr = type_guard->expr();
@@ -1681,7 +1690,10 @@
   if (!any_new)
     error_at(location, "variables redeclared but no variable is new");
 
-  this->gogo_->add_statement(s);
+  if (!this->gogo_->in_global_scope())
+    this->gogo_->add_statement(s);
+  else
+    val_no->var_value()->add_preinit_statement(s);
 
   return true;
 }

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