summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pkg/runtime/iface.goc23
-rw-r--r--test/fixedbugs/issue8139.go50
2 files changed, 69 insertions, 4 deletions
diff --git a/src/pkg/runtime/iface.goc b/src/pkg/runtime/iface.goc
index 96bb8b8aa..c0a17e303 100644
--- a/src/pkg/runtime/iface.goc
+++ b/src/pkg/runtime/iface.goc
@@ -209,9 +209,19 @@ func convT2E(t *Type, elem *byte) (ret Eface) {
static void assertI2Tret(Type *t, Iface i, byte *ret);
+/*
+ * NOTE: Cannot use 'func' here, because we have to declare
+ * a return value, the only types we have are at least 1 byte large,
+ * goc2c will zero the return value, and the actual return value
+ * might have size 0 bytes, in which case the zeroing of the
+ * 1 or more bytes would be wrong.
+ * Using C lets us control (avoid) the initial zeroing.
+ */
#pragma textflag NOSPLIT
-func assertI2T(t *Type, i Iface) (ret byte, ...) {
- assertI2Tret(t, i, &ret);
+void
+runtime·assertI2T(Type *t, Iface i, GoOutput retbase)
+{
+ assertI2Tret(t, i, (byte*)&retbase);
}
static void
@@ -260,9 +270,14 @@ func assertI2TOK(t *Type, i Iface) (ok bool) {
static void assertE2Tret(Type *t, Eface e, byte *ret);
+/*
+ * NOTE: Cannot use 'func' here. See assertI2T above.
+ */
#pragma textflag NOSPLIT
-func assertE2T(t *Type, e Eface) (ret byte, ...) {
- assertE2Tret(t, e, &ret);
+void
+runtime·assertE2T(Type *t, Eface e, GoOutput retbase)
+{
+ assertE2Tret(t, e, (byte*)&retbase);
}
static void
diff --git a/test/fixedbugs/issue8139.go b/test/fixedbugs/issue8139.go
new file mode 100644
index 000000000..821c9ff65
--- /dev/null
+++ b/test/fixedbugs/issue8139.go
@@ -0,0 +1,50 @@
+// run
+
+// Copyright 2014 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.
+
+// Issue 8139. The x.(T) assertions used to write 1 (unexpected)
+// return byte for the 0-byte return value T.
+
+package main
+
+import "fmt"
+
+type T struct{}
+
+func (T) M() {}
+
+type M interface {
+ M()
+}
+
+var e interface{} = T{}
+var i M = T{}
+var b bool
+
+func f1() int {
+ if b {
+ return f1() // convince inliner not to inline
+ }
+ z := 0x11223344
+ _ = e.(T)
+ return z
+}
+
+func f2() int {
+ if b {
+ return f1() // convince inliner not to inline
+ }
+ z := 0x11223344
+ _ = i.(T)
+ return z
+}
+
+func main() {
+ x := f1()
+ y := f2()
+ if x != 0x11223344 || y != 0x11223344 {
+ fmt.Printf("BUG: x=%#x y=%#x, want 0x11223344 for both\n", x, y)
+ }
+}