...
Run Format

Source file test/fixedbugs/issue16095.go

Documentation: test/fixedbugs

  // run
  
  // Copyright 2016 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.
  
  package main
  
  import (
  	"fmt"
  	"runtime"
  )
  
  var sink *[20]byte
  
  func f() (x [20]byte) {
  	// Initialize x.
  	for i := range x {
  		x[i] = byte(i)
  	}
  
  	// Force x to be allocated on the heap.
  	sink = &x
  	sink = nil
  
  	// Go to deferreturn after the panic below.
  	defer func() {
  		recover()
  	}()
  
  	// This call collects the heap-allocated version of x (oops!)
  	runtime.GC()
  
  	// Allocate that same object again and clobber it.
  	y := new([20]byte)
  	for i := 0; i < 20; i++ {
  		y[i] = 99
  	}
  	// Make sure y is heap allocated.
  	sink = y
  
  	panic(nil)
  
  	// After the recover we reach the deferreturn, which
  	// copies the heap version of x back to the stack.
  	// It gets the pointer to x from a stack slot that was
  	// not marked as live during the call to runtime.GC().
  }
  
  var sinkint int
  
  func g(p *int) (x [20]byte) {
  	// Initialize x.
  	for i := range x {
  		x[i] = byte(i)
  	}
  
  	// Force x to be allocated on the heap.
  	sink = &x
  	sink = nil
  
  	// Go to deferreturn after the panic below.
  	defer func() {
  		recover()
  	}()
  
  	// This call collects the heap-allocated version of x (oops!)
  	runtime.GC()
  
  	// Allocate that same object again and clobber it.
  	y := new([20]byte)
  	for i := 0; i < 20; i++ {
  		y[i] = 99
  	}
  	// Make sure y is heap allocated.
  	sink = y
  
  	// panic with a non-call (with no fallthrough)
  	for {
  		sinkint = *p
  	}
  
  	// After the recover we reach the deferreturn, which
  	// copies the heap version of x back to the stack.
  	// It gets the pointer to x from a stack slot that was
  	// not marked as live during the call to runtime.GC().
  }
  
  func main() {
  	x := f()
  	for i, v := range x {
  		if v != byte(i) {
  			fmt.Printf("%v\n", x)
  			panic("bad f")
  		}
  	}
  	x = g(nil)
  	for i, v := range x {
  		if v != byte(i) {
  			fmt.Printf("%v\n", x)
  			panic("bad g")
  		}
  	}
  }
  

View as plain text