Commit 14efaa0d authored by David Crawshaw's avatar David Crawshaw

cmd/compile: qualify unexported fields of unnamed types

The compiler was canonicalizing unnamed types of the form

	struct { i int }

across packages, even though an unexported field i should not be
accessible from other packages.

The fix requires both qualifying the field name in the string used by
the compiler to distinguish the type, and ensuring the struct's pkgpath
is set in the rtype version of the data when the type being written is
not part of the localpkg.

Fixes #16616

Change-Id: Ibab160b8b5936dfa47b17dbfd48964a65586785b
Reviewed-on: https://go-review.googlesource.com/27791
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent 3e59b20d
......@@ -1574,7 +1574,10 @@ func Fldconv(f *Field, flag FmtFlag) string {
if f.Funarg != FunargNone {
name = Nconv(f.Nname, 0)
} else if flag&FmtLong != 0 {
name = sconv(s, FmtShort|FmtByte) // qualify non-exported names (used on structs, not on funarg)
name = sconv(s, FmtShort|FmtByte)
if !exportname(name) && flag&FmtUnsigned == 0 {
name = sconv(s, 0) // qualify non-exported names (used on structs, not on funarg)
}
} else {
name = sconv(s, 0)
}
......
......@@ -1301,6 +1301,15 @@ ok:
pkg := localpkg
if t.Sym != nil {
pkg = t.Sym.Pkg
} else {
// Unnamed type. Grab the package from the first field, if any.
for _, f := range t.Fields().Slice() {
if f.Embedded != 0 {
continue
}
pkg = f.Sym.Pkg
break
}
}
ot = dgopkgpath(s, ot, pkg)
ot = dsymptr(s, ot, s, ot+Widthptr+2*Widthint+uncommonSize(t))
......
// Copyright 2016 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.
package a
type V struct{ i int }
// Copyright 2016 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.
package b
import "./a"
var V struct{ i int }
var U struct {
a.V
j int
}
// Copyright 2016 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.
package main
import (
"reflect"
_ "./a"
"./b"
)
var V struct{ i int }
func main() {
if got := reflect.ValueOf(b.V).Type().Field(0).PkgPath; got != "b" {
panic(`PkgPath=` + got + ` for first field of b.V, want "b"`)
}
if got := reflect.ValueOf(V).Type().Field(0).PkgPath; got != "main" {
panic(`PkgPath=` + got + ` for first field of V, want "main"`)
}
if got := reflect.ValueOf(b.U).Type().Field(0).PkgPath; got != "b" {
panic(`PkgPath=` + got + ` for first field of b.U, want "b"`)
}
}
// compiledir
// Copyright 2016 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.
// Tests that unexported fields of unnamed types have different PkgPath values.
package ignored
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment