aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2013-11-08 17:35:24 +0000
committerIan Lance Taylor <iant@google.com>2013-11-08 17:35:24 +0000
commitba75c1770f408b5704931877efec9208fe3b1a47 (patch)
tree8e018764c60906923b4368389d32c187887c5e74
parent5b1ea11f5fbaa1d51529a4efa58e0d652930eb81 (diff)
compiler: Fix bogus init loop error with struct composite literal.
This should eventually be bug482.go in the master testsuite. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@204583 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/go/gofrontend/expressions.cc48
1 files changed, 45 insertions, 3 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 7269f5849f5..aefb51cec5e 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -13488,10 +13488,52 @@ class Composite_literal_expression : public Parser_expression
int
Composite_literal_expression::do_traverse(Traverse* traverse)
{
- if (this->vals_ != NULL
- && this->vals_->traverse(traverse) == TRAVERSE_EXIT)
+ if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
- return Type::traverse(this->type_, traverse);
+
+ // If this is a struct composite literal with keys, then the keys
+ // are field names, not expressions. We don't want to traverse them
+ // in that case. If we do, we can give an erroneous error "variable
+ // initializer refers to itself." See bug482.go in the testsuite.
+ if (this->has_keys_ && this->vals_ != NULL)
+ {
+ // The type may not be resolvable at this point.
+ Type* type = this->type_;
+ while (true)
+ {
+ if (type->classification() == Type::TYPE_NAMED)
+ type = type->named_type()->real_type();
+ else if (type->classification() == Type::TYPE_FORWARD)
+ {
+ Type* t = type->forwarded();
+ if (t == type)
+ break;
+ type = t;
+ }
+ else
+ break;
+ }
+
+ if (type->classification() == Type::TYPE_STRUCT)
+ {
+ Expression_list::iterator p = this->vals_->begin();
+ while (p != this->vals_->end())
+ {
+ // Skip key.
+ ++p;
+ go_assert(p != this->vals_->end());
+ if (Expression::traverse(&*p, traverse) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
+ ++p;
+ }
+ return TRAVERSE_CONTINUE;
+ }
+ }
+
+ if (this->vals_ != NULL)
+ return this->vals_->traverse(traverse);
+
+ return TRAVERSE_CONTINUE;
}
// Lower a generic composite literal into a specific version based on