diff --git a/go/types/sizes.go b/go/types/sizes.go index cb911bbf91..56fb310c29 100644 --- a/go/types/sizes.go +++ b/go/types/sizes.go @@ -28,11 +28,12 @@ type Sizes interface { // specified size. // - The size of strings and interfaces is 2*WordSize. // - The size of slices is 3*WordSize. -// - The size of arrays is the aligned size (see below) of an element -// multiplied by the number of elements. +// - The size of an array of n elements corresponds to the size of +// a struct of n consecutive fields of the array's element type. // - The size of a struct is the offset of the last field plus that -// field's size. If the struct is used in an array its size must -// first be aligned to a multiple of the struct's alignment. +// field's size. As with all element types, if the struct is used +// in an array its size must first be aligned to a multiple of the +// struct's alignment. // - All other types have size WordSize. // - Arrays and structs are aligned per spec definition; all other // types are naturally aligned with a maximum alignment MaxAlign. @@ -117,9 +118,13 @@ func (s *StdSizes) Sizeof(T Type) int64 { return s.WordSize * 2 } case *Array: + n := t.len + if n == 0 { + return 0 + } a := s.Alignof(t.elem) z := s.Sizeof(t.elem) - return align(z, a) * t.len // may be 0 + return align(z, a)*(n-1) + z case *Slice: return s.WordSize * 3 case *Struct: diff --git a/go/types/testdata/builtins.src b/go/types/testdata/builtins.src index b89fd4403c..8b405c3f92 100644 --- a/go/types/testdata/builtins.src +++ b/go/types/testdata/builtins.src @@ -649,6 +649,21 @@ type S2 struct{ // offset *S1 // 0 } // 8 +type S3 struct { // offset + a int64 // 0 + b int32 // 8 +} // 12 + +type S4 struct { // offset + S3 // 0 + int32 // 12 +} // 16 + +type S5 struct { // offset + a [3]int32 // 0 + b int32 // 12 +} // 16 + func (S2) m() {} func Alignof1() { @@ -780,6 +795,18 @@ func Sizeof1() { var y2 S2 assert(unsafe.Sizeof(y2) == 8) + var y3 S3 + assert(unsafe.Sizeof(y3) == 12) + + var y4 S4 + assert(unsafe.Sizeof(y4) == 16) + + var y5 S5 + assert(unsafe.Sizeof(y5) == 16) + + var a3 [10]S3 + assert(unsafe.Sizeof(a3) == 156) + // test case for issue 5670 type T struct { a int32