1// run
2
3// Copyright 2020 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//go:build cgo
8
9package main
10
11import (
12	"runtime/cgo"
13	"unsafe"
14)
15
16type S struct {
17	_ cgo.Incomplete
18	x int
19}
20
21func main() {
22	var i int
23	p := (*S)(unsafe.Pointer(uintptr(unsafe.Pointer(&i))))
24	v := uintptr(unsafe.Pointer(p))
25	// p is a pointer to a not-in-heap type. Like some C libraries,
26	// we stored an integer in that pointer. That integer just happens
27	// to be the address of i.
28	// v is also the address of i.
29	// p has a base type which is marked not-in-heap, so it
30	// should not be adjusted when the stack is copied.
31	recurse(100, p, v)
32}
33func recurse(n int, p *S, v uintptr) {
34	if n > 0 {
35		recurse(n-1, p, v)
36	}
37	if uintptr(unsafe.Pointer(p)) != v {
38		panic("adjusted notinheap pointer")
39	}
40}
41