func toGoType(g *flowGroup, x cc.Syntax, typ *cc.Type, cache map[*cc.Type]*cc.Type) (ret *cc.Type) { if typ == nil { return nil } // Array and func implicitly convert to pointer types, so don't // trust the group they are in - they'll turn into pointers incorrectly. if g != nil && typ.Kind != cc.Array && typ.Kind != cc.Func { if g.goType != nil { return g.goType } defer func() { if ret != nil && ret.Kind <= cc.Enum { panic("bad go type override") } g.goType = ret }() } // Look in cache first. This cuts off recursion for self-referential types. // The cache only contains aggregate types - numeric types are shared // by many expressions in the program and we might want to translate // them differently in different contexts. if cache[typ] != nil { return cache[typ] } var force *cc.Type if d, ok := x.(*cc.Decl); ok { key := declKey(d) force = override[key] } switch typ.Kind { default: panic(fmt.Sprintf("unexpected C type %s", typ)) case c2go.Ideal: return typ case cc.Void: return &cc.Type{Kind: cc.Struct} // struct{} case cc.Char, cc.Uchar, cc.Short, cc.Ushort, cc.Int, cc.Uint, cc.Long, cc.Ulong, cc.Longlong, cc.Ulonglong, cc.Float, cc.Double, cc.Enum: // TODO: Use group. if force != nil { return force } return &cc.Type{Kind: c2goKind[typ.Kind]} case cc.Ptr: t := &cc.Type{Kind: cc.Ptr} cache[typ] = t t.Base = toGoType(nil, nil, typ.Base, cache) if g != nil { if g.goKind != 0 { t.Kind = g.goKind return t } for _, f := range g.syntax { if f.ptrAdd || f.ptrIndex { t.Kind = c2go.Slice } } } if force != nil { if force.Base != nil { return force } if force.Kind == cc.Ptr || force.Kind == c2go.Slice { t.Kind = force.Kind return t } } if typ.Base.Kind == cc.Char { t.Kind = c2go.String t.Base = nil return t } return t case cc.Array: if typ.Base.Def().Kind == cc.Char { return &cc.Type{Kind: c2go.String} } t := &cc.Type{Kind: cc.Array, Width: typ.Width} cache[typ] = t t.Base = toGoType(nil, nil, typ.Base, cache) return t case cc.TypedefType: // If this is a typedef like uchar, translate the base type directly. def := typ.Base if cc.Char <= def.Kind && def.Kind <= cc.Enum { return toGoType(g, x, def, cache) } // Otherwise assume it is a struct or some such, and preserve the name // but translate the base. t := &cc.Type{Kind: cc.TypedefType, Name: typ.Name, TypeDecl: typ.TypeDecl} cache[typ] = t t.Base = toGoType(nil, nil, typ.Base, cache) return t case cc.Func: // A func Type contains Decls, and we don't fork the Decls, so don't fork the Type. // The Decls themselves appear in the group lists, so they'll be handled by rewriteTypes. // The return value has no Decl and needs to be converted. if !typ.Base.Is(cc.Void) { typ.Base = toGoType(nil, nil, typ.Base, cache) } return typ case cc.Struct: // A struct Type contains Decls, and we don't fork the Decls, so don't fork the Type. // The Decls themselves appear in the group lists, so they'll be handled by rewriteTypes. return typ } }