diff --git a/api/next/46731.txt b/api/next/46731.txt new file mode 100644 index 00000000000..1d491ef7ecd --- /dev/null +++ b/api/next/46731.txt @@ -0,0 +1,14 @@ +pkg runtime/cgo (darwin-amd64-cgo), type Incomplete struct #46731 +pkg runtime/cgo (freebsd-386-cgo), type Incomplete struct #46731 +pkg runtime/cgo (freebsd-amd64-cgo), type Incomplete struct #46731 +pkg runtime/cgo (freebsd-arm-cgo), type Incomplete struct #46731 +pkg runtime/cgo (linux-386-cgo), type Incomplete struct #46731 +pkg runtime/cgo (linux-amd64-cgo), type Incomplete struct #46731 +pkg runtime/cgo (linux-arm-cgo), type Incomplete struct #46731 +pkg runtime/cgo (netbsd-386-cgo), type Incomplete struct #46731 +pkg runtime/cgo (netbsd-amd64-cgo), type Incomplete struct #46731 +pkg runtime/cgo (netbsd-arm-cgo), type Incomplete struct #46731 +pkg runtime/cgo (netbsd-arm64-cgo), type Incomplete struct #46731 +pkg runtime/cgo (openbsd-386-cgo), type Incomplete struct #46731 +pkg runtime/cgo (openbsd-amd64-cgo), type Incomplete struct #46731 +pkg runtime/cgo, type Incomplete struct #46731 diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index d89bff287b3..43f94bb0e53 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -2154,8 +2154,8 @@ type typeConv struct { // Type names X for which there exists an XGetTypeID function with type func() CFTypeID. getTypeIDs map[string]bool - // badStructs contains C structs that should be marked NotInHeap. - notInHeapStructs map[string]bool + // incompleteStructs contains C structs that should be marked Incomplete. + incompleteStructs map[string]bool // Predeclared types. bool ast.Expr @@ -2168,7 +2168,6 @@ type typeConv struct { string ast.Expr goVoid ast.Expr // _Ctype_void, denotes C's void goVoidPtr ast.Expr // unsafe.Pointer or *byte - goVoidPtrNoHeap ast.Expr // *_Ctype_void_notinheap, like goVoidPtr but marked NotInHeap ptrSize int64 intSize int64 @@ -2192,7 +2191,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) { c.m = make(map[string]*Type) c.ptrs = make(map[string][]*Type) c.getTypeIDs = make(map[string]bool) - c.notInHeapStructs = make(map[string]bool) + c.incompleteStructs = make(map[string]bool) c.bool = c.Ident("bool") c.byte = c.Ident("byte") c.int8 = c.Ident("int8") @@ -2211,7 +2210,6 @@ func (c *typeConv) Init(ptrSize, intSize int64) { c.void = c.Ident("void") c.string = c.Ident("string") c.goVoid = c.Ident("_Ctype_void") - c.goVoidPtrNoHeap = c.Ident("*_Ctype_void_notinheap") // Normally cgo translates void* to unsafe.Pointer, // but for historical reasons -godefs uses *byte instead. @@ -2561,19 +2559,13 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ // other than try to determine a Go representation. tt := *t tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}} - tt.Go = c.Ident("struct{}") - if dt.Kind == "struct" { - // We don't know what the representation of this struct is, so don't let - // anyone allocate one on the Go side. As a side effect of this annotation, - // pointers to this type will not be considered pointers in Go. They won't - // get writebarrier-ed or adjusted during a stack copy. This should handle - // all the cases badPointerTypedef used to handle, but hopefully will - // continue to work going forward without any more need for cgo changes. - tt.NotInHeap = true - // TODO: we should probably do the same for unions. Unions can't live - // on the Go heap, right? It currently doesn't work for unions because - // they are defined as a type alias for struct{}, not a defined type. - } + // We don't know what the representation of this struct is, so don't let + // anyone allocate one on the Go side. As a side effect of this annotation, + // pointers to this type will not be considered pointers in Go. They won't + // get writebarrier-ed or adjusted during a stack copy. This should handle + // all the cases badPointerTypedef used to handle, but hopefully will + // continue to work going forward without any more need for cgo changes. + tt.Go = c.Ident("_cgopackage.Incomplete") typedef[name.Name] = &tt break } @@ -2599,7 +2591,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ tt.C = &TypeRepr{"struct %s", []interface{}{tag}} } tt.Go = g - tt.NotInHeap = c.notInHeapStructs[tag] + if c.incompleteStructs[tag] { + tt.Go = c.Ident("_cgopackage.Incomplete") + } typedef[name.Name] = &tt } @@ -2644,9 +2638,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ } } if c.badVoidPointerTypedef(dt) { - // Treat this typedef as a pointer to a NotInHeap void. + // Treat this typedef as a pointer to a _cgopackage.Incomplete. s := *sub - s.Go = c.goVoidPtrNoHeap + s.Go = c.Ident("*_cgopackage.Incomplete") sub = &s // Make sure we update any previously computed type. if oldType := typedef[name.Name]; oldType != nil { @@ -2654,22 +2648,21 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ } } // Check for non-pointer "struct {...}; typedef struct *" - // typedefs that should be marked NotInHeap. + // typedefs that should be marked Incomplete. if ptr, ok := dt.Type.(*dwarf.PtrType); ok { if strct, ok := ptr.Type.(*dwarf.StructType); ok { if c.badStructPointerTypedef(dt.Name, strct) { - c.notInHeapStructs[strct.StructName] = true + c.incompleteStructs[strct.StructName] = true // Make sure we update any previously computed type. name := "_Ctype_struct_" + strct.StructName if oldType := typedef[name]; oldType != nil { - oldType.NotInHeap = true + oldType.Go = c.Ident("_cgopackage.Incomplete") } } } } t.Go = name t.BadPointer = sub.BadPointer - t.NotInHeap = sub.NotInHeap if unionWithPointer[sub.Go] { unionWithPointer[t.Go] = true } @@ -2680,7 +2673,6 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ tt := *t tt.Go = sub.Go tt.BadPointer = sub.BadPointer - tt.NotInHeap = sub.NotInHeap typedef[name.Name] = &tt } @@ -3204,7 +3196,7 @@ func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool { // non-pointers in this type. // TODO: Currently our best solution is to find these manually and list them as // they come up. A better solution is desired. -// Note: DEPRECATED. There is now a better solution. Search for NotInHeap in this file. +// Note: DEPRECATED. There is now a better solution. Search for _cgopackage.Incomplete in this file. func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool { if c.badCFType(dt) { return true @@ -3218,7 +3210,7 @@ func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool { return false } -// badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be NotInHeap. +// badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be _cgopackage.Incomplete. func (c *typeConv) badVoidPointerTypedef(dt *dwarf.TypedefType) bool { // Match the Windows HANDLE type (#42018). if goos != "windows" || dt.Name != "HANDLE" { diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index e3434598b2e..4f94d77c0ab 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -153,7 +153,6 @@ type Type struct { EnumValues map[string]int64 Typedef string BadPointer bool // this pointer type should be represented as a uintptr (deprecated) - NotInHeap bool // this type should have a go:notinheap annotation } // A FuncType collects information about a function type in both the C and Go worlds. diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go index 119eca2be79..6a224598cc9 100644 --- a/src/cmd/cgo/out.go +++ b/src/cmd/cgo/out.go @@ -81,11 +81,14 @@ func (p *Package) writeDefs() { fmt.Fprintf(fgo2, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n") fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName) fmt.Fprintf(fgo2, "import \"unsafe\"\n\n") - if !*gccgo && *importRuntimeCgo { - fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n") - } if *importSyscall { fmt.Fprintf(fgo2, "import \"syscall\"\n\n") + } + if *importRuntimeCgo { + fmt.Fprintf(fgo2, "import _cgopackage \"runtime/cgo\"\n\n") + fmt.Fprintf(fgo2, "type _ _cgopackage.Incomplete\n") // prevent import-not-used error + } + if *importSyscall { fmt.Fprintf(fgo2, "var _ syscall.Errno\n") } fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n") @@ -109,9 +112,6 @@ func (p *Package) writeDefs() { sort.Strings(typedefNames) for _, name := range typedefNames { def := typedef[name] - if def.NotInHeap { - fmt.Fprintf(fgo2, "//go:notinheap\n") - } fmt.Fprintf(fgo2, "type %s ", name) // We don't have source info for these types, so write them out without source info. // Otherwise types would look like: @@ -136,7 +136,6 @@ func (p *Package) writeDefs() { fmt.Fprintf(fgo2, "%s", buf.Bytes()) fmt.Fprintf(fgo2, "\n\n") } - fmt.Fprintf(fgo2, "//go:notinheap\ntype _Ctype_void_notinheap struct{}\n\n") if *gccgo { fmt.Fprintf(fgo2, "type _Ctype_void byte\n") } else { diff --git a/src/runtime/cgo/cgo.go b/src/runtime/cgo/cgo.go index 4b7046e2cc6..b8473e532d4 100644 --- a/src/runtime/cgo/cgo.go +++ b/src/runtime/cgo/cgo.go @@ -31,3 +31,10 @@ package cgo */ import "C" + +import "runtime/internal/sys" + +// Incomplete is used specifically for the semantics of incomplete C types. +type Incomplete struct { + _ sys.NotInHeap +}