reflect: more function layout tests

Test more stuff:
1) flagNoPointers, an incorrect value was the cause of #9425
2) Total function layout size
3) gc program

Change-Id: I73f65fe740215938fa930d2f096febd9db0a0021
Reviewed-on: https://go-review.googlesource.com/2090
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 9d092d9..69be8c6 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -4075,9 +4075,10 @@
 }
 
 type funcLayoutTest struct {
-	rcvr, t            Type
-	argsize, retOffset uintptr
-	stack              []byte
+	rcvr, t                  Type
+	size, argsize, retOffset uintptr
+	stack                    []byte
+	gc                       []byte
 }
 
 var funcLayoutTests []funcLayoutTest
@@ -4095,24 +4096,30 @@
 		funcLayoutTest{
 			nil,
 			ValueOf(func(a, b string) string { return "" }).Type(),
+			6 * PtrSize,
 			4 * PtrSize,
 			4 * PtrSize,
 			[]byte{BitsPointer, BitsScalar, BitsPointer},
+			[]byte{BitsPointer, BitsScalar, BitsPointer, BitsScalar, BitsPointer, BitsScalar},
 		})
 
-	var r []byte
+	var r, s []byte
 	if PtrSize == 4 {
 		r = []byte{BitsScalar, BitsScalar, BitsScalar, BitsPointer}
+		s = []byte{BitsScalar, BitsScalar, BitsScalar, BitsPointer, BitsScalar}
 	} else {
 		r = []byte{BitsScalar, BitsScalar, BitsPointer}
+		s = []byte{BitsScalar, BitsScalar, BitsPointer, BitsScalar}
 	}
 	funcLayoutTests = append(funcLayoutTests,
 		funcLayoutTest{
 			nil,
 			ValueOf(func(a, b, c uint32, p *byte, d uint16) {}).Type(),
+			roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
 			roundup(3*4, PtrSize) + PtrSize + 2,
 			roundup(roundup(3*4, PtrSize)+PtrSize+2, argAlign),
 			r,
+			s,
 		})
 
 	funcLayoutTests = append(funcLayoutTests,
@@ -4121,6 +4128,8 @@
 			ValueOf(func(a map[int]int, b uintptr, c interface{}) {}).Type(),
 			4 * PtrSize,
 			4 * PtrSize,
+			4 * PtrSize,
+			[]byte{BitsPointer, BitsScalar, BitsPointer, BitsPointer},
 			[]byte{BitsPointer, BitsScalar, BitsPointer, BitsPointer},
 		})
 
@@ -4134,6 +4143,8 @@
 			ValueOf(func(a S) {}).Type(),
 			4 * PtrSize,
 			4 * PtrSize,
+			4 * PtrSize,
+			[]byte{BitsScalar, BitsScalar, BitsPointer, BitsPointer},
 			[]byte{BitsScalar, BitsScalar, BitsPointer, BitsPointer},
 		})
 
@@ -4141,15 +4152,56 @@
 		funcLayoutTest{
 			ValueOf((*byte)(nil)).Type(),
 			ValueOf(func(a uintptr, b *int) {}).Type(),
+			roundup(3*PtrSize, argAlign),
 			3 * PtrSize,
 			roundup(3*PtrSize, argAlign),
 			[]byte{BitsPointer, BitsScalar, BitsPointer},
+			[]byte{BitsPointer, BitsScalar, BitsPointer},
+		})
+
+	funcLayoutTests = append(funcLayoutTests,
+		funcLayoutTest{
+			nil,
+			ValueOf(func(a uintptr){}).Type(),
+			PtrSize,
+			PtrSize,
+			PtrSize,
+			[]byte{},
+			[]byte{BitsScalar},
+		})
+
+	funcLayoutTests = append(funcLayoutTests,
+		funcLayoutTest{
+			nil,
+			ValueOf(func() uintptr{return 0}).Type(),
+			PtrSize,
+			0,
+			0,
+			[]byte{},
+			[]byte{BitsScalar},
+		})
+
+	funcLayoutTests = append(funcLayoutTests,
+		funcLayoutTest{
+			ValueOf(uintptr(0)).Type(),
+			ValueOf(func(a uintptr){}).Type(),
+			2*PtrSize,
+			2*PtrSize,
+			2*PtrSize,
+			[]byte{BitsPointer},
+			[]byte{BitsPointer, BitsScalar},
+			// Note: this one is tricky, as the receiver is not a pointer.  But we
+			// pass the receiver by reference to the autogenerated pointer-receiver
+			// version of the function.
 		})
 }
 
 func TestFuncLayout(t *testing.T) {
 	for _, lt := range funcLayoutTests {
-		_, argsize, retOffset, stack := FuncLayout(lt.t, lt.rcvr)
+		typ, argsize, retOffset, stack, gc, ptrs := FuncLayout(lt.t, lt.rcvr)
+		if typ.Size() != lt.size {
+			t.Errorf("funcLayout(%v, %v).size=%d, want %d", lt.t, lt.rcvr, typ.Size(), lt.size)
+		}
 		if argsize != lt.argsize {
 			t.Errorf("funcLayout(%v, %v).argsize=%d, want %d", lt.t, lt.rcvr, argsize, lt.argsize)
 		}
@@ -4159,5 +4211,11 @@
 		if !bytes.Equal(stack, lt.stack) {
 			t.Errorf("funcLayout(%v, %v).stack=%v, want %v", lt.t, lt.rcvr, stack, lt.stack)
 		}
+		if !bytes.Equal(gc, lt.gc) {
+			t.Errorf("funcLayout(%v, %v).gc=%v, want %v", lt.t, lt.rcvr, gc, lt.gc)
+		}
+		if ptrs && len(stack) == 0 || !ptrs && len(stack) > 0 {
+			t.Errorf("funcLayout(%v, %v) pointers flag=%v, want %v", lt.t, lt.rcvr, ptrs, !ptrs)
+		}
 	}
 }