diff mbox

Go patch committed: Use a different identity function for type hashes

Message ID mcrbp4m3myg.fsf@google.com
State New
Headers show

Commit Message

Ian Lance Taylor Dec. 15, 2010, 6:33 p.m. UTC
This is a better approach to handling the hash table mapping GOGO types
to GENERIC types.  Rather than not storing error_mark_node in the table,
we use a different identity function.  The usual identity function
treats all error types as equal, to avoid useless warnings about
incompatible types.  This patch uses a different identity function for
erroneous types, such that only the same types are equal.  This avoids
conflating different erroneous types in the hash table.  Bootstrapped
and ran Go testsuite on x86_64-unknown-linux-gnu.  Committed to
mainline.

Ian
diff mbox

Patch

diff -r ae613f1c42f3 go/types.cc
--- a/go/types.cc	Tue Dec 14 22:24:46 2010 -0800
+++ b/go/types.cc	Wed Dec 15 10:21:08 2010 -0800
@@ -393,6 +393,38 @@ 
     }
 }
 
+// Return true if two types are identical when it comes to storing
+// them in a hash table.  This differs from Type::are_identical with
+// regard to how we handle error types.  We want to treat error types
+// as identical to other types when it comes to reporting
+// compatibility errors, but we want to treat them as different when
+// it comes to storing them in a hash table.
+
+bool
+Type::are_identical_for_hash_table(const Type* t1, const Type *t2)
+{
+  if (t1 == NULL || t2 == NULL)
+    return t1 == t2;
+
+  t1 = t1->forwarded();
+  t2 = t2->forwarded();
+
+  if (t1 == t2)
+    return true;
+
+  // Undefined forward declarations are only equal to themselves.
+  if (t1->forward_declaration_type() != NULL
+      || t2->forward_declaration_type() != NULL)
+    return false;
+
+  // The error type is only equal to the error type.
+  if (t1->is_error_type() || t2->is_error_type())
+    return t1->is_error_type() && t2->is_error_type();
+
+  // Otherwise we can use the usual identity check.
+  return Type::are_identical(t1, t2, NULL);
+}
+
 // Return true if it's OK to have a binary operation with types LHS
 // and RHS.  This is not used for shifts or comparisons.
 
@@ -810,14 +842,6 @@ 
 
   tree t = this->get_tree_without_hash(gogo);
 
-  // Don't store errors in the hash table.  This type might be a
-  // pointer to an error type or something like that.  Since error
-  // types are identical to everything else, that could cause us to
-  // return error_mark_node for pointers to any type, which will then
-  // confuse us later.
-  if (t == error_mark_node)
-    return error_mark_node;
-
   if (ins.first->second == NULL_TREE)
     ins.first->second = t;
   else
diff -r ae613f1c42f3 go/types.h
--- a/go/types.h	Tue Dec 14 22:24:46 2010 -0800
+++ b/go/types.h	Wed Dec 15 10:21:08 2010 -0800
@@ -508,6 +508,12 @@ 
   static bool
   are_identical(const Type* lhs, const Type* rhs, std::string* reason);
 
+  // Return true if two types are identical when it comes to putting
+  // them in a hash table.  This differs from are_identical only in
+  // how error types are handled.
+  static bool
+  are_identical_for_hash_table(const Type*, const Type*);
+
   // Return true if two types are compatible for use in a binary
   // operation, other than a shift, comparison, or channel send.  This
   // is an equivalence relation.
@@ -1104,7 +1110,7 @@ 
  public:
   bool
   operator()(const Type* t1, const Type* t2) const
-  { return Type::are_identical(t1, t2, NULL); }
+  { return Type::are_identical_for_hash_table(t1, t2); }
 };
 
 // An identifier with a type.