mirror of
https://github.com/golang/go
synced 2024-11-11 23:10:23 -07:00
cmd/gc: avoid clobbering the AST in cgen_callmeth.
It confused the detection of init loops when involving method calls. Fixes #3890. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/6620067
This commit is contained in:
parent
46fcfdaa7d
commit
0b2ca9e62f
@ -509,22 +509,24 @@ ret:
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -36,7 +36,9 @@ init1(Node *n, NodeList **out)
|
||||
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);
|
||||
}
|
||||
|
35
test/fixedbugs/bug459.go
Normal file
35
test/fixedbugs/bug459.go
Normal file
@ -0,0 +1,35 @@
|
||||
// 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")
|
||||
}
|
Loading…
Reference in New Issue
Block a user