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:
parent
0c2b1bb7b6
commit
6f07319115
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user