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>
diff --git a/go/ssa/builder.go b/go/ssa/builder.go
index a13a884..2d0fdaa 100644
--- a/go/ssa/builder.go
+++ b/go/ssa/builder.go
@@ -693,6 +693,10 @@
 	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)
 		}
diff --git a/go/ssa/builder_go117_test.go b/go/ssa/builder_go117_test.go
index 93316c1..e7ba214 100644
--- a/go/ssa/builder_go117_test.go
+++ b/go/ssa/builder_go117_test.go
@@ -9,6 +9,7 @@
 
 import (
 	"go/ast"
+	"go/importer"
 	"go/parser"
 	"go/token"
 	"go/types"
@@ -18,24 +19,33 @@
 	"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)
+			}
+		})
 	}
 }