]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: cleanup for concrete types - noder
authorRuss Cox <rsc@golang.org>
Thu, 10 Dec 2020 23:48:18 +0000 (18:48 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 17 Dec 2020 04:43:46 +0000 (04:43 +0000)
An automated rewrite will add concrete type assertions after
a test of n.Op(), when n can be safely type-asserted
(meaning, n is not reassigned a different type, n is not reassigned
and then used outside the scope of the type assertion,
and so on).

This sequence of CLs handles the code that the automated
rewrite does not: adding specific types to function arguments,
adjusting code not to call n.Left() etc when n may have multiple
representations, and so on.

This CL focuses on noder.go.

Passes buildall w/ toolstash -cmp.

Change-Id: Ie870126b51558e83c738add8e91a2804ed6d7f92
Reviewed-on: https://go-review.googlesource.com/c/go/+/277931
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/noder.go
test/mainsig.go [new file with mode: 0644]

index 4c8e56731bee26f0fe092dd4c3a3701d2fd5f228..43ec2ce35008ec0859c29e236871d8a1e8267f91 100644 (file)
@@ -527,13 +527,13 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
        if fun.Recv == nil {
                if name.Name == "init" {
                        name = renameinit()
-                       if t.List().Len() > 0 || t.Rlist().Len() > 0 {
+                       if len(t.Params) > 0 || len(t.Results) > 0 {
                                base.ErrorfAt(f.Pos(), "func init must have no arguments and no return values")
                        }
                }
 
                if types.LocalPkg.Name == "main" && name.Name == "main" {
-                       if t.List().Len() > 0 || t.Rlist().Len() > 0 {
+                       if len(t.Params) > 0 || len(t.Results) > 0 {
                                base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values")
                        }
                }
@@ -983,10 +983,10 @@ func (p *noder) stmtsFall(stmts []syntax.Stmt, fallOK bool) []ir.Node {
        for i, stmt := range stmts {
                s := p.stmtFall(stmt, fallOK && i+1 == len(stmts))
                if s == nil {
-               } else if s.Op() == ir.OBLOCK && s.List().Len() > 0 {
+               } else if s.Op() == ir.OBLOCK && s.(*ir.BlockStmt).List().Len() > 0 {
                        // Inline non-empty block.
                        // Empty blocks must be preserved for checkreturn.
-                       nodes = append(nodes, s.List().Slice()...)
+                       nodes = append(nodes, s.(*ir.BlockStmt).List().Slice()...)
                } else {
                        nodes = append(nodes, s)
                }
@@ -1020,22 +1020,23 @@ func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
                return liststmt(p.decls(stmt.DeclList))
        case *syntax.AssignStmt:
                if stmt.Op != 0 && stmt.Op != syntax.Def {
-                       n := p.nod(stmt, ir.OASOP, p.expr(stmt.Lhs), p.expr(stmt.Rhs))
+                       n := ir.NewAssignOpStmt(p.pos(stmt), p.binOp(stmt.Op), p.expr(stmt.Lhs), p.expr(stmt.Rhs))
                        n.SetImplicit(stmt.Rhs == syntax.ImplicitOne)
-                       n.SetSubOp(p.binOp(stmt.Op))
                        return n
                }
 
                rhs := p.exprList(stmt.Rhs)
                if list, ok := stmt.Lhs.(*syntax.ListExpr); ok && len(list.ElemList) != 1 || len(rhs) != 1 {
                        n := p.nod(stmt, ir.OAS2, nil, nil)
-                       n.PtrList().Set(p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def))
+                       n.SetColas(stmt.Op == syntax.Def)
+                       n.PtrList().Set(p.assignList(stmt.Lhs, n, n.Colas()))
                        n.PtrRlist().Set(rhs)
                        return n
                }
 
                n := p.nod(stmt, ir.OAS, nil, nil)
-               n.SetLeft(p.assignList(stmt.Lhs, n, stmt.Op == syntax.Def)[0])
+               n.SetColas(stmt.Op == syntax.Def)
+               n.SetLeft(p.assignList(stmt.Lhs, n, n.Colas())[0])
                n.SetRight(rhs[0])
                return n
 
@@ -1110,8 +1111,6 @@ func (p *noder) assignList(expr syntax.Expr, defn ir.Node, colas bool) []ir.Node
                return p.exprList(expr)
        }
 
-       defn.SetColas(true)
-
        var exprs []syntax.Expr
        if list, ok := expr.(*syntax.ListExpr); ok {
                exprs = list.ElemList
@@ -1196,27 +1195,30 @@ func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
 
 func (p *noder) forStmt(stmt *syntax.ForStmt) ir.Node {
        p.openScope(stmt.Pos())
-       var n ir.Node
        if r, ok := stmt.Init.(*syntax.RangeClause); ok {
                if stmt.Cond != nil || stmt.Post != nil {
                        panic("unexpected RangeClause")
                }
 
-               n = p.nod(r, ir.ORANGE, nil, p.expr(r.X))
+               n := p.nod(r, ir.ORANGE, nil, p.expr(r.X))
                if r.Lhs != nil {
-                       n.PtrList().Set(p.assignList(r.Lhs, n, r.Def))
-               }
-       } else {
-               n = p.nod(stmt, ir.OFOR, nil, nil)
-               if stmt.Init != nil {
-                       n.PtrInit().Set1(p.stmt(stmt.Init))
-               }
-               if stmt.Cond != nil {
-                       n.SetLeft(p.expr(stmt.Cond))
-               }
-               if stmt.Post != nil {
-                       n.SetRight(p.stmt(stmt.Post))
+                       n.SetColas(r.Def)
+                       n.PtrList().Set(p.assignList(r.Lhs, n, n.Colas()))
                }
+               n.PtrBody().Set(p.blockStmt(stmt.Body))
+               p.closeAnotherScope()
+               return n
+       }
+
+       n := p.nod(stmt, ir.OFOR, nil, nil)
+       if stmt.Init != nil {
+               n.PtrInit().Set1(p.stmt(stmt.Init))
+       }
+       if stmt.Cond != nil {
+               n.SetLeft(p.expr(stmt.Cond))
+       }
+       if stmt.Post != nil {
+               n.SetRight(p.stmt(stmt.Post))
        }
        n.PtrBody().Set(p.blockStmt(stmt.Body))
        p.closeAnotherScope()
@@ -1233,9 +1235,9 @@ func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
                n.SetLeft(p.expr(stmt.Tag))
        }
 
-       tswitch := n.Left()
-       if tswitch != nil && tswitch.Op() != ir.OTYPESW {
-               tswitch = nil
+       var tswitch *ir.TypeSwitchGuard
+       if l := n.Left(); l != nil && l.Op() == ir.OTYPESW {
+               tswitch = l.(*ir.TypeSwitchGuard)
        }
        n.PtrList().Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace))
 
@@ -1243,7 +1245,7 @@ func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
        return n
 }
 
-func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch ir.Node, rbrace syntax.Pos) []ir.Node {
+func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []ir.Node {
        nodes := make([]ir.Node, 0, len(clauses))
        for i, clause := range clauses {
                p.setlineno(clause)
@@ -1328,10 +1330,18 @@ func (p *noder) labeledStmt(label *syntax.LabeledStmt, fallOK bool) ir.Node {
        var ls ir.Node
        if label.Stmt != nil { // TODO(mdempsky): Should always be present.
                ls = p.stmtFall(label.Stmt, fallOK)
-               switch label.Stmt.(type) {
-               case *syntax.ForStmt, *syntax.SwitchStmt, *syntax.SelectStmt:
-                       // Attach label directly to control statement too.
-                       ls.SetSym(sym)
+               // Attach label directly to control statement too.
+               if ls != nil {
+                       switch ls.Op() {
+                       case ir.OFOR:
+                               ls.SetSym(sym)
+                       case ir.ORANGE:
+                               ls.SetSym(sym)
+                       case ir.OSWITCH:
+                               ls.SetSym(sym)
+                       case ir.OSELECT:
+                               ls.SetSym(sym)
+                       }
                }
        }
 
@@ -1483,8 +1493,9 @@ func (p *noder) wrapname(n syntax.Node, x ir.Node) ir.Node {
                }
                fallthrough
        case ir.ONAME, ir.ONONAME, ir.OPACK:
-               x = p.nod(n, ir.OPAREN, x, nil)
-               x.SetImplicit(true)
+               p := p.nod(n, ir.OPAREN, x, nil)
+               p.SetImplicit(true)
+               return p
        }
        return x
 }
diff --git a/test/mainsig.go b/test/mainsig.go
new file mode 100644 (file)
index 0000000..d006d9c
--- /dev/null
@@ -0,0 +1,13 @@
+// errorcheck
+
+// Copyright 2020 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
+
+func main(int)  {}           // ERROR "func main must have no arguments and no return values"
+func main() int { return 1 } // ERROR "func main must have no arguments and no return values" "main redeclared in this block"
+
+func init(int)  {}           // ERROR "func init must have no arguments and no return values"
+func init() int { return 1 } // ERROR "func init must have no arguments and no return values"