]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: simplify OPTRLIT handling
authorMatthew Dempsky <mdempsky@google.com>
Wed, 25 Sep 2019 07:21:23 +0000 (00:21 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 26 Sep 2019 18:45:53 +0000 (18:45 +0000)
Previously, we would recognize &(T{...}) expressions during type
checking, rewrite them into (*T){...}, and then do a lot of extra work
to make sure the user doesn't write (*T){...} themselves and
resynthesizing the OPTRLIT later on.

This CL simply handles &T{...} directly in the straight forward
manner, by changing OADDR directly to OPTRLIT when appropriate.

While here, match go/types's invalid composite literal type error
message.

Passes toolstash-check.

Change-Id: I902b14c7e2cd9fa93e6915dd58272d2352ba38f8
Reviewed-on: https://go-review.googlesource.com/c/go/+/197120
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/closure.go
src/cmd/compile/internal/gc/fmt.go
src/cmd/compile/internal/gc/iexport.go
src/cmd/compile/internal/gc/iimport.go
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/gc/typecheck.go
test/complit1.go

index 21b3461b47fb82bc54e9729a45cc719a019e1696..6080777e8ecda8286b0b4c435af10e064ee07eb9 100644 (file)
@@ -395,18 +395,16 @@ func walkclosure(clo *Node, init *Nodes) *Node {
 
        typ := closureType(clo)
 
-       clos := nod(OCOMPLIT, nil, nod(ODEREF, typenod(typ), nil))
+       clos := nod(OCOMPLIT, nil, typenod(typ))
        clos.Esc = clo.Esc
-       clos.Right.SetImplicit(true)
        clos.List.Set(append([]*Node{nod(OCFUNC, xfunc.Func.Nname, nil)}, clo.Func.Enter.Slice()...))
 
+       clos = nod(OADDR, clos, nil)
+       clos.Esc = clo.Esc
+
        // Force type conversion from *struct to the func type.
        clos = convnop(clos, clo.Type)
 
-       // typecheck will insert a PTRLIT node under CONVNOP,
-       // tag it with escape analysis result.
-       clos.Left.Esc = clo.Esc
-
        // non-escaping temp to use, if any.
        if x := prealloc[clo]; x != nil {
                if !types.Identical(typ, x.Type) {
@@ -547,18 +545,16 @@ func walkpartialcall(n *Node, init *Nodes) *Node {
 
        typ := partialCallType(n)
 
-       clos := nod(OCOMPLIT, nil, nod(ODEREF, typenod(typ), nil))
+       clos := nod(OCOMPLIT, nil, typenod(typ))
        clos.Esc = n.Esc
-       clos.Right.SetImplicit(true)
        clos.List.Set2(nod(OCFUNC, n.Func.Nname, nil), n.Left)
 
+       clos = nod(OADDR, clos, nil)
+       clos.Esc = n.Esc
+
        // Force type conversion from *struct to the func type.
        clos = convnop(clos, n.Type)
 
-       // The typecheck inside convnop will insert a PTRLIT node under CONVNOP.
-       // Tag it with escape analysis result.
-       clos.Left.Esc = n.Esc
-
        // non-escaping temp to use, if any.
        if x := prealloc[n]; x != nil {
                if !types.Identical(typ, x.Type) {
index e7a2def9504c920512e27c4fe97f8e742e02c316..e449444ca576cec2338afc310bde5cbeb8157ec7 100644 (file)
@@ -1304,12 +1304,8 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
 
        case OCOMPLIT:
                if mode == FErr {
-                       if n.Right != nil && n.Right.Type != nil && !n.Implicit() {
-                               if n.Right.Implicit() && n.Right.Type.IsPtr() {
-                                       mode.Fprintf(s, "&%v literal", n.Right.Type.Elem())
-                                       return
-                               }
-                               mode.Fprintf(s, "%v literal", n.Right.Type)
+                       if n.Right != nil {
+                               mode.Fprintf(s, "%v literal", n.Right)
                                return
                        }
 
index eeca0b4083a7a8ce3cca5e99f24106667b5f3b44..da0a8be30e62a89cad620ef4b5a9b746f9e6b241 100644 (file)
@@ -1181,10 +1181,10 @@ func (w *exportWriter) expr(n *Node) {
        //      should have been resolved by typechecking - handled by default case
 
        case OPTRLIT:
-               w.op(OPTRLIT)
+               w.op(OPTRLIT) // TODO(mdempsky): Replace with OADDR.
                w.pos(n.Pos)
                w.expr(n.Left)
-               w.bool(n.Implicit())
+               w.bool(false)
 
        case OSTRUCTLIT:
                w.op(OSTRUCTLIT)
index 4862f86344ff971fb7bef3d174e98e45806a68f1..dd35b9ba46c36c89e8f2d132c9a9eb3f8278eb08 100644 (file)
@@ -802,17 +802,8 @@ func (r *importReader) node() *Node {
        //      unimplemented
 
        case OPTRLIT:
-               pos := r.pos()
-               n := npos(pos, r.expr())
-               if !r.bool() /* !implicit, i.e. '&' operator */ {
-                       if n.Op == OCOMPLIT {
-                               // Special case for &T{...}: turn into (*T){...}.
-                               n.Right = nodl(pos, ODEREF, n.Right, nil)
-                               n.Right.SetImplicit(true)
-                       } else {
-                               n = nodl(pos, OADDR, n, nil)
-                       }
-               }
+               n := nodl(r.pos(), OADDR, r.expr(), nil)
+               _ = r.bool()
                return n
 
        case OSTRUCTLIT:
index 91c7fd49b1791728e1bf2c02e7c3be1d8910bd2f..2922f9a87276ef059eea0df1e55b2d1505006352 100644 (file)
@@ -662,15 +662,6 @@ func (p *noder) expr(expr syntax.Expr) *Node {
                }
                x := p.expr(expr.X)
                if expr.Y == nil {
-                       if expr.Op == syntax.And {
-                               x = unparen(x) // TODO(mdempsky): Needed?
-                               if x.Op == OCOMPLIT {
-                                       // Special case for &T{...}: turn into (*T){...}.
-                                       x.Right = p.nod(expr, ODEREF, x.Right, nil)
-                                       x.Right.SetImplicit(true)
-                                       return x
-                               }
-                       }
                        return p.nod(expr, p.unOp(expr.Op), x, nil)
                }
                return p.nod(expr, p.binOp(expr.Op), x, p.expr(expr.Y))
index 7d0d5f35be9b79fd67efb32db06033c72a6ab24b..989805c1df43c59e3029b58aec4062332545bfa0 100644 (file)
@@ -830,36 +830,38 @@ func typecheck1(n *Node, top int) (res *Node) {
                        n.Type = nil
                        return n
                }
-               checklvalue(n.Left, "take the address of")
-               r := outervalue(n.Left)
-               var l *Node
-               for l = n.Left; l != r; l = l.Left {
-                       l.SetAddrtaken(true)
-                       if l.IsClosureVar() && !capturevarscomplete {
-                               // Mark the original variable as Addrtaken so that capturevars
-                               // knows not to pass it by value.
-                               // But if the capturevars phase is complete, don't touch it,
-                               // in case l.Name's containing function has not yet been compiled.
-                               l.Name.Defn.SetAddrtaken(true)
+
+               switch n.Left.Op {
+               case OARRAYLIT, OMAPLIT, OSLICELIT, OSTRUCTLIT:
+                       n.Op = OPTRLIT
+
+               default:
+                       checklvalue(n.Left, "take the address of")
+                       r := outervalue(n.Left)
+                       if r.Orig != r && r.Op == ONAME {
+                               Fatalf("found non-orig name node %v", r) // TODO(mdempsky): What does this mean?
+                       }
+                       for l := n.Left; ; l = l.Left {
+                               l.SetAddrtaken(true)
+                               if l.IsClosureVar() && !capturevarscomplete {
+                                       // Mark the original variable as Addrtaken so that capturevars
+                                       // knows not to pass it by value.
+                                       // But if the capturevars phase is complete, don't touch it,
+                                       // in case l.Name's containing function has not yet been compiled.
+                                       l.Name.Defn.SetAddrtaken(true)
+                               }
+                               if l == r {
+                                       break
+                               }
+                       }
+                       n.Left = defaultlit(n.Left, nil)
+                       if n.Left.Type == nil {
+                               n.Type = nil
+                               return n
                        }
                }
 
-               if l.Orig != l && l.Op == ONAME {
-                       Fatalf("found non-orig name node %v", l)
-               }
-               l.SetAddrtaken(true)
-               if l.IsClosureVar() && !capturevarscomplete {
-                       // See comments above about closure variables.
-                       l.Name.Defn.SetAddrtaken(true)
-               }
-               n.Left = defaultlit(n.Left, nil)
-               l = n.Left
-               t := l.Type
-               if t == nil {
-                       n.Type = nil
-                       return n
-               }
-               n.Type = types.NewPtr(t)
+               n.Type = types.NewPtr(n.Left.Type)
 
        case OCOMPLIT:
                ok |= ctxExpr
@@ -2723,13 +2725,8 @@ func fielddup(name string, hash map[string]bool) {
        hash[name] = true
 }
 
-// iscomptype reports whether type t is a composite literal type
-// or a pointer to one.
+// iscomptype reports whether type t is a composite literal type.
 func iscomptype(t *types.Type) bool {
-       if t.IsPtr() {
-               t = t.Elem()
-       }
-
        switch t.Etype {
        case TARRAY, TSLICE, TSTRUCT, TMAP:
                return true
@@ -2738,16 +2735,27 @@ func iscomptype(t *types.Type) bool {
        }
 }
 
-func pushtype(n *Node, t *types.Type) {
-       if n == nil || n.Op != OCOMPLIT || !iscomptype(t) {
-               return
+// pushtype adds elided type information for composite literals if
+// appropriate, and returns the resulting expression.
+func pushtype(n *Node, t *types.Type) *Node {
+       if n == nil || n.Op != OCOMPLIT || n.Right != nil {
+               return n
        }
 
-       if n.Right == nil {
+       switch {
+       case iscomptype(t):
+               // For T, return T{...}.
                n.Right = typenod(t)
-               n.SetImplicit(true)       // don't print
-               n.Right.SetImplicit(true) // * is okay
+
+       case t.IsPtr() && iscomptype(t.Elem()):
+               // For *T, return &T{...}.
+               n.Right = typenod(t.Elem())
+
+               n = nodl(n.Pos, OADDR, n, nil)
+               n.SetImplicit(true)
        }
+
+       return n
 }
 
 // The result of typecheckcomplit MUST be assigned back to n, e.g.
@@ -2782,28 +2790,9 @@ func typecheckcomplit(n *Node) (res *Node) {
        nerr := nerrors
        n.Type = t
 
-       if t.IsPtr() {
-               // For better or worse, we don't allow pointers as the composite literal type,
-               // except when using the &T syntax, which sets implicit on the ODEREF.
-               if !n.Right.Implicit() {
-                       yyerror("invalid pointer type %v for composite literal (use &%v instead)", t, t.Elem())
-                       n.Type = nil
-                       return n
-               }
-
-               // Also, the underlying type must be a struct, map, slice, or array.
-               if !iscomptype(t) {
-                       yyerror("invalid pointer type %v for composite literal", t)
-                       n.Type = nil
-                       return n
-               }
-
-               t = t.Elem()
-       }
-
        switch t.Etype {
        default:
-               yyerror("invalid type for composite literal: %v", t)
+               yyerror("invalid composite literal type %v", t)
                n.Type = nil
 
        case TARRAY, TSLICE:
@@ -2850,7 +2839,7 @@ func typecheckcomplit(n *Node) (res *Node) {
                        }
 
                        r := *vp
-                       pushtype(r, t.Elem())
+                       r = pushtype(r, t.Elem())
                        r = typecheck(r, ctxExpr)
                        *vp = assignconv(r, t.Elem(), "array or slice literal")
 
@@ -2887,13 +2876,13 @@ func typecheckcomplit(n *Node) (res *Node) {
                        }
 
                        r := l.Left
-                       pushtype(r, t.Key())
+                       r = pushtype(r, t.Key())
                        r = typecheck(r, ctxExpr)
                        l.Left = assignconv(r, t.Key(), "map key")
                        cs.add(lineno, l.Left, "key", "map literal")
 
                        r = l.Right
-                       pushtype(r, t.Elem())
+                       r = pushtype(r, t.Elem())
                        r = typecheck(r, ctxExpr)
                        l.Right = assignconv(r, t.Elem(), "map value")
                }
@@ -3024,15 +3013,6 @@ func typecheckcomplit(n *Node) (res *Node) {
                return n
        }
 
-       n.Orig = norig
-       if n.Type.IsPtr() {
-               n = nodl(n.Pos, OPTRLIT, n, nil)
-               n.SetTypecheck(1)
-               n.Type = n.Left.Type
-               n.Left.Type = t
-               n.Left.SetTypecheck(1)
-       }
-
        n.Orig = norig
        return n
 }
index 83695a9e88c0299e509b6e6ea326ffd58dba89be..eb0f920fcbde0d20616b6630f7b7f32978735687 100644 (file)
@@ -46,8 +46,8 @@ var (
        _ = &T{0, 0, "", nil}               // ok
        _ = &T{i: 0, f: 0, s: "", next: {}} // ERROR "missing type in composite literal|omit types within composite literal"
        _ = &T{0, 0, "", {}}                // ERROR "missing type in composite literal|omit types within composite literal"
-       _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid pointer type"
-       _ = &Ti{}                           // ERROR "invalid pointer type"
+       _ = TP{i: 0, f: 0, s: "", next: {}} // ERROR "invalid composite literal type TP"
+       _ = &Ti{}                           // ERROR "invalid composite literal type Ti"
 )
 
 type M map[T]T