aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-02-05 01:57:42 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-02-05 01:57:42 +0000
commit5dfb4d0f3339595881fba857ab5a4b57c681a8e3 (patch)
tree336c1452068533453093114132ffd040f836b06a /gcc/go
parent33cdac3baa9e0c8da598d5124ac9196be30a3ccb (diff)
downloadgcc-5dfb4d0f3339595881fba857ab5a4b57c681a8e3.zip
gcc-5dfb4d0f3339595881fba857ab5a4b57c681a8e3.tar.gz
gcc-5dfb4d0f3339595881fba857ab5a4b57c681a8e3.tar.bz2
compiler: update iota handling, fix using iota in array length
CL 71750 changed the definition of how iota works. This patch updates gccgo for the new definition. We've been mishandling iota appearing in a type that appears in a const expression, as in `c = len([iota]int{})`. Correct that by copying type expressions when we copy an expression. For simplicity only copy when it can change the size of a type, as that is the only case where iota in a type can affect the value of a constant (I think). This is still a bunch of changes, but almost all boilerplate. Fixes golang/go#22341 Reviewed-on: https://go-review.googlesource.com/91475 From-SVN: r257379
Diffstat (limited to 'gcc/go')
-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