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
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
--- /dev/null
+// 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)
+ }
+}