This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gccgo] Fix setting global vars with map/receive/type assertion tuples
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 29 Jan 2010 21:28:34 -0800
- Subject: [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;
}