@@ -293,19 +293,25 @@
// object type: a list of function pointers for each interface
// method.
Named_type* rhs_named_type = rhs_type->named_type();
+ Struct_type* rhs_struct_type = rhs_type->struct_type();
bool is_pointer = false;
- if (rhs_named_type == NULL)
+ if (rhs_named_type == NULL && rhs_struct_type == NULL)
{
rhs_named_type = rhs_type->deref()->named_type();
+ rhs_struct_type = rhs_type->deref()->struct_type();
is_pointer = true;
}
tree method_table;
- if (rhs_named_type == NULL)
- method_table = null_pointer_node;
- else
+ if (rhs_named_type != NULL)
method_table =
rhs_named_type->interface_method_table(gogo, lhs_interface_type,
is_pointer);
+ else if (rhs_struct_type != NULL)
+ method_table =
+ rhs_struct_type->interface_method_table(gogo, lhs_interface_type,
+ is_pointer);
+ else
+ method_table = null_pointer_node;
first_field_value = fold_convert_loc(location.gcc_location(),
const_ptr_type_node, method_table);
}
@@ -2128,8 +2128,7 @@
tree
Gogo::interface_method_table_for_type(const Interface_type* interface,
- Named_type* type,
- bool is_pointer)
+ Type* type, bool is_pointer)
{
const Typed_identifier_list* interface_methods = interface->methods();
go_assert(!interface_methods->empty());
@@ -2158,7 +2157,9 @@
// interface. If the interface has hidden methods, and the named
// type is defined in a different package, then the interface
// conversion table will be defined by that other package.
- if (has_hidden_methods && type->named_object()->package() != NULL)
+ if (has_hidden_methods
+ && type->named_type() != NULL
+ && type->named_type()->named_object()->package() != NULL)
{
tree array_type = build_array_type(const_ptr_type_node, NULL);
tree decl = build_decl(BUILTINS_LOCATION, VAR_DECL, id, array_type);
@@ -2187,13 +2188,20 @@
Linemap::predeclared_location());
elt->value = fold_convert(const_ptr_type_node, tdp);
+ Named_type* nt = type->named_type();
+ Struct_type* st = type->struct_type();
+ go_assert(nt != NULL || st != NULL);
size_t i = 1;
for (Typed_identifier_list::const_iterator p = interface_methods->begin();
p != interface_methods->end();
++p, ++i)
{
bool is_ambiguous;
- Method* m = type->method_function(p->name(), &is_ambiguous);
+ Method* m;
+ if (nt != NULL)
+ m = nt->method_function(p->name(), &is_ambiguous);
+ else
+ m = st->method_function(p->name(), &is_ambiguous);
go_assert(m != NULL);
Named_object* no = m->named_object();
@@ -2872,7 +2872,8 @@
Build_method_tables::type(Type* type)
{
Named_type* nt = type->named_type();
- if (nt != NULL)
+ Struct_type* st = type->struct_type();
+ if (nt != NULL || st != NULL)
{
for (std::vector<Interface_type*>::const_iterator p =
this->interfaces_.begin();
@@ -2882,10 +2883,23 @@
// We ask whether a pointer to the named type implements the
// interface, because a pointer can implement more methods
// than a value.
- if ((*p)->implements_interface(Type::make_pointer_type(nt), NULL))
+ if (nt != NULL)
{
- nt->interface_method_table(this->gogo_, *p, false);
- nt->interface_method_table(this->gogo_, *p, true);
+ if ((*p)->implements_interface(Type::make_pointer_type(nt),
+ NULL))
+ {
+ nt->interface_method_table(this->gogo_, *p, false);
+ nt->interface_method_table(this->gogo_, *p, true);
+ }
+ }
+ else
+ {
+ if ((*p)->implements_interface(Type::make_pointer_type(st),
+ NULL))
+ {
+ st->interface_method_table(this->gogo_, *p, false);
+ st->interface_method_table(this->gogo_, *p, true);
+ }
}
}
}
@@ -574,7 +574,7 @@
// Build an interface method table for a type: a list of function
// pointers, one for each interface method. This returns a decl.
tree
- interface_method_table_for_type(const Interface_type*, Named_type*,
+ interface_method_table_for_type(const Interface_type*, Type*,
bool is_pointer);
// Return a tree which allocate SIZE bytes to hold values of type
@@ -4554,6 +4554,20 @@
return Type::method_function(this->all_methods_, name, is_ambiguous);
}
+// Return a pointer to the interface method table for this type for
+// the interface INTERFACE. IS_POINTER is true if this is for a
+// pointer to THIS.
+
+tree
+Struct_type::interface_method_table(Gogo* gogo,
+ const Interface_type* interface,
+ bool is_pointer)
+{
+ return Type::interface_method_table(gogo, this, interface, is_pointer,
+ &this->interface_method_tables_,
+ &this->pointer_interface_method_tables_);
+}
+
// Convert struct fields to the backend representation. This is not
// declared in types.h so that types.h doesn't have to #include
// backend.h.
@@ -7182,7 +7196,17 @@
{
if (!p->name().empty())
{
- std::string n = Gogo::unpack_hidden_name(p->name());
+ std::string n;
+ if (!Gogo::is_hidden_name(p->name()))
+ n = p->name();
+ else
+ {
+ n = ".";
+ std::string pkgpath = Gogo::hidden_name_pkgpath(p->name());
+ n.append(Gogo::pkgpath_for_symbol(pkgpath));
+ n.append(1, '.');
+ n.append(Gogo::unpack_hidden_name(p->name()));
+ }
char buf[20];
snprintf(buf, sizeof buf, "%u_",
static_cast<unsigned int>(n.length()));
@@ -7735,32 +7759,9 @@
Named_type::interface_method_table(Gogo* gogo, const Interface_type* interface,
bool is_pointer)
{
- go_assert(!interface->is_empty());
-
- Interface_method_tables** pimt = (is_pointer
- ? &this->interface_method_tables_
- : &this->pointer_interface_method_tables_);
-
- if (*pimt == NULL)
- *pimt = new Interface_method_tables(5);
-
- std::pair<const Interface_type*, tree> val(interface, NULL_TREE);
- std::pair<Interface_method_tables::iterator, bool> ins = (*pimt)->insert(val);
-
- if (ins.second)
- {
- // This is a new entry in the hash table.
- go_assert(ins.first->second == NULL_TREE);
- ins.first->second = gogo->interface_method_table_for_type(interface,
- this,
- is_pointer);
- }
-
- tree decl = ins.first->second;
- if (decl == error_mark_node)
- return error_mark_node;
- go_assert(decl != NULL_TREE && TREE_CODE(decl) == VAR_DECL);
- return build_fold_addr_expr(decl);
+ return Type::interface_method_table(gogo, this, interface, is_pointer,
+ &this->interface_method_tables_,
+ &this->pointer_interface_method_tables_);
}
// Return whether a named type has any hidden fields.
@@ -8944,6 +8945,42 @@
return m;
}
+// Return a pointer to the interface method table for TYPE for the
+// interface INTERFACE.
+
+tree
+Type::interface_method_table(Gogo* gogo, Type* type,
+ const Interface_type *interface,
+ bool is_pointer,
+ Interface_method_tables** method_tables,
+ Interface_method_tables** pointer_tables)
+{
+ go_assert(!interface->is_empty());
+
+ Interface_method_tables** pimt = is_pointer ? method_tables : pointer_tables;
+
+ if (*pimt == NULL)
+ *pimt = new Interface_method_tables(5);
+
+ std::pair<const Interface_type*, tree> val(interface, NULL_TREE);
+ std::pair<Interface_method_tables::iterator, bool> ins = (*pimt)->insert(val);
+
+ if (ins.second)
+ {
+ // This is a new entry in the hash table.
+ go_assert(ins.first->second == NULL_TREE);
+ ins.first->second = gogo->interface_method_table_for_type(interface,
+ type,
+ is_pointer);
+ }
+
+ tree decl = ins.first->second;
+ if (decl == error_mark_node)
+ return error_mark_node;
+ go_assert(decl != NULL_TREE && TREE_CODE(decl) == VAR_DECL);
+ return build_fold_addr_expr(decl);
+}
+
// Look for field or method NAME for TYPE. Return an Expression for
// the field or method bound to EXPR. If there is no such field or
// method, give an appropriate error and return an error expression.
@@ -983,6 +983,19 @@
method_function(const Methods*, const std::string& name,
bool* is_ambiguous);
+ // A mapping from interfaces to the associated interface method
+ // tables for this type. This maps to a decl.
+ typedef Unordered_map_hash(const Interface_type*, tree, Type_hash_identical,
+ Type_identical) Interface_method_tables;
+
+ // Return a pointer to the interface method table for TYPE for the
+ // interface INTERFACE.
+ static tree
+ interface_method_table(Gogo* gogo, Type* type,
+ const Interface_type *interface, bool is_pointer,
+ Interface_method_tables** method_tables,
+ Interface_method_tables** pointer_tables);
+
// Return a composite literal for the type descriptor entry for a
// type.
static Expression*
@@ -1994,7 +2007,8 @@
public:
Struct_type(Struct_field_list* fields, Location location)
: Type(TYPE_STRUCT),
- fields_(fields), location_(location), all_methods_(NULL)
+ fields_(fields), location_(location), all_methods_(NULL),
+ interface_method_tables_(NULL), pointer_interface_method_tables_(NULL)
{ }
// Return the field NAME. This only looks at local fields, not at
@@ -2076,6 +2090,14 @@
Method*
method_function(const std::string& name, bool* is_ambiguous) const;
+ // Return a pointer to the interface method table for this type for
+ // the interface INTERFACE. If IS_POINTER is true, set the type
+ // descriptor to a pointer to this type, otherwise set it to this
+ // type.
+ tree
+ interface_method_table(Gogo*, const Interface_type* interface,
+ bool is_pointer);
+
// Traverse just the field types of a struct type.
int
traverse_field_types(Traverse* traverse)
@@ -2156,6 +2178,13 @@
Location location_;
// If this struct is unnamed, a list of methods.
Methods* all_methods_;
+ // A mapping from interfaces to the associated interface method
+ // tables for this type. Only used if this struct is unnamed.
+ Interface_method_tables* interface_method_tables_;
+ // A mapping from interfaces to the associated interface method
+ // tables for pointers to this type. Only used if this struct is
+ // unnamed.
+ Interface_method_tables* pointer_interface_method_tables_;
};
// The type of an array.
@@ -2861,11 +2890,6 @@
void
create_placeholder(Gogo*);
- // A mapping from interfaces to the associated interface method
- // tables for this type. This maps to a decl.
- typedef Unordered_map_hash(const Interface_type*, tree, Type_hash_identical,
- Type_identical) Interface_method_tables;
-
// A pointer back to the Named_object for this type.
Named_object* named_object_;
// If this type is defined in a function, a pointer back to the