]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: qualify unexported fields of unnamed types
authorDavid Crawshaw <crawshaw@golang.org>
Thu, 25 Aug 2016 18:31:50 +0000 (14:31 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Fri, 26 Aug 2016 11:46:15 +0000 (11:46 +0000)
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: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/fmt.go
src/cmd/compile/internal/gc/reflect.go
test/fixedbugs/issue16616.dir/a.go [new file with mode: 0644]
test/fixedbugs/issue16616.dir/b.go [new file with mode: 0644]
test/fixedbugs/issue16616.dir/issue16616.go [new file with mode: 0644]
test/fixedbugs/issue16616.go [new file with mode: 0644]

index 937f71469d99a503d31a87b14fdbe82ddb3decb5..49a41c8e917bbb3a73dbcaf1dbb7ce48ec3646a1 100644 (file)
@@ -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)
                        }
index cff1acc3436520e8d29dcda134db29a96e5e36c3..7ef825360b41426c20e4800d34868cd0d266f997 100644 (file)
@@ -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))
diff --git a/test/fixedbugs/issue16616.dir/a.go b/test/fixedbugs/issue16616.dir/a.go
new file mode 100644 (file)
index 0000000..0ffdbbe
--- /dev/null
@@ -0,0 +1,7 @@
+// 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 }
diff --git a/test/fixedbugs/issue16616.dir/b.go b/test/fixedbugs/issue16616.dir/b.go
new file mode 100644 (file)
index 0000000..4f238b9
--- /dev/null
@@ -0,0 +1,14 @@
+// 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
+}
diff --git a/test/fixedbugs/issue16616.dir/issue16616.go b/test/fixedbugs/issue16616.dir/issue16616.go
new file mode 100644 (file)
index 0000000..0bfadb8
--- /dev/null
@@ -0,0 +1,26 @@
+// 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"`)
+       }
+}
diff --git a/test/fixedbugs/issue16616.go b/test/fixedbugs/issue16616.go
new file mode 100644 (file)
index 0000000..a7d6ac0
--- /dev/null
@@ -0,0 +1,9 @@
+// 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