]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: convert typecheck_stack to []*Node
authorDave Cheney <dave@cheney.net>
Sat, 5 Sep 2015 04:43:50 +0000 (14:43 +1000)
committerDave Cheney <dave@cheney.net>
Sun, 6 Sep 2015 23:50:51 +0000 (23:50 +0000)
This one of a set of changes to make the transition away from NodeList
easier by removing cases in which NodeList doesn't act semi-trivially like a
[]*Node.

This CL was originally prepared by Josh Bleecher Snyder <josharian@gmail.com>.

This change passes go build -toolexec 'toolstash -cmp' -a std.

Change-Id: I4d041b343952f4a31f3150fd70669e08fcaa74f8
Reviewed-on: https://go-review.googlesource.com/14305
Run-TryBot: Dave Cheney <dave@cheney.net>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/cmd/compile/internal/gc/typecheck.go
test/typecheckloop.go [new file with mode: 0644]

index ff394f4f5e9fe72f3f322fca216d54ac93709c1f..7c9d85fb69049de4ebb5ae72e1bff264c18ce126 100644 (file)
@@ -89,33 +89,26 @@ func typekind(t *Type) string {
        return fmt.Sprintf("etype=%d", et)
 }
 
-/*
- * sprint_depchain prints a dependency chain
- * of nodes into fmt.
- * It is used by typecheck in the case of OLITERAL nodes
- * to print constant definition loops.
- */
-func sprint_depchain(fmt_ *string, stack *NodeList, cur *Node, first *Node) {
-       for l := stack; l != nil; l = l.Next {
-               if l.N.Op == cur.Op {
-                       if l.N != first {
-                               sprint_depchain(fmt_, l.Next, l.N, first)
+// sprint_depchain prints a dependency chain of nodes into fmt.
+// It is used by typecheck in the case of OLITERAL nodes
+// to print constant definition loops.
+func sprint_depchain(fmt_ *string, stack []*Node, cur *Node, first *Node) {
+       for i := len(stack) - 1; i >= 0; i-- {
+               if n := stack[i]; n.Op == cur.Op {
+                       if n != first {
+                               sprint_depchain(fmt_, stack[:i], n, first)
                        }
-                       *fmt_ += fmt.Sprintf("\n\t%v: %v uses %v", l.N.Line(), l.N, cur)
+                       *fmt_ += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
                        return
                }
        }
 }
 
-/*
- * type check node *np.
- * replaces *np with a new pointer in some cases.
- * returns the final value of *np as a convenience.
- */
-
-var typecheck_tcstack *NodeList
-var typecheck_tcfree *NodeList
+var typecheck_tcstack []*Node
 
+// typecheck type checks node *np.
+// It replaces *np with a new pointer in some cases.
+// It returns the final value of *np as a convenience.
 func typecheck(np **Node, top int) *Node {
        // cannot type check until all the source has been parsed
        if !typecheckok {
@@ -168,16 +161,15 @@ func typecheck(np **Node, top int) *Node {
                                Yyerror("%v is not a type", n)
                                break
                        }
-
-                       fmt_ = ""
                        sprint_depchain(&fmt_, typecheck_tcstack, n, n)
                        yyerrorl(int(n.Lineno), "constant definition loop%s", fmt_)
                }
 
                if nsavederrors+nerrors == 0 {
                        fmt_ = ""
-                       for l := typecheck_tcstack; l != nil; l = l.Next {
-                               fmt_ += fmt.Sprintf("\n\t%v %v", l.N.Line(), l.N)
+                       for i := len(typecheck_tcstack) - 1; i >= 0; i-- {
+                               x := typecheck_tcstack[i]
+                               fmt_ += fmt.Sprintf("\n\t%v %v", x.Line(), x)
                        }
                        Yyerror("typechecking loop involving %v%s", n, fmt_)
                }
@@ -188,27 +180,15 @@ func typecheck(np **Node, top int) *Node {
 
        n.Typecheck = 2
 
-       var l *NodeList
-       if typecheck_tcfree != nil {
-               l = typecheck_tcfree
-               typecheck_tcfree = l.Next
-       } else {
-               l = new(NodeList)
-       }
-       l.Next = typecheck_tcstack
-       l.N = n
-       typecheck_tcstack = l
-
+       typecheck_tcstack = append(typecheck_tcstack, n)
        typecheck1(&n, top)
        *np = n
+
        n.Typecheck = 1
 
-       if typecheck_tcstack != l {
-               Fatalf("typecheck stack out of sync")
-       }
-       typecheck_tcstack = l.Next
-       l.Next = typecheck_tcfree
-       typecheck_tcfree = l
+       last := len(typecheck_tcstack) - 1
+       typecheck_tcstack[last] = nil
+       typecheck_tcstack = typecheck_tcstack[:last]
 
        lineno = int32(lno)
        return n
diff --git a/test/typecheckloop.go b/test/typecheckloop.go
new file mode 100644 (file)
index 0000000..3b3e788
--- /dev/null
@@ -0,0 +1,14 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+// Verify that constant definition loops are caught during
+// typechecking and that the errors print correctly.
+
+package main
+
+const A = 1 + B // ERROR "constant definition loop\n.*A uses B\n.*B uses C\n.*C uses A"
+const B = C - 1 // ERROR "constant definition loop\n.*B uses C\n.*C uses B"
+const C = A + B + 1