compiler: Fix bug converting unnamed types with placeholders.
From-SVN: r194011
This commit is contained in:
parent
55ad8d77ab
commit
8ccaff35d4
|
@ -45,8 +45,7 @@ get_backend_interface_fields(Gogo* gogo, Interface_type* type,
|
|||
// Class Type.
|
||||
|
||||
Type::Type(Type_classification classification)
|
||||
: classification_(classification), btype_is_placeholder_(false),
|
||||
btype_(NULL), type_descriptor_var_(NULL)
|
||||
: classification_(classification), btype_(NULL), type_descriptor_var_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -910,11 +909,7 @@ Btype*
|
|||
Type::get_backend(Gogo* gogo)
|
||||
{
|
||||
if (this->btype_ != NULL)
|
||||
{
|
||||
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)
|
||||
|
@ -928,20 +923,36 @@ Type::get_backend(Gogo* gogo)
|
|||
// that. There is no need to use the hash table for named types, as
|
||||
// named types are only identical to themselves.
|
||||
|
||||
std::pair<Type*, Btype*> val(this, NULL);
|
||||
std::pair<Type*, Type_btype_entry> val;
|
||||
val.first = this;
|
||||
val.second.btype = NULL;
|
||||
val.second.is_placeholder = false;
|
||||
std::pair<Type_btypes::iterator, bool> ins =
|
||||
Type::type_btypes.insert(val);
|
||||
if (!ins.second && ins.first->second != NULL)
|
||||
if (!ins.second && ins.first->second.btype != NULL)
|
||||
{
|
||||
if (gogo != NULL && gogo->named_types_are_converted())
|
||||
this->btype_ = ins.first->second;
|
||||
return ins.first->second;
|
||||
// Note that GOGO can be NULL here, but only when the GCC
|
||||
// middle-end is asking for a frontend type. That will only
|
||||
// happen for simple types, which should never require
|
||||
// placeholders.
|
||||
if (!ins.first->second.is_placeholder)
|
||||
this->btype_ = ins.first->second.btype;
|
||||
else if (gogo->named_types_are_converted())
|
||||
{
|
||||
this->finish_backend(gogo, ins.first->second.btype);
|
||||
ins.first->second.is_placeholder = false;
|
||||
}
|
||||
|
||||
return ins.first->second.btype;
|
||||
}
|
||||
|
||||
Btype* bt = this->get_btype_without_hash(gogo);
|
||||
|
||||
if (ins.first->second == NULL)
|
||||
ins.first->second = bt;
|
||||
if (ins.first->second.btype == NULL)
|
||||
{
|
||||
ins.first->second.btype = bt;
|
||||
ins.first->second.is_placeholder = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have already created a backend representation for this
|
||||
|
@ -949,10 +960,9 @@ Type::get_backend(Gogo* gogo)
|
|||
// a named type which in turns uses an identical unnamed type.
|
||||
// Use the tree we created earlier and ignore the one we just
|
||||
// built.
|
||||
bt = ins.first->second;
|
||||
if (gogo == NULL || !gogo->named_types_are_converted())
|
||||
return bt;
|
||||
this->btype_ = bt;
|
||||
if (this->btype_ == bt)
|
||||
this->btype_ = ins.first->second.btype;
|
||||
bt = ins.first->second.btype;
|
||||
}
|
||||
|
||||
return bt;
|
||||
|
@ -1019,6 +1029,37 @@ Type::get_backend_placeholder(Gogo* gogo)
|
|||
// These are simple types that can just be created directly.
|
||||
return this->get_backend(gogo);
|
||||
|
||||
case TYPE_MAP:
|
||||
case TYPE_CHANNEL:
|
||||
// All maps and channels have the same backend representation.
|
||||
return this->get_backend(gogo);
|
||||
|
||||
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_INTERFACE:
|
||||
if (this->interface_type()->is_empty())
|
||||
return Interface_type::get_backend_empty_interface_type(gogo);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::pair<Type*, Type_btype_entry> val;
|
||||
val.first = this;
|
||||
val.second.btype = NULL;
|
||||
val.second.is_placeholder = false;
|
||||
std::pair<Type_btypes::iterator, bool> ins =
|
||||
Type::type_btypes.insert(val);
|
||||
if (!ins.second && ins.first->second.btype != NULL)
|
||||
return ins.first->second.btype;
|
||||
|
||||
switch (this->classification_)
|
||||
{
|
||||
case TYPE_FUNCTION:
|
||||
{
|
||||
Location loc = this->function_type()->location();
|
||||
|
@ -1061,16 +1102,9 @@ Type::get_backend_placeholder(Gogo* gogo)
|
|||
}
|
||||
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
|
||||
{
|
||||
go_assert(!this->interface_type()->is_empty());
|
||||
std::vector<Backend::Btyped_identifier> bfields;
|
||||
get_backend_interface_fields(gogo, this->interface_type(), true,
|
||||
&bfields);
|
||||
|
@ -1078,20 +1112,26 @@ Type::get_backend_placeholder(Gogo* gogo)
|
|||
}
|
||||
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:
|
||||
/* Note that various classifications were handled in the earlier
|
||||
switch. */
|
||||
default:
|
||||
go_unreachable();
|
||||
}
|
||||
|
||||
this->btype_ = bt;
|
||||
this->btype_is_placeholder_ = true;
|
||||
if (ins.first->second.btype == NULL)
|
||||
{
|
||||
ins.first->second.btype = bt;
|
||||
ins.first->second.is_placeholder = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// A placeholder for this type got created along the way. Use
|
||||
// that one and ignore the one we just built.
|
||||
bt = ins.first->second.btype;
|
||||
}
|
||||
|
||||
return bt;
|
||||
}
|
||||
|
||||
|
@ -1099,12 +1139,8 @@ Type::get_backend_placeholder(Gogo* gogo)
|
|||
// using a placeholder type.
|
||||
|
||||
void
|
||||
Type::finish_backend(Gogo* gogo)
|
||||
Type::finish_backend(Gogo* gogo, Btype *placeholder)
|
||||
{
|
||||
go_assert(this->btype_ != NULL);
|
||||
if (!this->btype_is_placeholder_)
|
||||
return;
|
||||
|
||||
switch (this->classification_)
|
||||
{
|
||||
case TYPE_ERROR:
|
||||
|
@ -1120,7 +1156,7 @@ Type::finish_backend(Gogo* gogo)
|
|||
case TYPE_FUNCTION:
|
||||
{
|
||||
Btype* bt = this->do_get_backend(gogo);
|
||||
if (!gogo->backend()->set_placeholder_function_type(this->btype_, bt))
|
||||
if (!gogo->backend()->set_placeholder_function_type(placeholder, bt))
|
||||
go_assert(saw_errors());
|
||||
}
|
||||
break;
|
||||
|
@ -1128,7 +1164,7 @@ Type::finish_backend(Gogo* gogo)
|
|||
case TYPE_POINTER:
|
||||
{
|
||||
Btype* bt = this->do_get_backend(gogo);
|
||||
if (!gogo->backend()->set_placeholder_pointer_type(this->btype_, bt))
|
||||
if (!gogo->backend()->set_placeholder_pointer_type(placeholder, bt))
|
||||
go_assert(saw_errors());
|
||||
}
|
||||
break;
|
||||
|
@ -1165,7 +1201,7 @@ Type::finish_backend(Gogo* gogo)
|
|||
go_unreachable();
|
||||
}
|
||||
|
||||
this->btype_is_placeholder_ = false;
|
||||
this->btype_ = placeholder;
|
||||
}
|
||||
|
||||
// Return a pointer to the type descriptor for this type.
|
||||
|
@ -2968,8 +3004,8 @@ String_type::do_get_backend(Gogo* gogo)
|
|||
// backend representation, so force it to be finished now.
|
||||
if (!gogo->named_types_are_converted())
|
||||
{
|
||||
pb->get_backend_placeholder(gogo);
|
||||
pb->finish_backend(gogo);
|
||||
Btype* bt = pb->get_backend_placeholder(gogo);
|
||||
pb->finish_backend(gogo, bt);
|
||||
}
|
||||
|
||||
fields[0].name = "__data";
|
||||
|
|
|
@ -888,7 +888,7 @@ class Type
|
|||
|
||||
// Finish the backend representation of a placeholder.
|
||||
void
|
||||
finish_backend(Gogo*);
|
||||
finish_backend(Gogo*, Btype*);
|
||||
|
||||
// Build a type descriptor entry for this type. Return a pointer to
|
||||
// it. The location is the location which causes us to need the
|
||||
|
@ -1210,10 +1210,18 @@ class Type
|
|||
Btype*
|
||||
get_btype_without_hash(Gogo*);
|
||||
|
||||
// A backend type that may be a placeholder.
|
||||
struct Type_btype_entry
|
||||
{
|
||||
Btype *btype;
|
||||
bool is_placeholder;
|
||||
};
|
||||
|
||||
// A mapping from Type to Btype*, used to ensure that the backend
|
||||
// representation of identical types is identical.
|
||||
typedef Unordered_map_hash(const Type*, Btype*, Type_hash_identical,
|
||||
Type_identical) Type_btypes;
|
||||
// representation of identical types is identical. This is only
|
||||
// used for unnamed types.
|
||||
typedef Unordered_map_hash(const Type*, Type_btype_entry,
|
||||
Type_hash_identical, Type_identical) Type_btypes;
|
||||
|
||||
static Type_btypes type_btypes;
|
||||
|
||||
|
@ -1230,9 +1238,6 @@ 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_;
|
||||
|
|
Loading…
Reference in New Issue