From: Dave Cheney Date: Sat, 5 Sep 2015 04:43:50 +0000 (+1000) Subject: cmd/compile: convert typecheck_stack to []*Node X-Git-Tag: go1.6beta1~1165 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=dab0dac01aa5074857ef8a2e089c3eda107a0fa1;p=gostls13.git cmd/compile: convert typecheck_stack to []*Node 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 . 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index ff394f4f5e..7c9d85fb69 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -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 index 0000000000..3b3e78858e --- /dev/null +++ b/test/typecheckloop.go @@ -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