From ba2d90b2df8bd3ac5a9c41f138bd76e486cadd50 Mon Sep 17 00:00:00 2001 From: ian Date: Thu, 25 Jan 2018 23:13:31 +0000 Subject: [PATCH] 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 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257069 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/types.cc | 60 ++++++++++++++++++++++++++++++---------------- gcc/go/gofrontend/types.h | 9 +++++++ 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 038a8e8c2c1..25801a67cd8 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -203cbe7d3820fa03c965a01f72461f71588fe952 +897ce971b06a39c217d02dce9e1361bc7a240188 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 28eef8e9ed9..3ee98844d3b 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -107,6 +107,34 @@ Type::forwarded() const 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. Named_type* @@ -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; } - // Skip defined forward declarations. - t1 = t1->forwarded(); - t2 = t2->forwarded(); - - // 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(); + // Skip defined forward declarations. Ignore aliases. + t1 = t1->unalias(); + t2 = t2->unalias(); if (t1 == t2) return true; @@ -1197,9 +1219,7 @@ Type::finish_backend(Gogo* gogo, Btype *placeholder) Bexpression* Type::type_descriptor_pointer(Gogo* gogo, Location location) { - Type* t = this->forwarded(); - while (t->named_type() != NULL && t->named_type()->is_alias()) - t = t->named_type()->real_type()->forwarded(); + Type* t = this->unalias(); if (t->type_descriptor_var_ == NULL) { t->make_type_descriptor_var(gogo); @@ -1648,10 +1668,10 @@ Type::type_functions(Gogo* gogo, Named_type* name, Function_type* hash_fntype, Function_type* equal_fntype, Named_object** hash_fn, Named_object** equal_fn) { - // If this loop leaves NAME as NULL, then the type does not have a - // name after all. - while (name != NULL && name->is_alias()) - name = name->real_type()->named_type(); + // If the unaliased type is not a named type, then the type does not + // have a name after all. + if (name != NULL) + name = name->unalias()->named_type(); if (!this->is_comparable()) { @@ -2370,9 +2390,7 @@ static const int64_t max_ptrmask_bytes = 2048; Bexpression* Type::gc_symbol_pointer(Gogo* gogo) { - Type* t = this->forwarded(); - while (t->named_type() != NULL && t->named_type()->is_alias()) - t = t->named_type()->real_type()->forwarded(); + Type* t = this->unalias(); if (!t->has_pointer()) return gogo->backend()->nil_pointer_expression(); @@ -11494,9 +11512,9 @@ Type::find_field_or_method(const Type* type, std::string* ambig2) { // 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) - nt = type->points_to()->named_type(); + nt = type->points_to()->unalias()->named_type(); if (nt != NULL) { Named_object* no = nt->find_local_method(name); diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 08e57019a6c..2703319554f 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -676,6 +676,15 @@ class Type const Type* 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 // of other types, and is not void. bool -- 2.11.4.GIT