This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Go patch committed: Compare non-empty and empty interfaces


The Go frontend incorrectly did not permit comparing a non-empty
interface value with an empty interface value.  This patch fixes the
bug.  Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian

diff -r 0fb4b3aa5c2a go/expressions.cc
--- a/go/expressions.cc	Mon Feb 21 18:32:59 2011 -0800
+++ b/go/expressions.cc	Mon Feb 21 18:49:53 2011 -0800
@@ -6270,9 +6270,9 @@
   else if (left_type->interface_type() != NULL
 	   && right_type->interface_type() != NULL)
     {
-      if (left_type->interface_type()->is_empty())
-	{
-	  gcc_assert(right_type->interface_type()->is_empty());
+      if (left_type->interface_type()->is_empty()
+	  && right_type->interface_type()->is_empty())
+	{
 	  static tree empty_interface_compare_decl;
 	  left_tree = Gogo::call_builtin(&empty_interface_compare_decl,
 					 location,
@@ -6288,9 +6288,9 @@
 	  // This can panic if the type is uncomparable.
 	  TREE_NOTHROW(empty_interface_compare_decl) = 0;
 	}
-      else
-	{
-	  gcc_assert(!right_type->interface_type()->is_empty());
+      else if (!left_type->interface_type()->is_empty()
+	       && !right_type->interface_type()->is_empty())
+	{
 	  static tree interface_compare_decl;
 	  left_tree = Gogo::call_builtin(&interface_compare_decl,
 					 location,
@@ -6306,6 +6306,32 @@
 	  // This can panic if the type is uncomparable.
 	  TREE_NOTHROW(interface_compare_decl) = 0;
 	}
+      else
+	{
+	  if (left_type->interface_type()->is_empty())
+	    {
+	      gcc_assert(op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ);
+	      std::swap(left_type, right_type);
+	      std::swap(left_tree, right_tree);
+	    }
+	  gcc_assert(!left_type->interface_type()->is_empty());
+	  gcc_assert(right_type->interface_type()->is_empty());
+	  static tree interface_empty_compare_decl;
+	  left_tree = Gogo::call_builtin(&interface_empty_compare_decl,
+					 location,
+					 "__go_interface_empty_compare",
+					 2,
+					 integer_type_node,
+					 TREE_TYPE(left_tree),
+					 left_tree,
+					 TREE_TYPE(right_tree),
+					 right_tree);
+	  if (left_tree == error_mark_node)
+	    return error_mark_node;
+	  // This can panic if the type is uncomparable.
+	  TREE_NOTHROW(interface_empty_compare_decl) = 0;
+	}
+
       right_tree = build_int_cst_type(integer_type_node, 0);
     }
 
diff -r 0fb4b3aa5c2a libgo/Makefile.am
--- a/libgo/Makefile.am	Mon Feb 21 18:32:59 2011 -0800
+++ b/libgo/Makefile.am	Mon Feb 21 18:49:53 2011 -0800
@@ -352,6 +352,7 @@
 	runtime/go-int-array-to-string.c \
 	runtime/go-int-to-string.c \
 	runtime/go-interface-compare.c \
+	runtime/go-interface-eface-compare.c \
 	runtime/go-interface-val-compare.c \
 	runtime/go-lock-os-thread.c \
 	runtime/go-map-delete.c \
diff -r 0fb4b3aa5c2a libgo/runtime/go-interface-eface-compare.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgo/runtime/go-interface-eface-compare.c	Mon Feb 21 18:49:53 2011 -0800
@@ -0,0 +1,32 @@
+/* go-interface-eface-compare.c -- compare non-empty and empty interface.
+
+   Copyright 2011 The Go Authors. All rights reserved.
+   Use of this source code is governed by a BSD-style
+   license that can be found in the LICENSE file.  */
+
+#include "interface.h"
+
+/* Compare a non-empty interface value with an empty interface value.
+   Return 0 for equal, not zero for not equal (return value is like
+   strcmp).  */
+
+int
+__go_interface_empty_compare (struct __go_interface left,
+			      struct __go_empty_interface right)
+{
+  const struct __go_type_descriptor *left_descriptor;
+
+  if (left.__methods == NULL && right.__type_descriptor == NULL)
+    return 0;
+  if (left.__methods == NULL || right.__type_descriptor == NULL)
+    return 1;
+  left_descriptor = left.__methods[0];
+  if (!__go_type_descriptors_equal (left_descriptor, right.__type_descriptor))
+    return 1;
+  if (__go_is_pointer_type (left_descriptor))
+    return left.__object == right.__object ? 0 : 1;
+  if (!left_descriptor->__equalfn (left.__object, right.__object,
+				   left_descriptor->__size))
+    return 1;
+  return 0;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]