// Copyright 2016 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. // This file contains tests for sizes. package types_test import ( "go/ast" "go/importer" "go/parser" "go/token" "go/types" "testing" ) // findStructType typechecks src and returns the first struct type encountered. func findStructType(t *testing.T, src string) *types.Struct { fset := token.NewFileSet() f, err := parser.ParseFile(fset, "x.go", src, 0) if err != nil { t.Fatal(err) } info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)} var conf types.Config _, err = conf.Check("x", fset, []*ast.File{f}, &info) if err != nil { t.Fatal(err) } for _, tv := range info.Types { if ts, ok := tv.Type.(*types.Struct); ok { return ts } } t.Fatalf("failed to find a struct type in src:\n%s\n", src) return nil } // Issue 16316 func TestMultipleSizeUse(t *testing.T) { const src = ` package main type S struct { i int b bool s string n int } ` ts := findStructType(t, src) sizes := types.StdSizes{WordSize: 4, MaxAlign: 4} if got := sizes.Sizeof(ts); got != 20 { t.Errorf("Sizeof(%v) with WordSize 4 = %d want 20", ts, got) } sizes = types.StdSizes{WordSize: 8, MaxAlign: 8} if got := sizes.Sizeof(ts); got != 40 { t.Errorf("Sizeof(%v) with WordSize 8 = %d want 40", ts, got) } } // Issue 16464 func TestAlignofNaclSlice(t *testing.T) { const src = ` package main var s struct { x *int y []byte } ` ts := findStructType(t, src) sizes := &types.StdSizes{WordSize: 4, MaxAlign: 8} var fields []*types.Var // Make a copy manually :( for i := 0; i < ts.NumFields(); i++ { fields = append(fields, ts.Field(i)) } offsets := sizes.Offsetsof(fields) if offsets[0] != 0 || offsets[1] != 4 { t.Errorf("OffsetsOf(%v) = %v want %v", ts, offsets, []int{0, 4}) } } func TestIssue16902(t *testing.T) { const src = ` package a import "unsafe" const _ = unsafe.Offsetof(struct{ x int64 }{}.x) ` fset := token.NewFileSet() f, err := parser.ParseFile(fset, "x.go", src, 0) if err != nil { t.Fatal(err) } info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)} conf := types.Config{ Importer: importer.Default(), Sizes: &types.StdSizes{WordSize: 8, MaxAlign: 8}, } _, err = conf.Check("x", fset, []*ast.File{f}, &info) if err != nil { t.Fatal(err) } for _, tv := range info.Types { _ = conf.Sizes.Sizeof(tv.Type) _ = conf.Sizes.Alignof(tv.Type) } }