Commit 50f671c6 by Ian Lance Taylor

compiler: Fix order of evaluation of struct composite literals.

From-SVN: r185990
parent 7b770e43
...@@ -10967,9 +10967,15 @@ class Struct_construction_expression : public Expression ...@@ -10967,9 +10967,15 @@ class Struct_construction_expression : public Expression
Struct_construction_expression(Type* type, Expression_list* vals, Struct_construction_expression(Type* type, Expression_list* vals,
Location location) Location location)
: Expression(EXPRESSION_STRUCT_CONSTRUCTION, location), : Expression(EXPRESSION_STRUCT_CONSTRUCTION, location),
type_(type), vals_(vals) type_(type), vals_(vals), traverse_order_(NULL)
{ } { }
// Set the traversal order, used to ensure that we implement the
// order of evaluation rules. Takes ownership of the argument.
void
set_traverse_order(std::vector<int>* traverse_order)
{ this->traverse_order_ = traverse_order; }
// Return whether this is a constant initializer. // Return whether this is a constant initializer.
bool bool
is_constant_struct() const; is_constant_struct() const;
...@@ -10991,8 +10997,12 @@ class Struct_construction_expression : public Expression ...@@ -10991,8 +10997,12 @@ class Struct_construction_expression : public Expression
Expression* Expression*
do_copy() do_copy()
{ {
return new Struct_construction_expression(this->type_, this->vals_->copy(), Struct_construction_expression* ret =
this->location()); new Struct_construction_expression(this->type_, this->vals_->copy(),
this->location());
if (this->traverse_order_ != NULL)
ret->set_traverse_order(this->traverse_order_);
return ret;
} }
tree tree
...@@ -11010,6 +11020,9 @@ class Struct_construction_expression : public Expression ...@@ -11010,6 +11020,9 @@ class Struct_construction_expression : public Expression
// The list of values, in order of the fields in the struct. A NULL // The list of values, in order of the fields in the struct. A NULL
// entry means that the field should be zero-initialized. // entry means that the field should be zero-initialized.
Expression_list* vals_; Expression_list* vals_;
// If not NULL, the order in which to traverse vals_. This is used
// so that we implement the order of evaluation rules correctly.
std::vector<int>* traverse_order_;
}; };
// Traversal. // Traversal.
...@@ -11017,9 +11030,26 @@ class Struct_construction_expression : public Expression ...@@ -11017,9 +11030,26 @@ class Struct_construction_expression : public Expression
int int
Struct_construction_expression::do_traverse(Traverse* traverse) Struct_construction_expression::do_traverse(Traverse* traverse)
{ {
if (this->vals_ != NULL if (this->vals_ != NULL)
&& this->vals_->traverse(traverse) == TRAVERSE_EXIT) {
return TRAVERSE_EXIT; if (this->traverse_order_ == NULL)
{
if (this->vals_->traverse(traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
else
{
for (std::vector<int>::const_iterator p =
this->traverse_order_->begin();
p != this->traverse_order_->end();
++p)
{
if (Expression::traverse(&this->vals_->at(*p), traverse)
== TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
}
}
if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT) if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT; return TRAVERSE_EXIT;
return TRAVERSE_CONTINUE; return TRAVERSE_CONTINUE;
...@@ -12198,6 +12228,7 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type) ...@@ -12198,6 +12228,7 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
size_t field_count = st->field_count(); size_t field_count = st->field_count();
std::vector<Expression*> vals(field_count); std::vector<Expression*> vals(field_count);
std::vector<int>* traverse_order = new(std::vector<int>);
Expression_list::const_iterator p = this->vals_->begin(); Expression_list::const_iterator p = this->vals_->begin();
while (p != this->vals_->end()) while (p != this->vals_->end())
{ {
...@@ -12350,6 +12381,7 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type) ...@@ -12350,6 +12381,7 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
type->named_type()->message_name().c_str()); type->named_type()->message_name().c_str());
vals[index] = val; vals[index] = val;
traverse_order->push_back(index);
} }
Expression_list* list = new Expression_list; Expression_list* list = new Expression_list;
...@@ -12357,7 +12389,10 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type) ...@@ -12357,7 +12389,10 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
for (size_t i = 0; i < field_count; ++i) for (size_t i = 0; i < field_count; ++i)
list->push_back(vals[i]); list->push_back(vals[i]);
return new Struct_construction_expression(type, list, location); Struct_construction_expression* ret =
new Struct_construction_expression(type, list, location);
ret->set_traverse_order(traverse_order);
return ret;
} }
// Lower an array composite literal. // Lower an array composite literal.
......
...@@ -842,6 +842,11 @@ class Expression_list ...@@ -842,6 +842,11 @@ class Expression_list
bool bool
contains_error() const; contains_error() const;
// Retrieve an element by index.
Expression*&
at(size_t i)
{ return this->entries_.at(i); }
// Return the first and last elements. // Return the first and last elements.
Expression*& Expression*&
front() front()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment