diff options
Diffstat (limited to 'gcc/go/gofrontend/gogo.cc')
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index a190917512a..4a932e4600e 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -2973,26 +2973,53 @@ Finalize_methods::type(Type* t) case Type::TYPE_NAMED: { - // We have to finalize the methods of the real type first. - // But if the real type is a struct type, then we only want to - // finalize the methods of the field types, not of the struct - // type itself. We don't want to add methods to the struct, - // since it has a name. Named_type* nt = t->named_type(); Type* rt = nt->real_type(); if (rt->classification() != Type::TYPE_STRUCT) { + // Finalize the methods of the real type first. if (Type::traverse(rt, this) == TRAVERSE_EXIT) return TRAVERSE_EXIT; + + // Finalize the methods of this type. + nt->finalize_methods(this->gogo_); } else { + // We don't want to finalize the methods of a named struct + // type, as the methods should be attached to the named + // type, not the struct type. We just want to finalize + // the field types. + // + // It is possible that a field type refers indirectly to + // this type, such as via a field with function type with + // an argument or result whose type is this type. To + // avoid the cycle, first finalize the methods of any + // embedded types, which are the only types we need to + // know to finalize the methods of this type. + const Struct_field_list* fields = rt->struct_type()->fields(); + if (fields != NULL) + { + for (Struct_field_list::const_iterator pf = fields->begin(); + pf != fields->end(); + ++pf) + { + if (pf->is_anonymous()) + { + if (Type::traverse(pf->type(), this) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + } + } + } + + // Finalize the methods of this type. + nt->finalize_methods(this->gogo_); + + // Finalize all the struct fields. if (rt->struct_type()->traverse_field_types(this) == TRAVERSE_EXIT) return TRAVERSE_EXIT; } - nt->finalize_methods(this->gogo_); - // If this type is defined in a different package, then finalize the // types of all the methods, since we won't see them otherwise. if (nt->named_object()->package() != NULL && nt->has_any_methods()) |