Source file test/fixedbugs/issue46304.go

     1  // run
     2  
     3  // Copyright 2021 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // This testcase caused a crash when the register ABI was in effect,
     8  // on amd64 (problem with register allocation).
     9  
    10  package main
    11  
    12  type Op struct {
    13  	tag   string
    14  	_x    []string
    15  	_q    [20]uint64
    16  	plist []P
    17  }
    18  
    19  type P struct {
    20  	tag string
    21  	_x  [10]uint64
    22  	b   bool
    23  }
    24  
    25  type M int
    26  
    27  //go:noinline
    28  func (w *M) walkP(p *P) *P {
    29  	np := &P{}
    30  	*np = *p
    31  	np.tag += "new"
    32  	return np
    33  }
    34  
    35  func (w *M) walkOp(op *Op) *Op {
    36  	if op == nil {
    37  		return nil
    38  	}
    39  
    40  	orig := op
    41  	cloned := false
    42  	clone := func() {
    43  		if !cloned {
    44  			cloned = true
    45  			op = &Op{}
    46  			*op = *orig
    47  		}
    48  	}
    49  
    50  	pCloned := false
    51  	for i := range op.plist {
    52  		if s := w.walkP(&op.plist[i]); s != &op.plist[i] {
    53  			if !pCloned {
    54  				pCloned = true
    55  				clone()
    56  				op.plist = make([]P, len(orig.plist))
    57  				copy(op.plist, orig.plist)
    58  			}
    59  			op.plist[i] = *s
    60  		}
    61  	}
    62  
    63  	return op
    64  }
    65  
    66  func main() {
    67  	var ww M
    68  	w := &ww
    69  	p1 := P{tag: "a"}
    70  	p1._x[1] = 9
    71  	o := Op{tag: "old", plist: []P{p1}}
    72  	no := w.walkOp(&o)
    73  	if no.plist[0].tag != "anew" {
    74  		panic("bad")
    75  	}
    76  }
    77  

View as plain text