return buf;
}
+/*
+ * 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.
+ */
+static void
+sprint_depchain(Fmt *fmt, NodeList *stack, Node *cur, Node *first)
+{
+ NodeList *l;
+
+ for(l = stack; l; l=l->next) {
+ if(l->n->op == cur->op) {
+ if(l->n != first)
+ sprint_depchain(fmt, l->next, l->n, first);
+ fmtprint(fmt, "\n\t%L: %N uses %N", l->n->lineno, l->n, cur);
+ return;
+ }
+ }
+}
+
/*
* type check node *np.
* replaces *np with a new pointer in some cases.
}
if(n->typecheck == 2) {
+ // Typechecking loop. Trying printing a meaningful message,
+ // otherwise a stack trace of typechecking.
+ switch(n->op) {
+ case ONAME:
+ // We can already diagnose variables used as types.
+ if((top & (Erv|Etype)) == Etype)
+ yyerror("%N is not a type", n);
+ break;
+ case OLITERAL:
+ if((top & (Erv|Etype)) == Etype) {
+ yyerror("%N is not a type", n);
+ break;
+ }
+ fmtstrinit(&fmt);
+ sprint_depchain(&fmt, tcstack, n, n);
+ yyerrorl(n->lineno, "constant definition loop%s", fmtstrflush(&fmt));
+ break;
+ }
if(nsavederrors+nerrors == 0) {
fmtstrinit(&fmt);
for(l=tcstack; l; l=l->next)
return n;
}
n->typecheck = 2;
-
+
if(tcfree != nil) {
l = tcfree;
tcfree = l->next;
--- /dev/null
+// errorcheck
+
+// Copyright 2012 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.
+
+// Issue 3757: unhelpful typechecking loop message
+// for constants that refer to themselves.
+
+package main
+
+const a = a // ERROR "refers to itself|definition loop"
+
+const (
+ X = A
+ A = B // ERROR "refers to itself|definition loop"
+ B = D
+ C, D = 1, A
+)
+
+func main() {
+}
--- /dev/null
+// errorcheck
+
+// Copyright 2012 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.
+
+// Issue 3937: unhelpful typechecking loop message
+// for identifiers wrongly used as types.
+
+package main
+
+func foo(x foo) {} // ERROR "expected type|not a type"