aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/cmd/cgo/gcc.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/cmd/cgo/gcc.go')
-rw-r--r--libgo/go/cmd/cgo/gcc.go63
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]&notDeclared != 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