This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Go patch committed: Compare non-empty and empty interfaces
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org, gofrontend-dev at googlegroups dot com
- Date: Mon, 21 Feb 2011 18:52:59 -0800
- Subject: 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;
+}