[release-branch.go1.9] cmd/compile: consider exported flag in namedata

It is possible to have an unexported name with a nil package,
for an embedded field whose type is a pointer to an unexported type.
We must encode that fact in the type..namedata symbol name,
to avoid incorrectly merging an unexported name with an exported name.

Fixes #21120

Change-Id: I2e3879d77fa15c05ad92e0bf8e55f74082db5111
Reviewed-on: https://go-review.googlesource.com/50710
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
Reviewed-on: https://go-review.googlesource.com/50970
Reviewed-by: Chris Broadfoot <cbro@golang.org>
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index decd3be..91e6f46 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -582,7 +582,11 @@
 				sname += "-noname-unexported." + tag
 			}
 		} else {
-			sname += name + "." + tag
+			if exported {
+				sname += name + "." + tag
+			} else {
+				sname += name + "-" + tag
+			}
 		}
 	} else {
 		sname = fmt.Sprintf(`%s"".%d`, sname, dnameCount)
diff --git a/test/fixedbugs/issue21120.dir/a.go b/test/fixedbugs/issue21120.dir/a.go
new file mode 100644
index 0000000..f2ee252
--- /dev/null
+++ b/test/fixedbugs/issue21120.dir/a.go
@@ -0,0 +1,13 @@
+// Copyright 2017 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 S struct {
+	x int
+}
+
+func V() interface{} {
+	return S{0}
+}
diff --git a/test/fixedbugs/issue21120.dir/b.go b/test/fixedbugs/issue21120.dir/b.go
new file mode 100644
index 0000000..b00bd53
--- /dev/null
+++ b/test/fixedbugs/issue21120.dir/b.go
@@ -0,0 +1,29 @@
+// Copyright 2017 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 "reflect"
+
+type X int
+
+func F1() string {
+	type x X
+
+	s := struct {
+		*x
+	}{nil}
+	v := reflect.TypeOf(s)
+	return v.Field(0).PkgPath
+}
+
+func F2() string {
+	type y X
+
+	s := struct {
+		*y
+	}{nil}
+	v := reflect.TypeOf(s)
+	return v.Field(0).PkgPath
+}
diff --git a/test/fixedbugs/issue21120.dir/main.go b/test/fixedbugs/issue21120.dir/main.go
new file mode 100644
index 0000000..1f1ec30
--- /dev/null
+++ b/test/fixedbugs/issue21120.dir/main.go
@@ -0,0 +1,25 @@
+// Copyright 2017 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 (
+	"fmt"
+	"os"
+
+	"./a"
+	"./b"
+)
+
+func main() {
+	// Make sure the reflect information for a.S is in the executable.
+	_ = a.V()
+
+	b1 := b.F1()
+	b2 := b.F2()
+	if b1 != b2 {
+		fmt.Printf("%q (from b.F1()) != %q (from b.F2())\n", b1, b2)
+		os.Exit(1)
+	}
+}
diff --git a/test/fixedbugs/issue21120.go b/test/fixedbugs/issue21120.go
new file mode 100644
index 0000000..ea896ce
--- /dev/null
+++ b/test/fixedbugs/issue21120.go
@@ -0,0 +1,11 @@
+// rundir
+
+// Copyright 2017 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.
+
+// The compiler was using an incomplete symbol name for reflect name data,
+// permitting an invalid merge in the linker, producing an incorrect
+// exported flag bit.
+
+package ignored