compiler: Fix crash: type T1 struct { F *[1]T2 } where T2 is a struct.
This will become bug417.go. From-SVN: r184299
This commit is contained in:
parent
cc8b9c31fb
commit
6df020c0d1
4 changed files with 352 additions and 81 deletions
|
@ -522,8 +522,8 @@ Expression::convert_interface_to_interface(Translate_context* context,
|
|||
// first field is just the type descriptor of the object.
|
||||
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
|
||||
"__type_descriptor") == 0);
|
||||
go_assert(TREE_TYPE(field) == TREE_TYPE(rhs_type_descriptor));
|
||||
elt->value = rhs_type_descriptor;
|
||||
elt->value = fold_convert_loc(location.gcc_location(),
|
||||
TREE_TYPE(field), rhs_type_descriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -2929,8 +2929,6 @@ Gogo::convert_named_types()
|
|||
|
||||
Runtime::convert_types(this);
|
||||
|
||||
Function_type::convert_types(this);
|
||||
|
||||
this->named_types_are_converted_ = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,28 @@ extern "C"
|
|||
#include "backend.h"
|
||||
#include "types.h"
|
||||
|
||||
// Forward declarations so that we don't have to make types.h #include
|
||||
// backend.h.
|
||||
|
||||
static void
|
||||
get_backend_struct_fields(Gogo* gogo, const Struct_field_list* fields,
|
||||
bool use_placeholder,
|
||||
std::vector<Backend::Btyped_identifier>* bfields);
|
||||
|
||||
static void
|
||||
get_backend_slice_fields(Gogo* gogo, Array_type* type, bool use_placeholder,
|
||||
std::vector<Backend::Btyped_identifier>* bfields);
|
||||
|
||||
static void
|
||||
get_backend_interface_fields(Gogo* gogo, Interface_type* type,
|
||||
bool use_placeholder,
|
||||
std::vector<Backend::Btyped_identifier>* bfields);
|
||||
|
||||
// Class Type.
|
||||
|
||||
Type::Type(Type_classification classification)
|
||||
: classification_(classification), btype_(NULL), type_descriptor_var_(NULL)
|
||||
: classification_(classification), btype_is_placeholder_(false),
|
||||
btype_(NULL), type_descriptor_var_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -895,7 +913,11 @@ Btype*
|
|||
Type::get_backend(Gogo* gogo)
|
||||
{
|
||||
if (this->btype_ != NULL)
|
||||
return this->btype_;
|
||||
{
|
||||
if (this->btype_is_placeholder_ && gogo->named_types_are_converted())
|
||||
this->finish_backend(gogo);
|
||||
return this->btype_;
|
||||
}
|
||||
|
||||
if (this->forward_declaration_type() != NULL
|
||||
|| this->named_type() != NULL)
|
||||
|
@ -966,6 +988,189 @@ Type::get_btype_without_hash(Gogo* gogo)
|
|||
return this->btype_;
|
||||
}
|
||||
|
||||
// Get the backend representation of a type without forcing the
|
||||
// creation of the backend representation of all supporting types.
|
||||
// This will return a backend type that has the correct size but may
|
||||
// be incomplete. E.g., a pointer will just be a placeholder pointer,
|
||||
// and will not contain the final representation of the type to which
|
||||
// it points. This is used while converting all named types to the
|
||||
// backend representation, to avoid problems with indirect references
|
||||
// to types which are not yet complete. When this is called, the
|
||||
// sizes of all direct references (e.g., a struct field) should be
|
||||
// known, but the sizes of indirect references (e.g., the type to
|
||||
// which a pointer points) may not.
|
||||
|
||||
Btype*
|
||||
Type::get_backend_placeholder(Gogo* gogo)
|
||||
{
|
||||
if (gogo->named_types_are_converted())
|
||||
return this->get_backend(gogo);
|
||||
if (this->btype_ != NULL)
|
||||
return this->btype_;
|
||||
|
||||
Btype* bt;
|
||||
switch (this->classification_)
|
||||
{
|
||||
case TYPE_ERROR:
|
||||
case TYPE_VOID:
|
||||
case TYPE_BOOLEAN:
|
||||
case TYPE_INTEGER:
|
||||
case TYPE_FLOAT:
|
||||
case TYPE_COMPLEX:
|
||||
case TYPE_STRING:
|
||||
case TYPE_NIL:
|
||||
// These are simple types that can just be created directly.
|
||||
return this->get_backend(gogo);
|
||||
|
||||
case TYPE_FUNCTION:
|
||||
{
|
||||
Location loc = this->function_type()->location();
|
||||
bt = gogo->backend()->placeholder_pointer_type("", loc, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_POINTER:
|
||||
{
|
||||
Location loc = Linemap::unknown_location();
|
||||
bt = gogo->backend()->placeholder_pointer_type("", loc, false);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_STRUCT:
|
||||
// We don't have to make the struct itself be a placeholder. We
|
||||
// are promised that we know the sizes of the struct fields.
|
||||
// But we may have to use a placeholder for any particular
|
||||
// struct field.
|
||||
{
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_struct_fields(gogo, this->struct_type()->fields(),
|
||||
true, &bfields);
|
||||
bt = gogo->backend()->struct_type(bfields);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_ARRAY:
|
||||
if (this->is_slice_type())
|
||||
{
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_slice_fields(gogo, this->array_type(), true, &bfields);
|
||||
bt = gogo->backend()->struct_type(bfields);
|
||||
}
|
||||
else
|
||||
{
|
||||
Btype* element = this->array_type()->get_backend_element(gogo, true);
|
||||
Bexpression* len = this->array_type()->get_backend_length(gogo);
|
||||
bt = gogo->backend()->array_type(element, len);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_MAP:
|
||||
case TYPE_CHANNEL:
|
||||
// All maps and channels have the same backend representation.
|
||||
return this->get_backend(gogo);
|
||||
|
||||
case TYPE_INTERFACE:
|
||||
if (this->interface_type()->is_empty())
|
||||
return Interface_type::get_backend_empty_interface_type(gogo);
|
||||
else
|
||||
{
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_interface_fields(gogo, this->interface_type(), true,
|
||||
&bfields);
|
||||
bt = gogo->backend()->struct_type(bfields);
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_NAMED:
|
||||
case TYPE_FORWARD:
|
||||
// Named types keep track of their own dependencies and manage
|
||||
// their own placeholders.
|
||||
return this->get_backend(gogo);
|
||||
|
||||
case TYPE_SINK:
|
||||
case TYPE_CALL_MULTIPLE_RESULT:
|
||||
default:
|
||||
go_unreachable();
|
||||
}
|
||||
|
||||
this->btype_ = bt;
|
||||
this->btype_is_placeholder_ = true;
|
||||
return bt;
|
||||
}
|
||||
|
||||
// Complete the backend representation. This is called for a type
|
||||
// using a placeholder type.
|
||||
|
||||
void
|
||||
Type::finish_backend(Gogo* gogo)
|
||||
{
|
||||
go_assert(this->btype_ != NULL);
|
||||
if (!this->btype_is_placeholder_)
|
||||
return;
|
||||
|
||||
switch (this->classification_)
|
||||
{
|
||||
case TYPE_ERROR:
|
||||
case TYPE_VOID:
|
||||
case TYPE_BOOLEAN:
|
||||
case TYPE_INTEGER:
|
||||
case TYPE_FLOAT:
|
||||
case TYPE_COMPLEX:
|
||||
case TYPE_STRING:
|
||||
case TYPE_NIL:
|
||||
go_unreachable();
|
||||
|
||||
case TYPE_FUNCTION:
|
||||
{
|
||||
Btype* bt = this->do_get_backend(gogo);
|
||||
if (!gogo->backend()->set_placeholder_function_type(this->btype_, bt))
|
||||
go_assert(saw_errors());
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_POINTER:
|
||||
{
|
||||
Btype* bt = this->do_get_backend(gogo);
|
||||
if (!gogo->backend()->set_placeholder_pointer_type(this->btype_, bt))
|
||||
go_assert(saw_errors());
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_STRUCT:
|
||||
// The struct type itself is done, but we have to make sure that
|
||||
// all the field types are converted.
|
||||
this->struct_type()->finish_backend_fields(gogo);
|
||||
break;
|
||||
|
||||
case TYPE_ARRAY:
|
||||
// The array type itself is done, but make sure the element type
|
||||
// is converted.
|
||||
this->array_type()->finish_backend_element(gogo);
|
||||
break;
|
||||
|
||||
case TYPE_MAP:
|
||||
case TYPE_CHANNEL:
|
||||
go_unreachable();
|
||||
|
||||
case TYPE_INTERFACE:
|
||||
// The interface type itself is done, but make sure the method
|
||||
// types are converted.
|
||||
this->interface_type()->finish_backend_methods(gogo);
|
||||
break;
|
||||
|
||||
case TYPE_NAMED:
|
||||
case TYPE_FORWARD:
|
||||
go_unreachable();
|
||||
|
||||
case TYPE_SINK:
|
||||
case TYPE_CALL_MULTIPLE_RESULT:
|
||||
default:
|
||||
go_unreachable();
|
||||
}
|
||||
|
||||
this->btype_is_placeholder_ = false;
|
||||
}
|
||||
|
||||
// Return a pointer to the type descriptor for this type.
|
||||
|
||||
tree
|
||||
|
@ -2059,7 +2264,8 @@ Type::backend_type_size(Gogo* gogo, unsigned int *psize)
|
|||
{
|
||||
if (!this->is_backend_type_size_known(gogo))
|
||||
return false;
|
||||
size_t size = gogo->backend()->type_size(this->get_backend(gogo));
|
||||
Btype* bt = this->get_backend_placeholder(gogo);
|
||||
size_t size = gogo->backend()->type_size(bt);
|
||||
*psize = static_cast<unsigned int>(size);
|
||||
if (*psize != size)
|
||||
return false;
|
||||
|
@ -2074,7 +2280,8 @@ Type::backend_type_align(Gogo* gogo, unsigned int *palign)
|
|||
{
|
||||
if (!this->is_backend_type_size_known(gogo))
|
||||
return false;
|
||||
size_t align = gogo->backend()->type_alignment(this->get_backend(gogo));
|
||||
Btype* bt = this->get_backend_placeholder(gogo);
|
||||
size_t align = gogo->backend()->type_alignment(bt);
|
||||
*palign = static_cast<unsigned int>(align);
|
||||
if (*palign != align)
|
||||
return false;
|
||||
|
@ -2089,7 +2296,8 @@ Type::backend_type_field_align(Gogo* gogo, unsigned int *palign)
|
|||
{
|
||||
if (!this->is_backend_type_size_known(gogo))
|
||||
return false;
|
||||
size_t a = gogo->backend()->type_field_alignment(this->get_backend(gogo));
|
||||
Btype* bt = this->get_backend_placeholder(gogo);
|
||||
size_t a = gogo->backend()->type_field_alignment(bt);
|
||||
*palign = static_cast<unsigned int>(a);
|
||||
if (*palign != a)
|
||||
return false;
|
||||
|
@ -2712,6 +2920,15 @@ String_type::do_get_backend(Gogo* gogo)
|
|||
|
||||
Type* b = gogo->lookup_global("byte")->type_value();
|
||||
Type* pb = Type::make_pointer_type(b);
|
||||
|
||||
// We aren't going to get back to this field to finish the
|
||||
// backend representation, so force it to be finished now.
|
||||
if (!gogo->named_types_are_converted())
|
||||
{
|
||||
pb->get_backend_placeholder(gogo);
|
||||
pb->finish_backend(gogo);
|
||||
}
|
||||
|
||||
fields[0].name = "__data";
|
||||
fields[0].btype = pb->get_backend(gogo);
|
||||
fields[0].location = Linemap::predeclared_location();
|
||||
|
@ -3117,7 +3334,7 @@ Function_type::do_hash_for_method(Gogo* gogo) const
|
|||
// Get the backend representation for a function type.
|
||||
|
||||
Btype*
|
||||
Function_type::get_function_backend(Gogo* gogo)
|
||||
Function_type::do_get_backend(Gogo* gogo)
|
||||
{
|
||||
Backend::Btyped_identifier breceiver;
|
||||
if (this->receiver_ != NULL)
|
||||
|
@ -3169,46 +3386,6 @@ Function_type::get_function_backend(Gogo* gogo)
|
|||
this->location());
|
||||
}
|
||||
|
||||
// A hash table mapping function types to their backend placeholders.
|
||||
|
||||
Function_type::Placeholders Function_type::placeholders;
|
||||
|
||||
// Get the backend representation for a function type. If we are
|
||||
// still converting types, and this types has multiple results, return
|
||||
// a placeholder instead. We do this because for multiple results we
|
||||
// build a struct, and we need to make sure that all the types in the
|
||||
// struct are valid before we create the struct.
|
||||
|
||||
Btype*
|
||||
Function_type::do_get_backend(Gogo* gogo)
|
||||
{
|
||||
if (!gogo->named_types_are_converted()
|
||||
&& this->results_ != NULL
|
||||
&& this->results_->size() > 1)
|
||||
{
|
||||
Btype* placeholder =
|
||||
gogo->backend()->placeholder_pointer_type("", this->location(), true);
|
||||
Function_type::placeholders.push_back(std::make_pair(this, placeholder));
|
||||
return placeholder;
|
||||
}
|
||||
return this->get_function_backend(gogo);
|
||||
}
|
||||
|
||||
// Convert function types after all named types are converted.
|
||||
|
||||
void
|
||||
Function_type::convert_types(Gogo* gogo)
|
||||
{
|
||||
for (Placeholders::const_iterator p = Function_type::placeholders.begin();
|
||||
p != Function_type::placeholders.end();
|
||||
++p)
|
||||
{
|
||||
Btype* bt = p->first->get_function_backend(gogo);
|
||||
if (!gogo->backend()->set_placeholder_function_type(p->second, bt))
|
||||
go_assert(saw_errors());
|
||||
}
|
||||
}
|
||||
|
||||
// The type of a function type descriptor.
|
||||
|
||||
Type*
|
||||
|
@ -4346,6 +4523,7 @@ Struct_type::method_function(const std::string& name, bool* is_ambiguous) const
|
|||
|
||||
static void
|
||||
get_backend_struct_fields(Gogo* gogo, const Struct_field_list* fields,
|
||||
bool use_placeholder,
|
||||
std::vector<Backend::Btyped_identifier>* bfields)
|
||||
{
|
||||
bfields->resize(fields->size());
|
||||
|
@ -4355,7 +4533,9 @@ get_backend_struct_fields(Gogo* gogo, const Struct_field_list* fields,
|
|||
++p, ++i)
|
||||
{
|
||||
(*bfields)[i].name = Gogo::unpack_hidden_name(p->field_name());
|
||||
(*bfields)[i].btype = p->type()->get_backend(gogo);
|
||||
(*bfields)[i].btype = (use_placeholder
|
||||
? p->type()->get_backend_placeholder(gogo)
|
||||
: p->type()->get_backend(gogo));
|
||||
(*bfields)[i].location = p->location();
|
||||
}
|
||||
go_assert(i == fields->size());
|
||||
|
@ -4367,10 +4547,25 @@ Btype*
|
|||
Struct_type::do_get_backend(Gogo* gogo)
|
||||
{
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_struct_fields(gogo, this->fields_, &bfields);
|
||||
get_backend_struct_fields(gogo, this->fields_, false, &bfields);
|
||||
return gogo->backend()->struct_type(bfields);
|
||||
}
|
||||
|
||||
// Finish the backend representation of the fields of a struct.
|
||||
|
||||
void
|
||||
Struct_type::finish_backend_fields(Gogo* gogo)
|
||||
{
|
||||
const Struct_field_list* fields = this->fields_;
|
||||
if (fields != NULL)
|
||||
{
|
||||
for (Struct_field_list::const_iterator p = fields->begin();
|
||||
p != fields->end();
|
||||
++p)
|
||||
p->type()->get_backend(gogo);
|
||||
}
|
||||
}
|
||||
|
||||
// The type of a struct type descriptor.
|
||||
|
||||
Type*
|
||||
|
@ -4776,8 +4971,8 @@ Struct_type::backend_field_offset(Gogo* gogo, unsigned int index,
|
|||
{
|
||||
if (!this->is_backend_type_size_known(gogo))
|
||||
return false;
|
||||
size_t offset = gogo->backend()->type_field_offset(this->get_backend(gogo),
|
||||
index);
|
||||
Btype* bt = this->get_backend_placeholder(gogo);
|
||||
size_t offset = gogo->backend()->type_field_offset(bt, index);
|
||||
*poffset = static_cast<unsigned int>(offset);
|
||||
if (*poffset != offset)
|
||||
return false;
|
||||
|
@ -5295,13 +5490,15 @@ Array_type::get_length_tree(Gogo* gogo)
|
|||
// size which does not fit in int.
|
||||
|
||||
static void
|
||||
get_backend_slice_fields(Gogo* gogo, Array_type* type,
|
||||
get_backend_slice_fields(Gogo* gogo, Array_type* type, bool use_placeholder,
|
||||
std::vector<Backend::Btyped_identifier>* bfields)
|
||||
{
|
||||
bfields->resize(3);
|
||||
|
||||
Type* pet = Type::make_pointer_type(type->element_type());
|
||||
Btype* pbet = pet->get_backend(gogo);
|
||||
Btype* pbet = (use_placeholder
|
||||
? pet->get_backend_placeholder(gogo)
|
||||
: pet->get_backend(gogo));
|
||||
Location ploc = Linemap::predeclared_location();
|
||||
|
||||
Backend::Btyped_identifier* p = &(*bfields)[0];
|
||||
|
@ -5333,12 +5530,12 @@ Array_type::do_get_backend(Gogo* gogo)
|
|||
if (this->length_ == NULL)
|
||||
{
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_slice_fields(gogo, this, &bfields);
|
||||
get_backend_slice_fields(gogo, this, false, &bfields);
|
||||
return gogo->backend()->struct_type(bfields);
|
||||
}
|
||||
else
|
||||
{
|
||||
Btype* element = this->get_backend_element(gogo);
|
||||
Btype* element = this->get_backend_element(gogo, false);
|
||||
Bexpression* len = this->get_backend_length(gogo);
|
||||
return gogo->backend()->array_type(element, len);
|
||||
}
|
||||
|
@ -5347,9 +5544,12 @@ Array_type::do_get_backend(Gogo* gogo)
|
|||
// Return the backend representation of the element type.
|
||||
|
||||
Btype*
|
||||
Array_type::get_backend_element(Gogo* gogo)
|
||||
Array_type::get_backend_element(Gogo* gogo, bool use_placeholder)
|
||||
{
|
||||
return this->element_type_->get_backend(gogo);
|
||||
if (use_placeholder)
|
||||
return this->element_type_->get_backend_placeholder(gogo);
|
||||
else
|
||||
return this->element_type_->get_backend(gogo);
|
||||
}
|
||||
|
||||
// Return the backend representation of the length.
|
||||
|
@ -5360,6 +5560,22 @@ Array_type::get_backend_length(Gogo* gogo)
|
|||
return tree_to_expr(this->get_length_tree(gogo));
|
||||
}
|
||||
|
||||
// Finish backend representation of the array.
|
||||
|
||||
void
|
||||
Array_type::finish_backend_element(Gogo* gogo)
|
||||
{
|
||||
Type* et = this->array_type()->element_type();
|
||||
et->get_backend(gogo);
|
||||
if (this->is_slice_type())
|
||||
{
|
||||
// This relies on the fact that we always use the same
|
||||
// structure for a pointer to any given type.
|
||||
Type* pet = Type::make_pointer_type(et);
|
||||
pet->get_backend(gogo);
|
||||
}
|
||||
}
|
||||
|
||||
// Return a tree for a pointer to the values in ARRAY.
|
||||
|
||||
tree
|
||||
|
@ -6652,6 +6868,7 @@ Interface_type::get_backend_empty_interface_type(Gogo* gogo)
|
|||
|
||||
static void
|
||||
get_backend_interface_fields(Gogo* gogo, Interface_type* type,
|
||||
bool use_placeholder,
|
||||
std::vector<Backend::Btyped_identifier>* bfields)
|
||||
{
|
||||
Location loc = type->location();
|
||||
|
@ -6670,7 +6887,9 @@ get_backend_interface_fields(Gogo* gogo, Interface_type* type,
|
|||
++p, ++i)
|
||||
{
|
||||
mfields[i].name = Gogo::unpack_hidden_name(p->name());
|
||||
mfields[i].btype = p->type()->get_backend(gogo);
|
||||
mfields[i].btype = (use_placeholder
|
||||
? p->type()->get_backend_placeholder(gogo)
|
||||
: p->type()->get_backend(gogo));
|
||||
mfields[i].location = loc;
|
||||
// Sanity check: the names should be sorted.
|
||||
go_assert(p->name() > last_name);
|
||||
|
@ -6710,7 +6929,7 @@ Interface_type::do_get_backend(Gogo* gogo)
|
|||
this->interface_btype_ =
|
||||
gogo->backend()->placeholder_struct_type("", this->location_);
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_interface_fields(gogo, this, &bfields);
|
||||
get_backend_interface_fields(gogo, this, false, &bfields);
|
||||
if (!gogo->backend()->set_placeholder_struct_type(this->interface_btype_,
|
||||
bfields))
|
||||
this->interface_btype_ = gogo->backend()->error_type();
|
||||
|
@ -6718,6 +6937,24 @@ Interface_type::do_get_backend(Gogo* gogo)
|
|||
}
|
||||
}
|
||||
|
||||
// Finish the backend representation of the methods.
|
||||
|
||||
void
|
||||
Interface_type::finish_backend_methods(Gogo* gogo)
|
||||
{
|
||||
if (!this->interface_type()->is_empty())
|
||||
{
|
||||
const Typed_identifier_list* methods = this->methods();
|
||||
if (methods != NULL)
|
||||
{
|
||||
for (Typed_identifier_list::const_iterator p = methods->begin();
|
||||
p != methods->end();
|
||||
++p)
|
||||
p->type()->get_backend(gogo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The type of an interface type descriptor.
|
||||
|
||||
Type*
|
||||
|
@ -7751,7 +7988,7 @@ Named_type::convert(Gogo* gogo)
|
|||
{
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_struct_fields(gogo, base->struct_type()->fields(),
|
||||
&bfields);
|
||||
true, &bfields);
|
||||
if (!gogo->backend()->set_placeholder_struct_type(bt, bfields))
|
||||
bt = gogo->backend()->error_type();
|
||||
}
|
||||
|
@ -7761,7 +7998,7 @@ Named_type::convert(Gogo* gogo)
|
|||
// Slice types were completed in create_placeholder.
|
||||
if (!base->is_slice_type())
|
||||
{
|
||||
Btype* bet = base->array_type()->get_backend_element(gogo);
|
||||
Btype* bet = base->array_type()->get_backend_element(gogo, true);
|
||||
Bexpression* blen = base->array_type()->get_backend_length(gogo);
|
||||
if (!gogo->backend()->set_placeholder_array_type(bt, bet, blen))
|
||||
bt = gogo->backend()->error_type();
|
||||
|
@ -7893,7 +8130,7 @@ Named_type::create_placeholder(Gogo* gogo)
|
|||
// because we can fill them in completely here with the final
|
||||
// size.
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_slice_fields(gogo, base->array_type(), &bfields);
|
||||
get_backend_slice_fields(gogo, base->array_type(), true, &bfields);
|
||||
if (!gogo->backend()->set_placeholder_struct_type(bt, bfields))
|
||||
this->named_btype_ = gogo->backend()->error_type();
|
||||
}
|
||||
|
@ -7904,7 +8141,8 @@ Named_type::create_placeholder(Gogo* gogo)
|
|||
// because we can fill them in completely here with the final
|
||||
// size.
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_interface_fields(gogo, base->interface_type(), &bfields);
|
||||
get_backend_interface_fields(gogo, base->interface_type(), true,
|
||||
&bfields);
|
||||
if (!gogo->backend()->set_placeholder_struct_type(bt, bfields))
|
||||
this->named_btype_ = gogo->backend()->error_type();
|
||||
}
|
||||
|
@ -7963,9 +8201,33 @@ Named_type::do_get_backend(Gogo* gogo)
|
|||
case TYPE_NIL:
|
||||
case TYPE_MAP:
|
||||
case TYPE_CHANNEL:
|
||||
return bt;
|
||||
|
||||
case TYPE_STRUCT:
|
||||
if (!this->seen_in_get_backend_)
|
||||
{
|
||||
this->seen_in_get_backend_ = true;
|
||||
base->struct_type()->finish_backend_fields(gogo);
|
||||
this->seen_in_get_backend_ = false;
|
||||
}
|
||||
return bt;
|
||||
|
||||
case TYPE_ARRAY:
|
||||
if (!this->seen_in_get_backend_)
|
||||
{
|
||||
this->seen_in_get_backend_ = true;
|
||||
base->array_type()->finish_backend_element(gogo);
|
||||
this->seen_in_get_backend_ = false;
|
||||
}
|
||||
return bt;
|
||||
|
||||
case TYPE_INTERFACE:
|
||||
if (!this->seen_in_get_backend_)
|
||||
{
|
||||
this->seen_in_get_backend_ = true;
|
||||
base->interface_type()->finish_backend_methods(gogo);
|
||||
this->seen_in_get_backend_ = false;
|
||||
}
|
||||
return bt;
|
||||
|
||||
case TYPE_FUNCTION:
|
||||
|
|
|
@ -852,6 +852,16 @@ class Type
|
|||
Btype*
|
||||
get_backend(Gogo*);
|
||||
|
||||
// Return a placeholder for the backend representation of the type.
|
||||
// This will return a type of the correct size, but for which some
|
||||
// of the fields may still need to be completed.
|
||||
Btype*
|
||||
get_backend_placeholder(Gogo*);
|
||||
|
||||
// Finish the backend representation of a placeholder.
|
||||
void
|
||||
finish_backend(Gogo*);
|
||||
|
||||
// Build a type descriptor entry for this type. Return a pointer to
|
||||
// it. The location is the location which causes us to need the
|
||||
// entry.
|
||||
|
@ -1179,6 +1189,9 @@ class Type
|
|||
|
||||
// The type classification.
|
||||
Type_classification classification_;
|
||||
// Whether btype_ is a placeholder type used while named types are
|
||||
// being converted.
|
||||
bool btype_is_placeholder_;
|
||||
// The backend representation of the type, once it has been
|
||||
// determined.
|
||||
Btype* btype_;
|
||||
|
@ -1730,10 +1743,6 @@ class Function_type : public Type
|
|||
Function_type*
|
||||
copy_with_receiver(Type*) const;
|
||||
|
||||
// Finishing converting function types.
|
||||
static void
|
||||
convert_types(Gogo*);
|
||||
|
||||
static Type*
|
||||
make_function_type_descriptor_type();
|
||||
|
||||
|
@ -1773,16 +1782,6 @@ class Function_type : public Type
|
|||
type_descriptor_params(Type*, const Typed_identifier*,
|
||||
const Typed_identifier_list*);
|
||||
|
||||
Btype*
|
||||
get_function_backend(Gogo*);
|
||||
|
||||
// A list of function types with multiple results and their
|
||||
// placeholder backend representations, used to postpone building
|
||||
// the structs we use for multiple results until all types are
|
||||
// converted.
|
||||
typedef std::vector<std::pair<Function_type*, Btype*> > Placeholders;
|
||||
static Placeholders placeholders;
|
||||
|
||||
// The receiver name and type. This will be NULL for a normal
|
||||
// function, non-NULL for a method.
|
||||
Typed_identifier* receiver_;
|
||||
|
@ -2079,6 +2078,10 @@ class Struct_type : public Type
|
|||
bool
|
||||
backend_field_offset(Gogo*, unsigned int index, unsigned int* poffset);
|
||||
|
||||
// Finish the backend representation of all the fields.
|
||||
void
|
||||
finish_backend_fields(Gogo*);
|
||||
|
||||
// Import a struct type.
|
||||
static Struct_type*
|
||||
do_import(Import*);
|
||||
|
@ -2193,12 +2196,16 @@ class Array_type : public Type
|
|||
|
||||
// Return the backend representation of the element type.
|
||||
Btype*
|
||||
get_backend_element(Gogo*);
|
||||
get_backend_element(Gogo*, bool use_placeholder);
|
||||
|
||||
// Return the backend representation of the length.
|
||||
Bexpression*
|
||||
get_backend_length(Gogo*);
|
||||
|
||||
// Finish the backend representation of the element type.
|
||||
void
|
||||
finish_backend_element(Gogo*);
|
||||
|
||||
static Type*
|
||||
make_array_type_descriptor_type();
|
||||
|
||||
|
@ -2521,6 +2528,10 @@ class Interface_type : public Type
|
|||
static Btype*
|
||||
get_backend_empty_interface_type(Gogo*);
|
||||
|
||||
// Finish the backend representation of the method types.
|
||||
void
|
||||
finish_backend_methods(Gogo*);
|
||||
|
||||
static Type*
|
||||
make_interface_type_descriptor_type();
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue