Commits

Anonymous committed e2ec9e4

cmd/gc: avoid clobbering the AST in cgen_callmeth.

It confused the detection of init loops when involving
method calls.

Fixes issue 3890.

R=golang-dev, rsc
CC=golang-dev
http://codereview.appspot.com/6620067

Comments (0)

Files changed (3)

 void
 cgen_callmeth(Node *n, int proc)
 {
+	Node n2;
 	Node *l;
 
-	// generate a rewrite for method call
+	// generate a rewrite in n2 for the method call
 	// (p.f)(...) goes to (f)(p,...)
 
 	l = n->left;
 	if(l->op != ODOTMETH)
 		fatal("cgen_callmeth: not dotmethod: %N");
 
-	n->op = OCALLFUNC;
-	n->left = n->left->right;
-	n->left->type = l->type;
+	n2 = *n;
+	n2.op = OCALLFUNC;
+	n2.left = l->right;
+	n2.left->type = l->type;
 
-	if(n->left->op == ONAME)
-		n->left->class = PFUNC;
-	cgen_call(n, proc);
+	if(n2.left->op == ONAME)
+		n2.left->class = PFUNC;
+	cgen_call(&n2, proc);
 }
 
 /*

src/cmd/gc/sinit.c

 	init1(n->right, out);
 	for(l=n->list; l; l=l->next)
 		init1(l->n, out);
+
 	if(n->left && n->type && n->left->op == OTYPE && n->class == PFUNC) {
+		// Methods called as Type.Method(receiver, ...).
 		// Definitions for method expressions are stored in type->nname.
 		init1(n->type->nname, out);
 	}

test/fixedbugs/bug459.go

+// 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 3890: missing detection of init loop involving
+// method calls in function bodies.
+
+package flag
+
+var commandLine = NewFlagSet() // ERROR "loop"
+
+type FlagSet struct {
+}
+
+func (f *FlagSet) failf(format string, a ...interface{}) {
+	f.usage()
+}
+
+func (f *FlagSet) usage() {
+	if f == commandLine {
+		panic(3)
+	}
+}
+
+func NewFlagSet() *FlagSet {
+	f := &FlagSet{}
+	f.setErrorHandling(true)
+	return f
+}
+
+func (f *FlagSet) setErrorHandling(b bool) {
+	f.failf("DIE")
+}