mirror of https://github.com/golang/go.git
go/pointer: support ssa.SliceToArrayPointer
Updates golang/go#47326 Change-Id: I6b9b59e82b1b93f7a328ba802ad473d4104d7577 Reviewed-on: https://go-review.googlesource.com/c/tools/+/339890 Run-TryBot: Tim King <taking@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Guodong Li <guodongli@google.com> Trust: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
d52cb71cca
commit
03a91dd97e
|
|
@ -791,7 +791,7 @@ func (a *analysis) genCall(caller *cgnode, instr ssa.CallInstruction) {
|
|||
// Some SSA instructions always have singletons points-to sets:
|
||||
// Alloc, Function, Global, MakeChan, MakeClosure, MakeInterface, MakeMap, MakeSlice.
|
||||
// Others may be singletons depending on their operands:
|
||||
// FreeVar, Const, Convert, FieldAddr, IndexAddr, Slice.
|
||||
// FreeVar, Const, Convert, FieldAddr, IndexAddr, Slice, SliceToArrayPointer.
|
||||
//
|
||||
// Idempotent. Objects are created as needed, possibly via recursion
|
||||
// down the SSA value graph, e.g IndexAddr(FieldAddr(Alloc))).
|
||||
|
|
@ -882,6 +882,11 @@ func (a *analysis) objectNode(cgn *cgnode, v ssa.Value) nodeid {
|
|||
case *ssa.Slice:
|
||||
obj = a.objectNode(cgn, v.X)
|
||||
|
||||
case *ssa.SliceToArrayPointer:
|
||||
// Going from a []T to a *[k]T for some k.
|
||||
// A slice []T is treated as if it were a *T pointer.
|
||||
obj = a.objectNode(cgn, v.X)
|
||||
|
||||
case *ssa.Convert:
|
||||
// TODO(adonovan): opt: handle these cases too:
|
||||
// - unsafe.Pointer->*T conversion acts like Alloc
|
||||
|
|
@ -1030,6 +1035,12 @@ func (a *analysis) genInstr(cgn *cgnode, instr ssa.Instruction) {
|
|||
case *ssa.Slice:
|
||||
a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
|
||||
|
||||
case *ssa.SliceToArrayPointer:
|
||||
// Going from a []T to a *[k]T (for some k) is a single `dst = src` constraint.
|
||||
// Both []T and *[k]T are modelled as an *IdArrayT where IdArrayT is the identity
|
||||
// node for an array of type T, i.e `type IdArrayT struct{elem T}`.
|
||||
a.copy(a.valueNode(instr), a.valueNode(instr.X), 1)
|
||||
|
||||
case *ssa.If, *ssa.Jump:
|
||||
// no-op.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright 2021 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.
|
||||
|
||||
// No testdata on Android.
|
||||
|
||||
//go:build !android && go1.17
|
||||
// +build !android,go1.17
|
||||
|
||||
package pointer_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSliceToArrayPointer(t *testing.T) {
|
||||
// Based on TestInput. Keep this up to date with that.
|
||||
filename := "testdata/arrays_go117.go"
|
||||
|
||||
if testing.Short() {
|
||||
t.Skip("skipping in short mode; this test requires tons of memory; https://golang.org/issue/14113")
|
||||
}
|
||||
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("os.Getwd: %s", err)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "Entering directory `%s'\n", wd)
|
||||
|
||||
content, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't read file '%s': %s", filename, err)
|
||||
}
|
||||
|
||||
if !doOneInput(string(content), filename) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,173 @@
|
|||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// Forked from arrays.go. Requires go1.17 to parse slice to array casts.
|
||||
// TODO(taking): Merge back into arrays.go once we can assume go1.17.
|
||||
|
||||
var unknown bool // defeat dead-code elimination
|
||||
|
||||
var a, b int
|
||||
|
||||
func array1() {
|
||||
sliceA := make([]*int, 10) // @line a1make
|
||||
sliceA[0] = &a
|
||||
|
||||
var sliceB []*int
|
||||
sliceB = append(sliceB, &b) // @line a1append
|
||||
|
||||
print(sliceA) // @pointsto makeslice@a1make:16
|
||||
print(sliceA[0]) // @pointsto main.a
|
||||
|
||||
print(sliceB) // @pointsto append@a1append:17
|
||||
print(sliceB[100]) // @pointsto main.b
|
||||
}
|
||||
|
||||
func array2() {
|
||||
sliceA := make([]*int, 10) // @line a2make
|
||||
sliceA[0] = &a
|
||||
|
||||
sliceB := sliceA[:]
|
||||
|
||||
print(sliceA) // @pointsto makeslice@a2make:16
|
||||
print(sliceA[0]) // @pointsto main.a
|
||||
|
||||
print(sliceB) // @pointsto makeslice@a2make:16
|
||||
print(sliceB[0]) // @pointsto main.a
|
||||
}
|
||||
|
||||
func array3() {
|
||||
a := []interface{}{"", 1}
|
||||
b := []interface{}{true, func() {}}
|
||||
print(a[0]) // @types string | int
|
||||
print(b[0]) // @types bool | func()
|
||||
}
|
||||
|
||||
// Test of append, copy, slice.
|
||||
func array4() {
|
||||
var s2 struct { // @line a4L0
|
||||
a [3]int
|
||||
b struct{ c, d int }
|
||||
}
|
||||
var sl1 = make([]*int, 10) // @line a4make
|
||||
var someint int // @line a4L1
|
||||
sl1[1] = &someint
|
||||
sl2 := append(sl1, &s2.a[1]) // @line a4append1
|
||||
print(sl1) // @pointsto makeslice@a4make:16
|
||||
print(sl2) // @pointsto append@a4append1:15 | makeslice@a4make:16
|
||||
print(sl1[0]) // @pointsto someint@a4L1:6 | s2.a[*]@a4L0:6
|
||||
print(sl2[0]) // @pointsto someint@a4L1:6 | s2.a[*]@a4L0:6
|
||||
|
||||
// In z=append(x,y) we should observe flow from y[*] to x[*].
|
||||
var sl3 = make([]*int, 10) // @line a4L2
|
||||
_ = append(sl3, &s2.a[1])
|
||||
print(sl3) // @pointsto makeslice@a4L2:16
|
||||
print(sl3[0]) // @pointsto s2.a[*]@a4L0:6
|
||||
|
||||
var sl4 = []*int{&a} // @line a4L3
|
||||
sl4a := append(sl4) // @line a4L4
|
||||
print(sl4a) // @pointsto slicelit@a4L3:18 | append@a4L4:16
|
||||
print(&sl4a[0]) // @pointsto slicelit[*]@a4L3:18 | append[*]@a4L4:16
|
||||
print(sl4a[0]) // @pointsto main.a
|
||||
|
||||
var sl5 = []*int{&b} // @line a4L5
|
||||
copy(sl5, sl4)
|
||||
print(sl5) // @pointsto slicelit@a4L5:18
|
||||
print(&sl5[0]) // @pointsto slicelit[*]@a4L5:18
|
||||
print(sl5[0]) // @pointsto main.b | main.a
|
||||
|
||||
var sl6 = sl5[:0]
|
||||
print(sl6) // @pointsto slicelit@a4L5:18
|
||||
print(&sl6[0]) // @pointsto slicelit[*]@a4L5:18
|
||||
print(sl6[0]) // @pointsto main.b | main.a
|
||||
}
|
||||
|
||||
func array5() {
|
||||
var arr [2]*int
|
||||
arr[0] = &a
|
||||
arr[1] = &b
|
||||
|
||||
var n int
|
||||
print(arr[n]) // @pointsto main.a | main.b
|
||||
}
|
||||
|
||||
func array6() {
|
||||
var n int
|
||||
|
||||
sl0 := []*int{&a}
|
||||
ap0 := (*[1]*int)(sl0)
|
||||
ar0 := *ap0
|
||||
|
||||
print(ap0[n]) // @pointsto main.a
|
||||
print(sl0[n]) // @pointsto main.a
|
||||
print(ar0[n]) // @pointsto main.a
|
||||
|
||||
sl1 := []*int{&a}
|
||||
ap1 := (*[1]*int)(sl1)
|
||||
ar1 := *ap1
|
||||
|
||||
ar1[0] = &b
|
||||
print(ap1[n]) // @pointsto main.a
|
||||
print(sl1[n]) // @pointsto main.a
|
||||
print(ar1[n]) // @pointsto main.a | main.b
|
||||
|
||||
sl2 := []*int{&a}
|
||||
ap2 := (*[1]*int)(sl2)
|
||||
ar2 := *ap2
|
||||
|
||||
ap2[0] = &b
|
||||
print(ap2[n]) // @pointsto main.a | main.b
|
||||
print(sl2[n]) // @pointsto main.a | main.b
|
||||
print(ar2[n]) // @pointsto main.a | main.b
|
||||
|
||||
sl3 := []*int{&b, nil}
|
||||
ap3 := (*[1]*int)(sl3)
|
||||
ar3 := *ap3
|
||||
|
||||
print(sl3[n]) // @pointsto main.b
|
||||
print(ap3[n]) // @pointsto main.b
|
||||
print(ar3[n]) // @pointsto main.b
|
||||
}
|
||||
|
||||
func array7() {
|
||||
var n int
|
||||
|
||||
sl0 := []*int{nil, nil, nil}
|
||||
ap0 := (*[2]*int)(sl0)
|
||||
ap1 := (*[1]*int)(sl0[2:])
|
||||
|
||||
ap1[0] = &a
|
||||
|
||||
print(sl0[n]) // @pointsto main.a
|
||||
print(ap0[n]) // @pointsto main.a
|
||||
print(ap1[n]) // @pointsto main.a
|
||||
}
|
||||
|
||||
func array8() {
|
||||
var n int
|
||||
|
||||
sl1 := make([]*int, 1, 1)
|
||||
sl2 := make([]*int, 1, 1)
|
||||
pa1 := (*[1]*int)(sl1)
|
||||
pa2 := (*[1]*int)(sl2)
|
||||
sl1[0] = &a
|
||||
sl2[0] = &b
|
||||
print(pa1[n]) // @pointsto main.a
|
||||
print(pa2[n]) // @pointsto main.b
|
||||
|
||||
pa2 = pa1
|
||||
print(pa1[n]) // @pointsto main.a
|
||||
print(pa2[n]) // @pointsto main.a
|
||||
}
|
||||
|
||||
func main() {
|
||||
array1()
|
||||
array2()
|
||||
array3()
|
||||
array4()
|
||||
array5()
|
||||
array6()
|
||||
array7()
|
||||
array8()
|
||||
}
|
||||
Loading…
Reference in New Issue