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)
{
*all_methods = NULL;
Types_seen types_seen;
Type::add_methods_for_type(type, NULL, 0, false, false, &types_seen,
all_methods);
std::vector<const Named_type*> seen;
Type::add_methods_for_type(type, NULL, 0, false, false, &seen, all_methods);
Type::build_stub_methods(gogo, type, *all_methods, location);
}
@ -8944,7 +8943,7 @@ Type::add_methods_for_type(const Type* type,
unsigned int depth,
bool is_embedded_pointer,
bool needs_stub_method,
Types_seen* types_seen,
std::vector<const Named_type*>* seen,
Methods** 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();
if (nt != NULL)
{
std::pair<Types_seen::iterator, bool> ins = types_seen->insert(nt);
if (!ins.second)
return;
}
for (std::vector<const Named_type*>::const_iterator p = seen->begin();
p != seen->end();
++p)
{
if (*p == nt)
return;
}
if (nt != NULL)
Type::add_local_methods_for_type(nt, field_indexes, depth,
is_embedded_pointer, needs_stub_method,
methods);
seen->push_back(nt);
Type::add_local_methods_for_type(nt, field_indexes, depth,
is_embedded_pointer, needs_stub_method,
methods);
}
Type::add_embedded_methods_for_type(type, field_indexes, depth,
is_embedded_pointer, needs_stub_method,
types_seen, methods);
seen, methods);
// 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,
@ -8975,6 +8979,9 @@ Type::add_methods_for_type(const Type* type,
// following the usual rules for an interface type.
if (depth > 0)
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
@ -9020,7 +9027,7 @@ Type::add_embedded_methods_for_type(const Type* type,
unsigned int depth,
bool is_embedded_pointer,
bool needs_stub_method,
Types_seen* types_seen,
std::vector<const Named_type*>* seen,
Methods** methods)
{
// 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
|| is_pointer
|| i > 0),
types_seen,
seen,
methods);
}
}

View File

@ -1171,14 +1171,11 @@ class Type
static tree
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.
static void
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**);
static void
@ -1189,7 +1186,8 @@ class Type
static void
add_embedded_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**);
static void