diff mbox

Go patch committed: Fix bug in embedded method handling

Message ID mcriopjqcvi.fsf@iant-glaptop.roam.corp.google.com
State New
Headers show

Commit Message

Ian Lance Taylor May 6, 2014, 1:02 p.m. UTC
This patch to the Go frontend fixes a bug in the handling of methods of
embedded fields.  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.  If the second instance was at a higher level,
its methods would not be used.  This only applied when building the set
of all methods, so ambiguous cases were detected correctly.  The bug
only applied for non-ambiguous cases.  I will commit a test case for
this to the master testsuite.

Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline and 4.9 branch.

Ian
diff mbox

Patch

diff -r 4e7f09e27159 go/types.cc
--- a/go/types.cc	Mon May 05 21:13:00 2014 -0400
+++ b/go/types.cc	Tue May 06 01:15:54 2014 -0400
@@ -8924,9 +8924,8 @@ 
 		       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 @@ 
 			   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 @@ 
   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;
-    }
-
-  if (nt != NULL)
-    Type::add_local_methods_for_type(nt, field_indexes, depth,
-				     is_embedded_pointer, needs_stub_method,
-				     methods);
+      for (std::vector<const Named_type*>::const_iterator p = seen->begin();
+	   p != seen->end();
+	   ++p)
+	{
+	  if (*p == nt)
+	    return;
+	}
+
+      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 @@ 
   // 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 @@ 
 				    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 @@ 
 				 (needs_stub_method
 				  || is_pointer
 				  || i > 0),
-				 types_seen,
+				 seen,
 				 methods);
     }
 }
diff -r 4e7f09e27159 go/types.h
--- a/go/types.h	Mon May 05 21:13:00 2014 -0400
+++ b/go/types.h	Tue May 06 01:15:54 2014 -0400
@@ -1171,14 +1171,11 @@ 
   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 @@ 
   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