diff options
Diffstat (limited to 'libgo/go/cmd/cgo/gcc.go')
-rw-r--r-- | libgo/go/cmd/cgo/gcc.go | 63 |
1 files changed, 53 insertions, 10 deletions
diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go index d9db573..fcf334e 100644 --- a/libgo/go/cmd/cgo/gcc.go +++ b/libgo/go/cmd/cgo/gcc.go @@ -243,6 +243,7 @@ func (p *Package) guessKinds(f *File) []*Name { // Determine kinds for names we already know about, // like #defines or 'struct foo', before bothering with gcc. var names, needType []*Name + optional := map[*Name]bool{} for _, key := range nameKeys(f.Name) { n := f.Name[key] // If we've already found this name as a #define @@ -279,6 +280,14 @@ func (p *Package) guessKinds(f *File) []*Name { continue } + if goos == "darwin" && strings.HasSuffix(n.C, "Ref") { + // For FooRef, find out if FooGetTypeID exists. + s := n.C[:len(n.C)-3] + "GetTypeID" + n := &Name{Go: s, C: s} + names = append(names, n) + optional[n] = true + } + // Otherwise, we'll need to find out from gcc. names = append(names, n) } @@ -425,6 +434,11 @@ func (p *Package) guessKinds(f *File) []*Name { for i, n := range names { switch sniff[i] { default: + if sniff[i]¬Declared != 0 && optional[n] { + // Ignore optional undeclared identifiers. + // Don't report an error, and skip adding n to the needType array. + continue + } error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go)) case notStrLiteral | notType: n.Kind = "iconst" @@ -437,6 +451,7 @@ func (p *Package) guessKinds(f *File) []*Name { case notIntConst | notNumConst | notStrLiteral | notType: n.Kind = "not-type" } + needType = append(needType, n) } if nerrors > 0 { // Check if compiling the preamble by itself causes any errors, @@ -450,7 +465,6 @@ func (p *Package) guessKinds(f *File) []*Name { fatalf("unresolved names") } - needType = append(needType, names...) return needType } @@ -566,6 +580,11 @@ func (p *Package) loadDWARF(f *File, names []*Name) { var conv typeConv conv.Init(p.PtrSize, p.IntSize) for i, n := range names { + if strings.HasSuffix(n.Go, "GetTypeID") && types[i].String() == "func() CFTypeID" { + conv.getTypeIDs[n.Go[:len(n.Go)-9]] = true + } + } + for i, n := range names { if types[i] == nil { continue } @@ -1737,6 +1756,9 @@ type typeConv struct { // Keys of ptrs in insertion order (deterministic worklist) ptrKeys []dwarf.Type + // Type names X for which there exists an XGetTypeID function with type func() CFTypeID. + getTypeIDs map[string]bool + // Predeclared types. bool ast.Expr byte ast.Expr // denotes padding @@ -1766,6 +1788,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) { c.intSize = intSize c.m = make(map[dwarf.Type]*Type) c.ptrs = make(map[dwarf.Type][]*Type) + c.getTypeIDs = make(map[string]bool) c.bool = c.Ident("bool") c.byte = c.Ident("byte") c.int8 = c.Ident("int8") @@ -2152,7 +2175,7 @@ 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) { + if c.badPointerTypedef(dt) { // Treat this typedef as a uintptr. s := *sub s.Go = c.uintptr @@ -2318,7 +2341,7 @@ func (c *typeConv) FuncArg(dtype dwarf.Type, pos token.Pos) *Type { } // ...or the typedef is one in which we expect bad pointers. // It will be a uintptr instead of *X. - if badPointerTypedef(dt) { + if c.badPointerTypedef(dt) { break } @@ -2666,23 +2689,43 @@ func fieldPrefix(fld []*ast.Field) string { // 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(dt *dwarf.TypedefType) bool { - if badCFType(dt) { +func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool { + if c.badCFType(dt) { return true } - if badJNI(dt) { + if c.badJNI(dt) { return true } return false } -func badCFType(dt *dwarf.TypedefType) bool { +func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool { // The real bad types are CFNumberRef and CFDateRef. // 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. + // We return true for the other *Ref types just so casting between them is easier. + // We identify the correct set of types as those ending in Ref and for which + // there exists a corresponding GetTypeID function. // See comment below for details about the bad pointers. - return goos == "darwin" && strings.HasPrefix(dt.Name, "CF") && strings.HasSuffix(dt.Name, "Ref") + if goos != "darwin" { + return false + } + s := dt.Name + if !strings.HasSuffix(s, "Ref") { + return false + } + s = s[:len(s)-3] + if s == "CFType" { + return true + } + if c.getTypeIDs[s] { + return true + } + if i := strings.Index(s, "Mutable"); i >= 0 && c.getTypeIDs[s[:i]+s[i+7:]] { + // Mutable and immutable variants share a type ID. + return true + } + return false } // Comment from Darwin's CFInternal.h @@ -2720,7 +2763,7 @@ enum { }; */ -func badJNI(dt *dwarf.TypedefType) bool { +func (c *typeConv) badJNI(dt *dwarf.TypedefType) bool { // In Dalvik and ART, the jobject type in the JNI interface of the JVM has the // property that it is sometimes (always?) a small integer instead of a real pointer. // Note: although only the android JVMs are bad in this respect, we declare the JNI types |