-d9f33a479f8012f7495d197e4b7417cba4d477fa
+36594b69b94326014c331fe50a5a345ef4f8de16
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
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());
}
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*
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());
}
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*
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*
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;
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.
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*
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*
}
}
+// 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*
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
}
}
+// 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*
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());
}
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());
}
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());
}
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
{
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);
{ 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*);
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;
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*);
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*);
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*);
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*);
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*);
{ }
Expression*
- do_copy()
- {
- return new Backend_expression(this->bexpr_, this->type_, this->location());
- }
+ do_copy();
Bexpression*
do_get_backend(Translate_context*)
gogo_(gogo),
break_stack_(NULL),
continue_stack_(NULL),
- iota_(0),
enclosing_vars_()
{
}
{
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))
// 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);
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;
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;
}
}
}
-// 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
#ifndef GO_PARSE_H
#define GO_PARSE_H
-class Set_iota_traverse;
class Lex;
class Gogo;
class Named_object;
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();
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
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_;
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
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*
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