diff options
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 87 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 23 |
3 files changed, 85 insertions, 27 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 7900e1a..532cf1e 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -2c62d5223e814887801b1540162c72b90299d910 +7fa4eb4b7a32953c2e838f1b0c684a6733172b43 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 8006888..fee3203 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3878,33 +3878,52 @@ Unary_expression::do_is_static_initializer() const if (this->op_ == OPERATOR_MULT) return false; else if (this->op_ == OPERATOR_AND) - { - // The address of a global variable can used as a static - // initializer. - Var_expression* ve = this->expr_->var_expression(); - if (ve != NULL) - { - Named_object* no = ve->named_object(); - return no->is_variable() && no->var_value()->is_global(); - } + return Unary_expression::base_is_static_initializer(this->expr_); + else + return this->expr_->is_static_initializer(); +} - // The address of a composite literal can be used as a static - // initializer if the composite literal is itself usable as a - // static initializer. - if (this->expr_->is_composite_literal() - && this->expr_->is_static_initializer()) - return true; +// Return whether the address of EXPR can be used as a static +// initializer. - // The address of a string constant can be used as a static - // initializer. This can not be written in Go itself but this - // is used when building a type descriptor. - if (this->expr_->string_expression() != NULL) - return true; +bool +Unary_expression::base_is_static_initializer(Expression* expr) +{ + // The address of a field reference can be a static initializer if + // the base can be a static initializer. + Field_reference_expression* fre = expr->field_reference_expression(); + if (fre != NULL) + return Unary_expression::base_is_static_initializer(fre->expr()); + + // The address of an index expression can be a static initializer if + // the base can be a static initializer and the index is constant. + Array_index_expression* aind = expr->array_index_expression(); + if (aind != NULL) + return (aind->end() == NULL + && aind->start()->is_constant() + && Unary_expression::base_is_static_initializer(aind->array())); + + // The address of a global variable can be a static initializer. + Var_expression* ve = expr->var_expression(); + if (ve != NULL) + { + Named_object* no = ve->named_object(); + return no->is_variable() && no->var_value()->is_global(); + } + + // The address of a composite literal can be used as a static + // initializer if the composite literal is itself usable as a + // static initializer. + if (expr->is_composite_literal() && expr->is_static_initializer()) + return true; - return false; - } - else - return this->expr_->is_static_initializer(); + // The address of a string constant can be used as a static + // initializer. This can not be written in Go itself but this is + // used when building a type descriptor. + if (expr->string_expression() != NULL) + return true; + + return false; } // Apply unary opcode OP to UNC, setting NC. Return true if this @@ -12460,6 +12479,17 @@ Struct_construction_expression::do_is_static_initializer() const if (*pv != NULL && !(*pv)->is_static_initializer()) return false; } + + const Struct_field_list* fields = this->type_->struct_type()->fields(); + for (Struct_field_list::const_iterator pf = fields->begin(); + pf != fields->end(); + ++pf) + { + // There are no constant constructors for interfaces. + if (pf->type()->interface_type() != NULL) + return false; + } + return true; } @@ -12550,7 +12580,7 @@ Struct_construction_expression::do_flatten(Gogo*, Named_object*, return this; // If this is a constant struct, we don't need temporaries. - if (this->is_constant_struct()) + if (this->is_constant_struct() || this->is_static_initializer()) return this; Location loc = this->location(); @@ -12701,6 +12731,11 @@ Array_construction_expression::do_is_static_initializer() const { if (this->vals() == NULL) return true; + + // There are no constant constructors for interfaces. + if (this->type_->array_type()->element_type()->interface_type() != NULL) + return false; + for (Expression_list::const_iterator pv = this->vals()->begin(); pv != this->vals()->end(); ++pv) @@ -12765,7 +12800,7 @@ Array_construction_expression::do_flatten(Gogo*, Named_object*, return this; // If this is a constant array, we don't need temporaries. - if (this->is_constant_array()) + if (this->is_constant_array() || this->is_static_initializer()) return this; Location loc = this->location(); diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index e088100..adf9eab 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -1842,6 +1842,9 @@ class Unary_expression : public Expression { this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); } private: + static bool + base_is_static_initializer(Expression*); + // The unary operator to apply. Operator op_; // Normally true. False if this is an address expression which does @@ -2640,6 +2643,26 @@ class Array_index_expression : public Expression array() const { return this->array_; } + // Return the index of a simple index expression, or the start index + // of a slice expression. + Expression* + start() + { return this->start_; } + + const Expression* + start() const + { return this->start_; } + + // Return the end index of a slice expression. This is NULL for a + // simple index expression. + Expression* + end() + { return this->end_; } + + const Expression* + end() const + { return this->end_; } + protected: int do_traverse(Traverse*); |