summaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/expressions.h
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2016-10-30 16:48:37 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2016-10-30 16:48:37 +0000
commite32de7baeb35e1b8794c8d6596bd218d6ef39504 (patch)
treedbe8fdb330eeb1b6785b676fd16430ff6fb88892 /gcc/go/gofrontend/expressions.h
parent41fd2d10cd89f0be0930c5bfc3138418078163ee (diff)
downloadgcc-e32de7baeb35e1b8794c8d6596bd218d6ef39504.tar.gz
compiler: fix slice/array evaluation order bug
There was a phase ordering issue in the handling of "keyed" array literal expressions: the lowering phase was canonicalizing the indices/vals before the phase that fixed evaluation order, meaning that the evaluation order was incorrect. The fix is to capture the orginal ordering and use that ordering when doing traversals (there is already something similar being done for struct literal expressions). Fixes golang/go#17640 Reviewed-on: https://go-review.googlesource.com/32296 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@241688 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go/gofrontend/expressions.h')
-rw-r--r--gcc/go/gofrontend/expressions.h86
1 files changed, 54 insertions, 32 deletions
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 0d00f458c38..a02fd19feb3 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -3232,31 +3232,64 @@ class Composite_literal_expression : public Parser_expression
std::vector<bool> key_path_;
};
-// Construct a struct.
+// Helper/mixin class for struct and array construction expressions;
+// encapsulates a list of values plus an optional traversal order
+// recording the order in which the values should be visited.
-class Struct_construction_expression : public Expression
+class Ordered_value_list
{
public:
- Struct_construction_expression(Type* type, Expression_list* vals,
- Location location)
- : Expression(EXPRESSION_STRUCT_CONSTRUCTION, location),
- type_(type), vals_(vals), traverse_order_(NULL)
+ Ordered_value_list(Expression_list* vals)
+ : vals_(vals), traverse_order_(NULL)
{ }
+ Expression_list*
+ vals() const
+ { return this->vals_; }
+
+ int
+ traverse_vals(Traverse* traverse);
+
+ // Get the traversal order (may be NULL)
+ std::vector<unsigned long>*
+ traverse_order()
+ { return traverse_order_; }
+
// 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)
+ set_traverse_order(std::vector<unsigned long>* traverse_order)
{ this->traverse_order_ = traverse_order; }
- // Return whether this is a constant initializer.
+ private:
+ // The list of values, in order of the fields in the struct or in
+ // order of indices in an array. A NULL value of vals_ means that
+ // all fields/slots should be zero-initialized; a single NULL entry
+ // in the list means that the corresponding field or array slot
+ // should be zero-initialized.
+ 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<unsigned long>* traverse_order_;
+};
+
+// Construct a struct.
+
+class Struct_construction_expression : public Expression,
+ public Ordered_value_list
+{
+ public:
+ Struct_construction_expression(Type* type, Expression_list* vals,
+ Location location)
+ : Expression(EXPRESSION_STRUCT_CONSTRUCTION, location),
+ Ordered_value_list(vals),
+ type_(type)
+ { }
+
+ // Return whether this is a constant initializer.
bool
is_constant_struct() const;
- Expression_list*
- vals() const
- { return this->vals_; }
-
protected:
int
do_traverse(Traverse* traverse);
@@ -3279,12 +3312,12 @@ class Struct_construction_expression : public Expression
{
Struct_construction_expression* ret =
new Struct_construction_expression(this->type_,
- (this->vals_ == NULL
+ (this->vals() == NULL
? NULL
- : this->vals_->copy()),
+ : this->vals()->copy()),
this->location());
- if (this->traverse_order_ != NULL)
- ret->set_traverse_order(this->traverse_order_);
+ if (this->traverse_order() != NULL)
+ ret->set_traverse_order(this->traverse_order());
return ret;
}
@@ -3303,19 +3336,14 @@ class Struct_construction_expression : public Expression
private:
// The type of the struct to construct.
Type* type_;
- // The list of values, in order of the fields in the struct. A NULL
- // entry means that the field should be zero-initialized.
- 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_;
};
// Construct an array. This class is not used directly; instead we
// use the child classes, Fixed_array_construction_expression and
// Slice_construction_expression.
-class Array_construction_expression : public Expression
+class Array_construction_expression : public Expression,
+ public Ordered_value_list
{
protected:
Array_construction_expression(Expression_classification classification,
@@ -3323,7 +3351,8 @@ class Array_construction_expression : public Expression
const std::vector<unsigned long>* indexes,
Expression_list* vals, Location location)
: Expression(classification, location),
- type_(type), indexes_(indexes), vals_(vals)
+ Ordered_value_list(vals),
+ type_(type), indexes_(indexes)
{ go_assert(indexes == NULL || indexes->size() == vals->size()); }
public:
@@ -3334,12 +3363,7 @@ class Array_construction_expression : public Expression
// Return the number of elements.
size_t
element_count() const
- { return this->vals_ == NULL ? 0 : this->vals_->size(); }
-
- // The list of values.
- Expression_list*
- vals() const
- { return this->vals_; }
+ { return this->vals() == NULL ? 0 : this->vals()->size(); }
protected:
virtual int
@@ -3385,8 +3409,6 @@ protected:
// The list of indexes into the array, one for each value. This may
// be NULL, in which case the indexes start at zero and increment.
const std::vector<unsigned long>* indexes_;
- // The list of values. This may be NULL if there are no values.
- Expression_list* vals_;
};
// Construct a fixed array.