Consider this test case:
package main
type CloseSetter interface {
Set()
Close() error
}
type S1 struct {
f int
}
func (p *S1) Close() error {
if p.f != 0 {
panic(p.f)
}
return nil
}
type S2 struct {
*S1
}
func (p *S2) Set() {
p.S1 = &S1{0}
}
func F1(p CloseSetter) {
p.Set()
p.Close()
}
func F2() {
s2 := &S2{}
defer s2.Close()
F1(s2)
}
func main() {
F2()
}
When run with the gc compiler, this crashes:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x455534]
goroutine 1 [running]:
main.(*S1).Close(0xc000096000?)
/home/iant/foo10.go:13 +0x14
main.F2()
/home/iant/foo10.go:36 +0x7c
main.main()
/home/iant/foo10.go:39 +0x17
exit status 2
When run with the gccgo compiler it exits successfully without printing anything.
I think the difference is that with the gc compiler the defer statement is resolving the embedded pointer at the point of the defer, and thus deferred a call to a nil pointer. If that is correct, then that seems wrong. A defer statement resolves all the arguments, but it shouldn't resolve s2 into s2.S1.
Or maybe gccgo is incorrectly not crashing, but I don't yet see it.
CC @randall77 @griesemer @mdempsky
Consider this test case:
When run with the gc compiler, this crashes:
When run with the gccgo compiler it exits successfully without printing anything.
I think the difference is that with the gc compiler the
deferstatement is resolving the embedded pointer at the point of thedefer, and thus deferred a call to a nil pointer. If that is correct, then that seems wrong. Adeferstatement resolves all the arguments, but it shouldn't resolves2intos2.S1.Or maybe gccgo is incorrectly not crashing, but I don't yet see it.
CC @randall77 @griesemer @mdempsky