mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/cgo: special case C ptr types to use uintptr
Some C types are declared as pointers, but C code stores non-pointers in them. When the Go garbage collector sees such a pointer, it gets unhappy. Instead, for these types represent them on the Go side with uintptr. We need this change to handle Apple's CoreFoundation CF*Ref types. Users of these types might need to update their code like we do in root_cgo_darwin.go. The only change that is required under normal circumstances is converting some nils to 0. A go fix module is provided to help. Fixes #21897 RELNOTE=yes Change-Id: I9716cfb255dc918792625f42952aa171cd31ec1b Reviewed-on: https://go-review.googlesource.com/66332 Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
644787c337
commit
b868616b63
10 changed files with 549 additions and 4 deletions
|
|
@ -2057,6 +2057,12 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
|||
name := c.Ident("_Ctype_" + dt.Name)
|
||||
goIdent[name.Name] = name
|
||||
sub := c.Type(dt.Type, pos)
|
||||
if badPointerTypedef(dt.Name) {
|
||||
// Treat this typedef as a uintptr.
|
||||
s := *sub
|
||||
s.Go = c.uintptr
|
||||
sub = &s
|
||||
}
|
||||
t.Go = name
|
||||
if unionWithPointer[sub.Go] {
|
||||
unionWithPointer[t.Go] = true
|
||||
|
|
@ -2215,6 +2221,11 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type {
|
|||
if _, void := base(ptr.Type).(*dwarf.VoidType); void {
|
||||
break
|
||||
}
|
||||
// ...or the typedef is one in which we expect bad pointers.
|
||||
// It will be a uintptr instead of *X.
|
||||
if badPointerTypedef(dt.Name) {
|
||||
break
|
||||
}
|
||||
|
||||
t = c.Type(ptr, pos)
|
||||
if t == nil {
|
||||
|
|
@ -2547,3 +2558,51 @@ func fieldPrefix(fld []*ast.Field) string {
|
|||
}
|
||||
return prefix
|
||||
}
|
||||
|
||||
// badPointerTypedef reports whether t is a C typedef that should not be considered a pointer in Go.
|
||||
// A typedef is bad if C code sometimes stores 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.
|
||||
func badPointerTypedef(t string) bool {
|
||||
// The real bad types are CFNumberRef and CFTypeRef.
|
||||
// Sometimes non-pointers are stored in these types.
|
||||
// CFTypeRef is a supertype of those, so it can have bad pointers in it as well.
|
||||
// We return true for the other CF*Ref types just so casting between them is easier.
|
||||
// See comment below for details about the bad pointers.
|
||||
return goos == "darwin" && strings.HasPrefix(t, "CF") && strings.HasSuffix(t, "Ref")
|
||||
}
|
||||
|
||||
// Comment from Darwin's CFInternal.h
|
||||
/*
|
||||
// Tagged pointer support
|
||||
// Low-bit set means tagged object, next 3 bits (currently)
|
||||
// define the tagged object class, next 4 bits are for type
|
||||
// information for the specific tagged object class. Thus,
|
||||
// the low byte is for type info, and the rest of a pointer
|
||||
// (32 or 64-bit) is for payload, whatever the tagged class.
|
||||
//
|
||||
// Note that the specific integers used to identify the
|
||||
// specific tagged classes can and will change from release
|
||||
// to release (that's why this stuff is in CF*Internal*.h),
|
||||
// as can the definition of type info vs payload above.
|
||||
//
|
||||
#if __LP64__
|
||||
#define CF_IS_TAGGED_OBJ(PTR) ((uintptr_t)(PTR) & 0x1)
|
||||
#define CF_TAGGED_OBJ_TYPE(PTR) ((uintptr_t)(PTR) & 0xF)
|
||||
#else
|
||||
#define CF_IS_TAGGED_OBJ(PTR) 0
|
||||
#define CF_TAGGED_OBJ_TYPE(PTR) 0
|
||||
#endif
|
||||
|
||||
enum {
|
||||
kCFTaggedObjectID_Invalid = 0,
|
||||
kCFTaggedObjectID_Atom = (0 << 1) + 1,
|
||||
kCFTaggedObjectID_Undefined3 = (1 << 1) + 1,
|
||||
kCFTaggedObjectID_Undefined2 = (2 << 1) + 1,
|
||||
kCFTaggedObjectID_Integer = (3 << 1) + 1,
|
||||
kCFTaggedObjectID_DateTS = (4 << 1) + 1,
|
||||
kCFTaggedObjectID_ManagedObjectID = (5 << 1) + 1, // Core Data
|
||||
kCFTaggedObjectID_Date = (6 << 1) + 1,
|
||||
kCFTaggedObjectID_Undefined7 = (7 << 1) + 1,
|
||||
};
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue