diff --git a/go/ssa/emit.go b/go/ssa/emit.go index 66107621..1036988a 100644 --- a/go/ssa/emit.go +++ b/go/ssa/emit.go @@ -147,7 +147,7 @@ func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value { // func isValuePreserving(ut_src, ut_dst types.Type) bool { // Identical underlying types? - if types.Identical(ut_dst, ut_src) { + if structTypesIdentical(ut_dst, ut_src) { return true } diff --git a/go/ssa/identical.go b/go/ssa/identical.go new file mode 100644 index 00000000..53cbee10 --- /dev/null +++ b/go/ssa/identical.go @@ -0,0 +1,7 @@ +// +build go1.8 + +package ssa + +import "go/types" + +var structTypesIdentical = types.IdenticalIgnoreTags diff --git a/go/ssa/identical_17.go b/go/ssa/identical_17.go new file mode 100644 index 00000000..da89d333 --- /dev/null +++ b/go/ssa/identical_17.go @@ -0,0 +1,7 @@ +// +build !go1.8 + +package ssa + +import "go/types" + +var structTypesIdentical = types.Identical diff --git a/go/ssa/identical_test.go b/go/ssa/identical_test.go new file mode 100644 index 00000000..404693dc --- /dev/null +++ b/go/ssa/identical_test.go @@ -0,0 +1,9 @@ +//+build go1.8 + +package ssa_test + +import "testing" + +func TestValueForExprStructConv(t *testing.T) { + testValueForExpr(t, "testdata/structconv.go") +} diff --git a/go/ssa/source_test.go b/go/ssa/source_test.go index 85b55c21..43051f80 100644 --- a/go/ssa/source_test.go +++ b/go/ssa/source_test.go @@ -194,12 +194,16 @@ func checkVarValue(t *testing.T, prog *ssa.Program, pkg *ssa.Package, ref []ast. // Ensure that, in debug mode, we can determine the ssa.Value // corresponding to every ast.Expr. func TestValueForExpr(t *testing.T) { + testValueForExpr(t, "testdata/valueforexpr.go") +} + +func testValueForExpr(t *testing.T, testfile string) { if runtime.GOOS == "android" { t.Skipf("no testdata dir on %s", runtime.GOOS) } conf := loader.Config{ParserMode: parser.ParseComments} - f, err := conf.ParseFile("testdata/valueforexpr.go", nil) + f, err := conf.ParseFile(testfile, nil) if err != nil { t.Error(err) return diff --git a/go/ssa/testdata/structconv.go b/go/ssa/testdata/structconv.go new file mode 100644 index 00000000..31264691 --- /dev/null +++ b/go/ssa/testdata/structconv.go @@ -0,0 +1,24 @@ +//+build ignore + +// This file is the input to TestValueForExprStructConv in identical_test.go, +// which uses the same framework as TestValueForExpr does in source_test.go. +// +// In Go 1.8, struct conversions are permitted even when the struct types have +// different tags. This wasn't permitted in earlier versions of Go, so this file +// exists separately from valueforexpr.go to just test this behavior in Go 1.8 +// and later. + +package main + +type t1 struct { + x int +} +type t2 struct { + x int `tag` +} + +func main() { + var tv1 t1 + var tv2 t2 = /*@ChangeType*/ (t2(tv1)) + _ = tv2 +}