| // +build ignore |
| |
| package main |
| |
| import "reflect" |
| |
| // Test of arrays & slices with reflection. |
| |
| var a int |
| |
| func arrayreflect1() { |
| sl := make([]*int, 10) // @line ar1make |
| sl[0] = &a |
| |
| srv := reflect.ValueOf(sl).Slice(0, 0) |
| print(srv.Interface()) // @concrete []*int |
| print(srv.Interface().([]*int)) // @pointsto makeslice@ar1make:12 |
| print(srv.Interface().([]*int)[42]) // @pointsto main.a |
| } |
| |
| func arrayreflect2() { |
| var arr [10]*int |
| sl := arr[:] |
| sl[0] = &a |
| |
| srv := reflect.ValueOf(sl).Slice(0, 0) |
| print(srv.Interface()) // @concrete []*int |
| print(srv.Interface().([]*int)) // pointsto TODO |
| print(srv.Interface().([]*int)[42]) // @pointsto main.a |
| } |
| |
| func arrayreflect3() { |
| srv := reflect.ValueOf("hi").Slice(0, 0) |
| print(srv.Interface()) // @concrete string |
| |
| type S string |
| srv2 := reflect.ValueOf(S("hi")).Slice(0, 0) |
| print(srv2.Interface()) // @concrete main.S |
| } |
| |
| func arrayreflect4() { |
| rv1 := reflect.ValueOf("hi") |
| rv2 := rv1 // backflow! |
| if unknown { |
| rv2 = reflect.ValueOf(123) |
| } |
| // We see backflow through the assignment above causing an |
| // imprecise result for rv1. This is because the SSA builder |
| // doesn't yet lift structs (like reflect.Value) into |
| // registers so these are all loads/stores to the stack. |
| // Under Das's algorithm, the extra indirection results in |
| // (undirected) unification not (directed) flow edges. |
| // TODO(adonovan): precision: lift aggregates. |
| print(rv1.Interface()) // @concrete string | int |
| print(rv2.Interface()) // @concrete string | int |
| } |
| |
| func arrayreflect5() { |
| sl1 := make([]byte, 0) |
| sl2 := make([]byte, 0) |
| |
| srv := reflect.ValueOf(sl1) |
| |
| print(srv.Interface()) // @concrete []byte |
| print(srv.Interface().([]byte)) // @pointsto makeslice@testdata/arrayreflect.go:62:13 |
| print(srv.Bytes()) // @pointsto makeslice@testdata/arrayreflect.go:62:13 |
| |
| srv2 := reflect.ValueOf(123) |
| srv2.SetBytes(sl2) |
| print(srv2.Interface()) // @concrete []byte | int |
| print(srv2.Interface().([]byte)) // @pointsto makeslice@testdata/arrayreflect.go:63:13 |
| print(srv2.Bytes()) // @pointsto makeslice@testdata/arrayreflect.go:63:13 |
| } |
| |
| func arrayreflect6() { |
| sl1 := []*bool{new(bool)} |
| sl2 := []*int{&a} |
| |
| srv1 := reflect.ValueOf(sl1) |
| print(srv1.Index(42).Interface()) // @concrete *bool |
| print(srv1.Index(42).Interface().(*bool)) // @pointsto alloc@testdata/arrayreflect.go:79:20 |
| |
| srv2 := reflect.ValueOf(sl2) |
| print(srv2.Index(42).Interface()) // @concrete *int |
| print(srv2.Index(42).Interface().(*int)) // @pointsto main.a |
| |
| p1 := &sl1[0] |
| p2 := &sl2[0] |
| |
| prv1 := reflect.ValueOf(p1) |
| print(prv1.Elem().Interface()) // @concrete *bool |
| print(prv1.Elem().Interface().(*bool)) // @pointsto alloc@testdata/arrayreflect.go:79:20 |
| |
| prv2 := reflect.ValueOf(p2) |
| print(prv2.Elem().Interface()) // @concrete *int |
| print(prv2.Elem().Interface().(*int)) // @pointsto main.a |
| } |
| |
| func main() { |
| arrayreflect1() |
| arrayreflect2() |
| arrayreflect3() |
| arrayreflect4() |
| arrayreflect5() |
| arrayreflect6() |
| } |
| |
| var unknown bool |