aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc141
-rw-r--r--gcc/go/gofrontend/expressions.h79
-rw-r--r--gcc/go/gofrontend/parse.cc40
-rw-r--r--gcc/go/gofrontend/parse.h9
-rw-r--r--gcc/go/gofrontend/types.cc62
-rw-r--r--gcc/go/gofrontend/types.h14
7 files changed, 227 insertions, 120 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index c0f977a..3588a8a 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-d9f33a479f8012f7495d197e4b7417cba4d477fa
+36594b69b94326014c331fe50a5a345ef4f8de16
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 3bcc5ae..8555c05 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -1928,10 +1928,16 @@ class Integer_expression : public Expression
do_copy()
{
if (this->is_character_constant_)
- return Expression::make_character(&this->val_, this->type_,
+ return Expression::make_character(&this->val_,
+ (this->type_ == NULL
+ ? NULL
+ : this->type_->copy_expressions()),
this->location());
else
- return Expression::make_integer_z(&this->val_, this->type_,
+ return Expression::make_integer_z(&this->val_,
+ (this->type_ == NULL
+ ? NULL
+ : this->type_->copy_expressions()),
this->location());
}
@@ -2323,7 +2329,10 @@ class Float_expression : public Expression
Expression*
do_copy()
- { return Expression::make_float(&this->val_, this->type_,
+ { return Expression::make_float(&this->val_,
+ (this->type_ == NULL
+ ? NULL
+ : this->type_->copy_expressions()),
this->location()); }
Bexpression*
@@ -2514,7 +2523,10 @@ class Complex_expression : public Expression
Expression*
do_copy()
{
- return Expression::make_complex(&this->val_, this->type_,
+ return Expression::make_complex(&this->val_,
+ (this->type_ == NULL
+ ? NULL
+ : this->type_->copy_expressions()),
this->location());
}
@@ -3420,6 +3432,16 @@ Type_conversion_expression::do_check_types(Gogo*)
this->set_is_error();
}
+// Copy.
+
+Expression*
+Type_conversion_expression::do_copy()
+{
+ return new Type_conversion_expression(this->type_->copy_expressions(),
+ this->expr_->copy(),
+ this->location());
+}
+
// Get the backend representation for a type conversion.
Bexpression*
@@ -3621,6 +3643,16 @@ Unsafe_type_conversion_expression::do_is_static_initializer() const
return false;
}
+// Copy.
+
+Expression*
+Unsafe_type_conversion_expression::do_copy()
+{
+ return new Unsafe_type_conversion_expression(this->type_->copy_expressions(),
+ this->expr_->copy(),
+ this->location());
+}
+
// Convert to backend representation.
Bexpression*
@@ -12401,7 +12433,8 @@ Expression*
Allocation_expression::do_copy()
{
Allocation_expression* alloc =
- new Allocation_expression(this->type_, this->location());
+ new Allocation_expression(this->type_->copy_expressions(),
+ this->location());
if (this->allocate_on_stack_)
alloc->set_allocate_on_stack();
return alloc;
@@ -12641,6 +12674,22 @@ Struct_construction_expression::do_check_types(Gogo*)
go_assert(pv == this->vals()->end());
}
+// Copy.
+
+Expression*
+Struct_construction_expression::do_copy()
+{
+ Struct_construction_expression* ret =
+ new Struct_construction_expression(this->type_->copy_expressions(),
+ (this->vals() == NULL
+ ? NULL
+ : this->vals()->copy()),
+ this->location());
+ if (this->traverse_order() != NULL)
+ ret->set_traverse_order(this->traverse_order());
+ return ret;
+}
+
// Flatten a struct construction expression. Store the values into
// temporaries in case they need interface conversion.
@@ -13032,6 +13081,20 @@ Fixed_array_construction_expression::Fixed_array_construction_expression(
type, indexes, vals, location)
{ go_assert(type->array_type() != NULL && !type->is_slice_type()); }
+
+// Copy.
+
+Expression*
+Fixed_array_construction_expression::do_copy()
+{
+ Type* t = this->type()->copy_expressions();
+ return new Fixed_array_construction_expression(t, this->indexes(),
+ (this->vals() == NULL
+ ? NULL
+ : this->vals()->copy()),
+ this->location());
+}
+
// Return the backend representation for constructing a fixed array.
Bexpression*
@@ -13166,6 +13229,19 @@ dump_slice_storage_expression(Ast_dump_context* ast_dump_context) const
ast_dump_context->dump_expression(this->slice_storage_);
}
+// Copy.
+
+Expression*
+Slice_construction_expression::do_copy()
+{
+ return new Slice_construction_expression(this->type()->copy_expressions(),
+ this->indexes(),
+ (this->vals() == NULL
+ ? NULL
+ : this->vals()->copy()),
+ this->location());
+}
+
// Return the backend representation for constructing a slice.
Bexpression*
@@ -13379,6 +13455,18 @@ Map_construction_expression::do_check_types(Gogo*)
}
}
+// Copy.
+
+Expression*
+Map_construction_expression::do_copy()
+{
+ return new Map_construction_expression(this->type_->copy_expressions(),
+ (this->vals_ == NULL
+ ? NULL
+ : this->vals_->copy()),
+ this->location());
+}
+
// Return the backend representation for constructing a map.
Bexpression*
@@ -14058,6 +14146,23 @@ Composite_literal_expression::lower_map(Gogo* gogo, Named_object* function,
return new Map_construction_expression(type, this->vals_, location);
}
+// Copy.
+
+Expression*
+Composite_literal_expression::do_copy()
+{
+ Composite_literal_expression* ret =
+ new Composite_literal_expression(this->type_->copy_expressions(),
+ this->depth_, this->has_keys_,
+ (this->vals_ == NULL
+ ? NULL
+ : this->vals_->copy()),
+ this->all_are_names_,
+ this->location());
+ ret->key_path_ = this->key_path_;
+ return ret;
+}
+
// Dump ast representation for a composite literal expression.
void
@@ -14234,6 +14339,16 @@ Type_guard_expression::do_check_types(Gogo*)
}
}
+// Copy.
+
+Expression*
+Type_guard_expression::do_copy()
+{
+ return new Type_guard_expression(this->expr_->copy(),
+ this->type_->copy_expressions(),
+ this->location());
+}
+
// Return the backend representation for a type guard expression.
Bexpression*
@@ -14961,7 +15076,8 @@ class Slice_value_expression : public Expression
Expression*
do_copy()
{
- return new Slice_value_expression(this->type_, this->valptr_->copy(),
+ return new Slice_value_expression(this->type_->copy_expressions(),
+ this->valptr_->copy(),
this->len_->copy(), this->cap_->copy(),
this->location());
}
@@ -15222,7 +15338,7 @@ class Interface_value_expression : public Expression
Expression*
do_copy()
{
- return new Interface_value_expression(this->type_,
+ return new Interface_value_expression(this->type_->copy_expressions(),
this->first_field_->copy(),
this->obj_->copy(), this->location());
}
@@ -15317,7 +15433,9 @@ class Interface_mtable_expression : public Expression
Expression*
do_copy()
{
- return new Interface_mtable_expression(this->itype_, this->type_,
+ Interface_type* itype = this->itype_->copy_expressions()->interface_type();
+ return new Interface_mtable_expression(itype,
+ this->type_->copy_expressions(),
this->is_pointer_, this->location());
}
@@ -15805,6 +15923,13 @@ Backend_expression::do_traverse(Traverse*)
return TRAVERSE_CONTINUE;
}
+Expression*
+Backend_expression::do_copy()
+{
+ return new Backend_expression(this->bexpr_, this->type_->copy_expressions(),
+ this->location());
+}
+
void
Backend_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
{
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 18fd91b..d16a284 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -1664,11 +1664,7 @@ class Type_conversion_expression : public Expression
do_check_types(Gogo*);
Expression*
- do_copy()
- {
- return new Type_conversion_expression(this->type_, this->expr_->copy(),
- this->location());
- }
+ do_copy();
Bexpression*
do_get_backend(Translate_context* context);
@@ -1720,12 +1716,7 @@ class Unsafe_type_conversion_expression : public Expression
{ this->expr_->determine_type_no_context(); }
Expression*
- do_copy()
- {
- return new Unsafe_type_conversion_expression(this->type_,
- this->expr_->copy(),
- this->location());
- }
+ do_copy();
Bexpression*
do_get_backend(Translate_context*);
@@ -3430,19 +3421,7 @@ class Composite_literal_expression : public Parser_expression
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
Expression*
- do_copy()
- {
- Composite_literal_expression *ret =
- new Composite_literal_expression(this->type_, this->depth_,
- this->has_keys_,
- (this->vals_ == NULL
- ? NULL
- : this->vals_->copy()),
- this->all_are_names_,
- this->location());
- ret->key_path_ = this->key_path_;
- return ret;
- }
+ do_copy();
void
do_dump_expression(Ast_dump_context*) const;
@@ -3556,18 +3535,7 @@ class Struct_construction_expression : public Expression,
do_check_types(Gogo*);
Expression*
- do_copy()
- {
- Struct_construction_expression* ret =
- new Struct_construction_expression(this->type_,
- (this->vals() == NULL
- ? NULL
- : this->vals()->copy()),
- this->location());
- if (this->traverse_order() != NULL)
- ret->set_traverse_order(this->traverse_order());
- return ret;
- }
+ do_copy();
Expression*
do_flatten(Gogo*, Named_object*, Statement_inserter*);
@@ -3671,15 +3639,7 @@ class Fixed_array_construction_expression :
protected:
Expression*
- do_copy()
- {
- return new Fixed_array_construction_expression(this->type(),
- this->indexes(),
- (this->vals() == NULL
- ? NULL
- : this->vals()->copy()),
- this->location());
- }
+ do_copy();
Bexpression*
do_get_backend(Translate_context*);
@@ -3712,14 +3672,7 @@ class Slice_construction_expression : public Array_construction_expression
do_traverse(Traverse* traverse);
Expression*
- do_copy()
- {
- return new Slice_construction_expression(this->type(), this->indexes(),
- (this->vals() == NULL
- ? NULL
- : this->vals()->copy()),
- this->location());
- }
+ do_copy();
Bexpression*
do_get_backend(Translate_context*);
@@ -3778,14 +3731,7 @@ class Map_construction_expression : public Expression
do_check_types(Gogo*);
Expression*
- do_copy()
- {
- return new Map_construction_expression(this->type_,
- (this->vals_ == NULL
- ? NULL
- : this->vals_->copy()),
- this->location());
- }
+ do_copy();
Bexpression*
do_get_backend(Translate_context*);
@@ -3846,11 +3792,7 @@ class Type_guard_expression : public Expression
do_check_types(Gogo*);
Expression*
- do_copy()
- {
- return new Type_guard_expression(this->expr_->copy(), this->type_,
- this->location());
- }
+ do_copy();
Bexpression*
do_get_backend(Translate_context*);
@@ -4102,10 +4044,7 @@ class Backend_expression : public Expression
{ }
Expression*
- do_copy()
- {
- return new Backend_expression(this->bexpr_, this->type_, this->location());
- }
+ do_copy();
Bexpression*
do_get_backend(Translate_context*)
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index cc3791b..4891e75 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -50,7 +50,6 @@ Parse::Parse(Lex* lex, Gogo* gogo)
gogo_(gogo),
break_stack_(NULL),
continue_stack_(NULL),
- iota_(0),
enclosing_vars_()
{
}
@@ -1407,19 +1406,20 @@ Parse::const_decl()
{
go_assert(this->peek_token()->is_keyword(KEYWORD_CONST));
this->advance_token();
- this->reset_iota();
+ int iota = 0;
Type* last_type = NULL;
Expression_list* last_expr_list = NULL;
if (!this->peek_token()->is_op(OPERATOR_LPAREN))
- this->const_spec(&last_type, &last_expr_list);
+ this->const_spec(iota, &last_type, &last_expr_list);
else
{
this->advance_token();
while (!this->peek_token()->is_op(OPERATOR_RPAREN))
{
- this->const_spec(&last_type, &last_expr_list);
+ this->const_spec(iota, &last_type, &last_expr_list);
+ ++iota;
if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
this->advance_token();
else if (!this->peek_token()->is_op(OPERATOR_RPAREN))
@@ -1440,7 +1440,7 @@ Parse::const_decl()
// ConstSpec = IdentifierList [ [ CompleteType ] "=" ExpressionList ] .
void
-Parse::const_spec(Type** last_type, Expression_list** last_expr_list)
+Parse::const_spec(int iota, Type** last_type, Expression_list** last_expr_list)
{
Typed_identifier_list til;
this->identifier_list(&til);
@@ -1492,7 +1492,7 @@ Parse::const_spec(Type** last_type, Expression_list** last_expr_list)
pi->set_type(type);
if (!Gogo::is_sink_name(pi->name()))
- this->gogo_->add_constant(*pi, *pe, this->iota_value());
+ this->gogo_->add_constant(*pi, *pe, iota);
else
{
static int count;
@@ -1500,15 +1500,13 @@ Parse::const_spec(Type** last_type, Expression_list** last_expr_list)
snprintf(buf, sizeof buf, ".$sinkconst%d", count);
++count;
Typed_identifier ti(std::string(buf), type, pi->location());
- Named_object* no = this->gogo_->add_constant(ti, *pe, this->iota_value());
+ Named_object* no = this->gogo_->add_constant(ti, *pe, iota);
no->const_value()->set_is_sink();
}
}
if (pe != expr_list->end())
go_error_at(this->location(), "too many initializers");
- this->increment_iota();
-
return;
}
@@ -5838,30 +5836,6 @@ Parse::program()
}
}
-// Reset the current iota value.
-
-void
-Parse::reset_iota()
-{
- this->iota_ = 0;
-}
-
-// Return the current iota value.
-
-int
-Parse::iota_value()
-{
- return this->iota_;
-}
-
-// Increment the current iota value.
-
-void
-Parse::increment_iota()
-{
- ++this->iota_;
-}
-
// Skip forward to a semicolon or OP. OP will normally be
// OPERATOR_RPAREN or OPERATOR_RCURLY. If we find a semicolon, move
// past it and return. If we find OP, it will be the next token to
diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h
index 2ba8457..f309ee0 100644
--- a/gcc/go/gofrontend/parse.h
+++ b/gcc/go/gofrontend/parse.h
@@ -7,7 +7,6 @@
#ifndef GO_PARSE_H
#define GO_PARSE_H
-class Set_iota_traverse;
class Lex;
class Gogo;
class Named_object;
@@ -185,7 +184,7 @@ class Parse
void decl(void (Parse::*)(void*, unsigned int), void*, unsigned int pragmas);
void list(void (Parse::*)(void*, unsigned int), void*, bool);
void const_decl();
- void const_spec(Type**, Expression_list**);
+ void const_spec(int, Type**, Expression_list**);
void type_decl(unsigned int pragmas);
void type_spec(void*, unsigned int pragmas);
void var_decl();
@@ -280,10 +279,6 @@ class Parse
void import_decl();
void import_spec(void*, unsigned int pragmas);
- void reset_iota();
- int iota_value();
- void increment_iota();
-
// Skip past an error looking for a semicolon or OP. Return true if
// all is well, false if we found EOF.
bool
@@ -319,8 +314,6 @@ class Parse
Bc_stack* break_stack_;
// A stack of statements for which continue may be used.
Bc_stack* continue_stack_;
- // The current iota value.
- int iota_;
// References from the local function to variables defined in
// enclosing functions.
Enclosing_vars enclosing_vars_;
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index ea9d81d..34edf76 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -868,6 +868,68 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason)
return false;
}
+// Copy expressions if it may change the size.
+//
+// The only type that has an expression is an array type. The only
+// types whose size can be changed by the size of an array type are an
+// array type itself, or a struct type with an array field.
+Type*
+Type::copy_expressions()
+{
+ // This is run during parsing, so types may not be valid yet.
+ // We only have to worry about array type literals.
+ switch (this->classification_)
+ {
+ default:
+ return this;
+
+ case TYPE_ARRAY:
+ {
+ Array_type* at = this->array_type();
+ if (at->length() == NULL)
+ return this;
+ Expression* len = at->length()->copy();
+ if (at->length() == len)
+ return this;
+ return Type::make_array_type(at->element_type(), len);
+ }
+
+ case TYPE_STRUCT:
+ {
+ Struct_type* st = this->struct_type();
+ const Struct_field_list* sfl = st->fields();
+ if (sfl == NULL)
+ return this;
+ bool changed = false;
+ Struct_field_list *nsfl = new Struct_field_list();
+ for (Struct_field_list::const_iterator pf = sfl->begin();
+ pf != sfl->end();
+ ++pf)
+ {
+ Type* ft = pf->type()->copy_expressions();
+ Struct_field nf(Typed_identifier((pf->is_anonymous()
+ ? ""
+ : pf->field_name()),
+ ft,
+ pf->location()));
+ if (pf->has_tag())
+ nf.set_tag(pf->tag());
+ nsfl->push_back(nf);
+ if (ft != pf->type())
+ changed = true;
+ }
+ if (!changed)
+ {
+ delete(nsfl);
+ return this;
+ }
+ return Type::make_struct_type(nsfl, st->location());
+ }
+ }
+
+ go_unreachable();
+}
+
// Return a hash code for the type to be used for method lookup.
unsigned int
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 4e060a4..6487731 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -916,6 +916,15 @@ class Type
is_unsafe_pointer_type() const
{ return this->points_to() != NULL && this->points_to()->is_void_type(); }
+ // Return a version of this type with any expressions copied, but
+ // only if copying the expressions will affect the size of the type.
+ // If there are no such expressions in the type (expressions can
+ // only occur in array types), just return the same type. If any
+ // expressions can not affect the size of the type, just return the
+ // same type.
+ Type*
+ copy_expressions();
+
// Look for field or method NAME for TYPE. Return an expression for
// it, bound to EXPR.
static Expression*
@@ -2444,6 +2453,11 @@ class Struct_type : public Type
field_count() const
{ return this->fields_->size(); }
+ // Location of struct definition.
+ Location
+ location() const
+ { return this->location_; }
+
// Push a new field onto the end of the struct. This is used when
// building a closure variable.
void