compiler: Fix bug in embedded method handling.

If the same type was embedded in a struct at different levels,
only the first embedded instance was considered when building
the set of all methods.  A second instance was ignored, even
if it was at a higher level and should therefore override the
first instance.

Test case is bug485.go in master repository.

From-SVN: r210096
This commit is contained in:
Ian Lance Taylor 2014-05-06 05:33:31 +00:00
parent 0c2b1bb7b6
commit 6f07319115
2 changed files with 26 additions and 21 deletions

View File

@ -8924,9 +8924,8 @@ Type::finalize_methods(Gogo* gogo, const Type* type, Location location,
Methods** all_methods) Methods** all_methods)
{ {
*all_methods = NULL; *all_methods = NULL;
Types_seen types_seen; std::vector<const Named_type*> seen;
Type::add_methods_for_type(type, NULL, 0, false, false, &types_seen, Type::add_methods_for_type(type, NULL, 0, false, false, &seen, all_methods);
all_methods);
Type::build_stub_methods(gogo, type, *all_methods, location); Type::build_stub_methods(gogo, type, *all_methods, location);
} }
@ -8944,7 +8943,7 @@ Type::add_methods_for_type(const Type* type,
unsigned int depth, unsigned int depth,
bool is_embedded_pointer, bool is_embedded_pointer,
bool needs_stub_method, bool needs_stub_method,
Types_seen* types_seen, std::vector<const Named_type*>* seen,
Methods** methods) Methods** methods)
{ {
// Pointer types may not have methods. // Pointer types may not have methods.
@ -8954,19 +8953,24 @@ Type::add_methods_for_type(const Type* type,
const Named_type* nt = type->named_type(); const Named_type* nt = type->named_type();
if (nt != NULL) if (nt != NULL)
{ {
std::pair<Types_seen::iterator, bool> ins = types_seen->insert(nt); for (std::vector<const Named_type*>::const_iterator p = seen->begin();
if (!ins.second) p != seen->end();
return; ++p)
} {
if (*p == nt)
return;
}
if (nt != NULL) seen->push_back(nt);
Type::add_local_methods_for_type(nt, field_indexes, depth,
is_embedded_pointer, needs_stub_method, Type::add_local_methods_for_type(nt, field_indexes, depth,
methods); is_embedded_pointer, needs_stub_method,
methods);
}
Type::add_embedded_methods_for_type(type, field_indexes, depth, Type::add_embedded_methods_for_type(type, field_indexes, depth,
is_embedded_pointer, needs_stub_method, is_embedded_pointer, needs_stub_method,
types_seen, methods); seen, methods);
// If we are called with depth > 0, then we are looking at an // If we are called with depth > 0, then we are looking at an
// anonymous field of a struct. If such a field has interface type, // anonymous field of a struct. If such a field has interface type,
@ -8975,6 +8979,9 @@ Type::add_methods_for_type(const Type* type,
// following the usual rules for an interface type. // following the usual rules for an interface type.
if (depth > 0) if (depth > 0)
Type::add_interface_methods_for_type(type, field_indexes, depth, methods); Type::add_interface_methods_for_type(type, field_indexes, depth, methods);
if (nt != NULL)
seen->pop_back();
} }
// Add the local methods for the named type NT to *METHODS. The // Add the local methods for the named type NT to *METHODS. The
@ -9020,7 +9027,7 @@ Type::add_embedded_methods_for_type(const Type* type,
unsigned int depth, unsigned int depth,
bool is_embedded_pointer, bool is_embedded_pointer,
bool needs_stub_method, bool needs_stub_method,
Types_seen* types_seen, std::vector<const Named_type*>* seen,
Methods** methods) Methods** methods)
{ {
// Look for anonymous fields in TYPE. TYPE has fields if it is a // Look for anonymous fields in TYPE. TYPE has fields if it is a
@ -9064,7 +9071,7 @@ Type::add_embedded_methods_for_type(const Type* type,
(needs_stub_method (needs_stub_method
|| is_pointer || is_pointer
|| i > 0), || i > 0),
types_seen, seen,
methods); methods);
} }
} }

View File

@ -1171,14 +1171,11 @@ class Type
static tree static tree
build_receive_return_type(tree type); build_receive_return_type(tree type);
// A hash table we use to avoid infinite recursion.
typedef Unordered_set_hash(const Named_type*, Type_hash_identical,
Type_identical) Types_seen;
// Add all methods for TYPE to the list of methods for THIS. // Add all methods for TYPE to the list of methods for THIS.
static void static void
add_methods_for_type(const Type* type, const Method::Field_indexes*, add_methods_for_type(const Type* type, const Method::Field_indexes*,
unsigned int depth, bool, bool, Types_seen*, unsigned int depth, bool, bool,
std::vector<const Named_type*>*,
Methods**); Methods**);
static void static void
@ -1189,7 +1186,8 @@ class Type
static void static void
add_embedded_methods_for_type(const Type* type, add_embedded_methods_for_type(const Type* type,
const Method::Field_indexes*, const Method::Field_indexes*,
unsigned int depth, bool, bool, Types_seen*, unsigned int depth, bool, bool,
std::vector<const Named_type*>*,
Methods**); Methods**);
static void static void