go/ssa: support unsafe.Add and unsafe.Slice

Fixes golang/go#47091

Change-Id: Id59375a3083520275025f58879c8950b0560e25a
Reviewed-on: https://go-review.googlesource.com/c/tools/+/333110
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Cuong Manh Le 2021-07-08 07:22:02 +07:00
Родитель fd00574339
Коммит 640c1dea83
2 изменённых файлов: 31 добавлений и 17 удалений

Просмотреть файл

@ -693,6 +693,10 @@ func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value {
case *ast.SelectorExpr:
sel, ok := fn.Pkg.info.Selections[e]
if !ok {
// builtin unsafe.{Add,Slice}
if obj, ok := fn.Pkg.info.Uses[e.Sel].(*types.Builtin); ok {
return &Builtin{name: obj.Name(), sig: tv.Type.(*types.Signature)}
}
// qualified identifier
return b.expr(fn, e.Sel)
}

Просмотреть файл

@ -9,6 +9,7 @@ package ssa_test
import (
"go/ast"
"go/importer"
"go/parser"
"go/token"
"go/types"
@ -18,24 +19,33 @@ import (
"golang.org/x/tools/go/ssa/ssautil"
)
func TestSliceToArrayPtr(t *testing.T) {
src := `package p
func f() {
var s []byte
_ = (*[4]byte)(s)
}
`
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "p.go", src, parser.ParseComments)
if err != nil {
t.Fatal(err)
func TestBuildPackageGo117(t *testing.T) {
tests := []struct {
name string
src string
importer types.Importer
}{
{"slice to array pointer", "package p; var s []byte; var _ = (*[4]byte)(s)", nil},
{"unsafe slice", `package p; import "unsafe"; var _ = unsafe.Add(nil, 0)`, importer.Default()},
{"unsafe add", `package p; import "unsafe"; var _ = unsafe.Slice((*int)(nil), 0)`, importer.Default()},
}
files := []*ast.File{f}
pkg := types.NewPackage("p", "")
conf := &types.Config{}
if _, _, err := ssautil.BuildPackage(conf, fset, pkg, files, ssa.SanityCheckFunctions); err != nil {
t.Fatalf("unexpected error: %v", err)
for _, tc := range tests {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "p.go", tc.src, parser.ParseComments)
if err != nil {
t.Error(err)
}
files := []*ast.File{f}
pkg := types.NewPackage("p", "")
conf := &types.Config{Importer: tc.importer}
if _, _, err := ssautil.BuildPackage(conf, fset, pkg, files, ssa.SanityCheckFunctions); err != nil {
t.Errorf("unexpected error: %v", err)
}
})
}
}