cmd/compile: clean up encoding of method expressions and add test

Fixes #15646.

Change-Id: Ic13d1adc0a358149209195cdb03811eeee506fb8
Reviewed-on: https://go-review.googlesource.com/23052
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go
index cd2963e..3fe7296 100644
--- a/src/cmd/compile/internal/gc/bexport.go
+++ b/src/cmd/compile/internal/gc/bexport.go
@@ -1157,9 +1157,9 @@
 		// Special case: name used as local variable in export.
 		// _ becomes ~b%d internally; print as _ for export
 		if n.Sym != nil && n.Sym.Name[0] == '~' && n.Sym.Name[1] == 'b' {
-			// case 0: mapped to ONAME
-			p.op(ONAME)
-			p.bool(true) // indicate blank identifier
+			// case 0: mapped to OPACK
+			p.op(OPACK)
+			p.string("_") // inlined and customized version of p.sym(n)
 			break
 		}
 
@@ -1174,22 +1174,18 @@
 		// but for export, this should be rendered as (*pkg.T).meth.
 		// These nodes have the special property that they are names with a left OTYPE and a right ONAME.
 		if n.Left != nil && n.Left.Op == OTYPE && n.Right != nil && n.Right.Op == ONAME {
-			// case 2: mapped to ONAME
-			p.op(ONAME)
-			// TODO(gri) can we map this case directly to OXDOT
-			//           and then get rid of the bool here?
-			p.bool(false) // indicate non-blank identifier
-			p.typ(n.Left.Type)
+			// case 2: mapped to OXDOT
+			p.op(OXDOT)
+			p.expr(n.Left) // n.Left.Op == OTYPE
 			p.fieldSym(n.Right.Sym, true)
 			break
 		}
 
 		// case 3: mapped to OPACK
-		p.op(OPACK)
-		p.sym(n) // fallthrough inlined here
+		fallthrough
 
 	case OPACK, ONONAME:
-		p.op(op)
+		p.op(OPACK)
 		p.sym(n)
 
 	case OTYPE:
@@ -1508,6 +1504,8 @@
 	}
 }
 
+// sym must encode the _ (blank) identifier as a single string "_" since
+// encoding for some nodes is based on this assumption (e.g. ONAME nodes).
 func (p *exporter) sym(n *Node) {
 	s := n.Sym
 	if s.Pkg != nil {