compiler: look through aliases when looking for methods
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 25 Jan 2018 23:13:31 +0000 (23:13 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 25 Jan 2018 23:13:31 +0000 (23:13 +0000)
    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

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index 038a8e8c2c146e03a51f43f49b04af794db83a1b..25801a67cd8748c839f50ee4a6dc706ee6f3edb4 100644 (file)
@@ -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.
index 28eef8e9ed9d0e84565d7645f40466bd08e9d70f..3ee98844d3b8f34df18b2475513bd8f5e81c1166 100644 (file)
@@ -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);
index 08e57019a6ca22705944e24971bb93fb72b3b134..2703319554f7ffd129c20b4635d44e2dff2e0e7c 100644 (file)
@@ -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