]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: separate code for len, cap from code for real, imag
authorRobert Griesemer <gri@golang.org>
Wed, 7 Jun 2017 21:14:20 +0000 (14:14 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 7 Jun 2017 21:34:03 +0000 (21:34 +0000)
Prep work for issues mentioned below. No semantic or functionality change.

For #11945.
For #17446.

Change-Id: Ia1bb2b87647a6daa47f7863c0eb42cf5e1d35a7c
Reviewed-on: https://go-review.googlesource.com/45076
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/typecheck.go

index 04efcc3d823219f64f76714980048b7d65c2e349..b3dfe9dc8cc54da66768c3c6549b4ec2525b3284 100644 (file)
@@ -1341,68 +1341,51 @@ OpSwitch:
 
                break OpSwitch
 
-       case OCAP, OLEN, OREAL, OIMAG:
+       case OCAP, OLEN:
                ok |= Erv
                if !onearg(n, "%v", n.Op) {
                        n.Type = nil
                        return n
                }
+
                n.Left = typecheck(n.Left, Erv)
                n.Left = defaultlit(n.Left, nil)
-               if n.Op == OCAP || n.Op == OLEN {
-                       n.Left = implicitstar(n.Left)
-               }
+               n.Left = implicitstar(n.Left)
                l := n.Left
                t := l.Type
                if t == nil {
                        n.Type = nil
                        return n
                }
-               switch n.Op {
-               case OCAP:
-                       if !okforcap[t.Etype] {
-                               goto badcall1
-                       }
-
-               case OLEN:
-                       if !okforlen[t.Etype] {
-                               goto badcall1
-                       }
 
-               case OREAL, OIMAG:
-                       if !t.IsComplex() {
-                               goto badcall1
-                       }
-                       if Isconst(l, CTCPLX) {
-                               r := n
-                               if n.Op == OREAL {
-                                       n = nodfltconst(&l.Val().U.(*Mpcplx).Real)
-                               } else {
-                                       n = nodfltconst(&l.Val().U.(*Mpcplx).Imag)
-                               }
-                               n.Orig = r
-                       }
-
-                       n.Type = types.Types[cplxsubtype(t.Etype)]
-                       break OpSwitch
+               var ok bool
+               if n.Op == OLEN {
+                       ok = okforlen[t.Etype]
+               } else {
+                       ok = okforcap[t.Etype]
+               }
+               if !ok {
+                       yyerror("invalid argument %L for %v", n.Left, n.Op)
+                       n.Type = nil
+                       return n
                }
 
-               // might be constant
+               // result might be constant
+               var res int64 = -1 // valid if >= 0
                switch t.Etype {
                case TSTRING:
                        if Isconst(l, CTSTR) {
-                               var r Node
-                               nodconst(&r, types.Types[TINT], int64(len(l.Val().U.(string))))
-                               r.Orig = n
-                               n = &r
+                               res = int64(len(l.Val().U.(string)))
                        }
 
                case TARRAY:
-                       if callrecv(l) { // has call or receive
-                               break
+                       if !callrecv(l) {
+                               res = t.NumElem()
                        }
+               }
+               if res >= 0 {
                        var r Node
-                       nodconst(&r, types.Types[TINT], t.NumElem())
+                       nodconst(&r, types.Types[TINT], res)
                        r.Orig = n
                        n = &r
                }
@@ -1410,10 +1393,39 @@ OpSwitch:
                n.Type = types.Types[TINT]
                break OpSwitch
 
-       badcall1:
-               yyerror("invalid argument %L for %v", n.Left, n.Op)
-               n.Type = nil
-               return n
+       case OREAL, OIMAG:
+               ok |= Erv
+               if !onearg(n, "%v", n.Op) {
+                       n.Type = nil
+                       return n
+               }
+
+               n.Left = typecheck(n.Left, Erv)
+               n.Left = defaultlit(n.Left, nil)
+               l := n.Left
+               t := l.Type
+               if t == nil {
+                       n.Type = nil
+                       return n
+               }
+
+               if !t.IsComplex() {
+                       yyerror("invalid argument %L for %v", n.Left, n.Op)
+                       n.Type = nil
+                       return n
+               }
+               if Isconst(l, CTCPLX) {
+                       r := n
+                       if n.Op == OREAL {
+                               n = nodfltconst(&l.Val().U.(*Mpcplx).Real)
+                       } else {
+                               n = nodfltconst(&l.Val().U.(*Mpcplx).Imag)
+                       }
+                       n.Orig = r
+               }
+
+               n.Type = types.Types[cplxsubtype(t.Etype)]
+               break OpSwitch
 
        case OCOMPLEX:
                ok |= Erv