mirror of git://gcc.gnu.org/git/gcc.git
compiler: Fix order of evaluation of struct composite literals.
From-SVN: r185990
This commit is contained in:
parent
7b770e43ee
commit
50f671c667
|
@ -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
|
||||||
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
|
||||||
// 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
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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
|
||||||
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()
|
||||||
|
|
Loading…
Reference in New Issue