Commit 1bfbe9ad by Ian Lance Taylor

compiler: look through aliases when looking for methods

    
    Add a Type::is_alias method to remove some existing loops and avoid
    adding a new one.
    
    Test case is https://golang.org/cl/89935.
    
    Fixes golang/go#23489
    
    Reviewed-on: https://go-review.googlesource.com/89975

From-SVN: r257069
parent a14e122a
203cbe7d3820fa03c965a01f72461f71588fe952 897ce971b06a39c217d02dce9e1361bc7a240188
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -107,6 +107,34 @@ Type::forwarded() const ...@@ -107,6 +107,34 @@ Type::forwarded() const
return t; return t;
} }
// Skip alias definitions.
Type*
Type::unalias()
{
Type* t = this->forwarded();
Named_type* nt = t->named_type();
while (nt != NULL && nt->is_alias())
{
t = nt->real_type()->forwarded();
nt = t->named_type();
}
return t;
}
const Type*
Type::unalias() const
{
const Type* t = this->forwarded();
const Named_type* nt = t->named_type();
while (nt != NULL && nt->is_alias())
{
t = nt->real_type()->forwarded();
nt = t->named_type();
}
return t;
}
// If this is a named type, return it. Otherwise, return NULL. // If this is a named type, return it. Otherwise, return NULL.
Named_type* Named_type*
...@@ -333,15 +361,9 @@ Type::are_identical_cmp_tags(const Type* t1, const Type* t2, Cmp_tags cmp_tags, ...@@ -333,15 +361,9 @@ Type::are_identical_cmp_tags(const Type* t1, const Type* t2, Cmp_tags cmp_tags,
return errors_are_identical ? true : t1 == t2; return errors_are_identical ? true : t1 == t2;
} }
// Skip defined forward declarations. // Skip defined forward declarations. Ignore aliases.
t1 = t1->forwarded(); t1 = t1->unalias();
t2 = t2->forwarded(); t2 = t2->unalias();
// Ignore aliases for purposes of type identity.
while (t1->named_type() != NULL && t1->named_type()->is_alias())
t1 = t1->named_type()->real_type()->forwarded();
while (t2->named_type() != NULL && t2->named_type()->is_alias())
t2 = t2->named_type()->real_type()->forwarded();
if (t1 == t2) if (t1 == t2)
return true; return true;
...@@ -1197,9 +1219,7 @@ Type::finish_backend(Gogo* gogo, Btype *placeholder) ...@@ -1197,9 +1219,7 @@ Type::finish_backend(Gogo* gogo, Btype *placeholder)
Bexpression* Bexpression*
Type::type_descriptor_pointer(Gogo* gogo, Location location) Type::type_descriptor_pointer(Gogo* gogo, Location location)
{ {
Type* t = this->forwarded(); Type* t = this->unalias();
while (t->named_type() != NULL && t->named_type()->is_alias())
t = t->named_type()->real_type()->forwarded();
if (t->type_descriptor_var_ == NULL) if (t->type_descriptor_var_ == NULL)
{ {
t->make_type_descriptor_var(gogo); t->make_type_descriptor_var(gogo);
...@@ -1648,10 +1668,10 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype, ...@@ -1648,10 +1668,10 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype,
Function_type* equal_fntype, Named_object** hash_fn, Function_type* equal_fntype, Named_object** hash_fn,
Named_object** equal_fn) Named_object** equal_fn)
{ {
// If this loop leaves NAME as NULL, then the type does not have a // If the unaliased type is not a named type, then the type does not
// name after all. // have a name after all.
while (name != NULL && name->is_alias()) if (name != NULL)
name = name->real_type()->named_type(); name = name->unalias()->named_type();
if (!this->is_comparable()) if (!this->is_comparable())
{ {
...@@ -2370,9 +2390,7 @@ static const int64_t max_ptrmask_bytes = 2048; ...@@ -2370,9 +2390,7 @@ static const int64_t max_ptrmask_bytes = 2048;
Bexpression* Bexpression*
Type::gc_symbol_pointer(Gogo* gogo) Type::gc_symbol_pointer(Gogo* gogo)
{ {
Type* t = this->forwarded(); Type* t = this->unalias();
while (t->named_type() != NULL && t->named_type()->is_alias())
t = t->named_type()->real_type()->forwarded();
if (!t->has_pointer()) if (!t->has_pointer())
return gogo->backend()->nil_pointer_expression(); return gogo->backend()->nil_pointer_expression();
...@@ -11494,9 +11512,9 @@ Type::find_field_or_method(const Type* type, ...@@ -11494,9 +11512,9 @@ Type::find_field_or_method(const Type* type,
std::string* ambig2) std::string* ambig2)
{ {
// Named types can have locally defined methods. // Named types can have locally defined methods.
const Named_type* nt = type->named_type(); const Named_type* nt = type->unalias()->named_type();
if (nt == NULL && type->points_to() != NULL) if (nt == NULL && type->points_to() != NULL)
nt = type->points_to()->named_type(); nt = type->points_to()->unalias()->named_type();
if (nt != NULL) if (nt != NULL)
{ {
Named_object* no = nt->find_local_method(name); Named_object* no = nt->find_local_method(name);
......
...@@ -676,6 +676,15 @@ class Type ...@@ -676,6 +676,15 @@ class Type
const Type* const Type*
forwarded() const; forwarded() const;
// Return the type skipping any alias definitions and any defined
// forward declarations. This is like forwarded, but also
// recursively expands alias definitions to the aliased type.
Type*
unalias();
const Type*
unalias() const;
// Return true if this is a basic type: a type which is not composed // Return true if this is a basic type: a type which is not composed
// of other types, and is not void. // of other types, and is not void.
bool bool
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment