func inferCompatible(t1, t2 *cc.Type) bool { t1 = t1.Def() t2 = t2.Def() if isNumericCType(t1) && isNumericCType(t2) { return true } if t1.Kind == cc.Ptr && t1.Base.Kind == cc.Func { t1 = t1.Base } if t2.Kind == cc.Ptr && t2.Base.Kind == cc.Func { t2 = t2.Base } if sameType(t1, t2) { return true } if t1.Kind > t2.Kind { t1, t2 = t2, t1 } if t1.Kind == cc.Ptr && t2.Kind == cc.Array && (t1.Base.Is(cc.Void) || sameType(t1.Base, t2.Base)) { return true } if t1.Kind == cc.Ptr && t2.Kind == cc.Ptr && (t1.Base.Is(cc.Void) || t2.Base.Is(cc.Void)) { return true } return false }
func zeroFor(targ *cc.Type) *cc.Expr { if targ != nil { k := targ.Def().Kind switch k { case c2go.String: return &cc.Expr{Op: cc.String, Texts: []string{`""`}} case c2go.Slice, cc.Ptr: return &cc.Expr{Op: cc.Name, Text: "nil"} case cc.Struct, cc.Array: return &cc.Expr{Op: cc.CastInit, Type: targ, Init: &cc.Init{}} case c2go.Bool: return &cc.Expr{Op: cc.Name, Text: "false"} } if c2go.Int8 <= k && k <= c2go.Float64 { return &cc.Expr{Op: cc.Number, Text: "0"} } return &cc.Expr{Op: cc.Number, Text: "0 /*" + targ.String() + "*/"} } return &cc.Expr{Op: cc.Number, Text: "0 /*untyped*/"} }
func sameType(t, u *cc.Type) bool { t = t.Def() u = u.Def() if t == u { return true } if t == nil || u == nil { return false } if t.Kind != u.Kind { return false } if t.Name != "" || u.Name != "" { return t.Name == u.Name } if !sameType(t.Base, u.Base) || len(t.Decls) != len(u.Decls) { return false } for i, td := range t.Decls { ud := u.Decls[i] if !sameType(td.Type, ud.Type) || t.Kind == cc.Struct && td.Name != ud.Name { return false } } return true }
func (p *Printer) printType(t *cc.Type) { if t == nil { p.Print("<nil type>") return } // Shouldn't happen but handle in case it does. p.Print(t.Comments.Before) defer p.Print(t.Comments.Suffix, t.Comments.After) if t == cc.BoolType { p.Print("bool") return } if typemap[t.Kind] != "" { p.Print(typemap[t.Kind]) return } switch t.Kind { default: p.Print("C.", t.String()) // hope for the best case Slice: p.Print("[]", t.Base) case String: p.Print("string") case cc.Struct: if len(t.Decls) == 0 { p.Print("struct{}") break } p.Print("struct {", Indent) p.printStructBody(t) p.Print(Unindent, Newline, "}") case cc.Enum: if t.Tag != "" { p.Print(t.Tag) } else { p.Print("int") } case cc.TypedefType: if t.Base != nil && typemap[t.Base.Kind] != "" && strings.ToLower(t.Name) == t.Name { p.Print(typemap[t.Base.Kind]) return } if t.TypeDecl != nil && t.TypeDecl.GoPackage != "" && p.Package != "" && t.TypeDecl.GoPackage != p.Package { p.Print(path.Base(t.TypeDecl.GoPackage) + "." + t.Name) break } p.Print(t.Name) case cc.Ptr: if t.Base.Is(cc.Func) { p.Print(t.Base) return } if t.Base.Is(cc.Void) { p.Print("*[0]byte") return } p.Print("*", t.Base) case cc.Func: p.Print("func(") for i, arg := range t.Decls { if i > 0 { p.Print(", ") } if arg.Name == "..." { p.Print("...interface{}") continue } if arg.Name == "" && arg.Type.Is(cc.Void) { continue } p.Print(arg.Type) } p.Print(")") if !t.Base.Is(cc.Void) { p.Print(" ", t.Base) } case cc.Array: if t.Width == nil { p.Print("[XXX]", t.Base) return } p.Print("[", t.Width, "]", t.Base) } }
func (p *Printer) printInit(typ *cc.Type, x *cc.Init) { p.Print(x.Comments.Before) defer p.Print(x.Comments.Suffix, x.Comments.After) if len(x.Prefix) > 0 { for _, pre := range x.Prefix { p.Print(pre) } } if x.Expr != nil { if x.Expr.Op == cc.Number && (typ.Is(cc.Ptr) || typ.Is(Slice)) { p.Print("nil") return } p.printExpr(x.Expr, precComma) return } nl := len(x.Braced) > 0 && x.Braced[0].Span.Start.Line != x.Braced[len(x.Braced)-1].Span.End.Line if typ != nil { p.printType(typ) } p.Print("{") if nl { p.Print(Indent) } warned := false for i, y := range x.Braced { if nl { p.Print(Newline) } else if i > 0 { p.Print(" ") } var subtyp *cc.Type if typ != nil { if typ.Is(cc.Struct) && i < len(typ.Def().Decls) && len(y.Prefix) == 0 { subtyp = typ.Def().Decls[i].Type } else if typ.Is(cc.Struct) && len(y.Prefix) == 1 && y.Prefix[0].XDecl != nil { subtyp = y.Prefix[0].XDecl.Type } else if typ.Is(cc.Array) || typ.Is(Slice) { subtyp = typ.Def().Base } else if !warned { warned = true fprintf(x.Span, "too many fields in braced initializer of %s", GoString(typ)) } } p.printInit(subtyp, y) p.Print(",") } if typ != nil && typ.Is(cc.Struct) && len(x.Braced) > 0 && len(x.Braced[0].Prefix) == 0 && len(x.Braced) < len(typ.Def().Decls) { for i := len(x.Braced); i < len(typ.Def().Decls); i++ { subtyp := typ.Def().Decls[i].Type if subtyp.Is(cc.Ptr) || subtyp.Is(Slice) { p.Print(" nil,") } else if subtyp.Is(cc.Array) { p.Print(" ", subtyp, "{},") } else { p.Print(" 0,") } } } if nl { p.Print(Unindent, Newline) } p.Print("}") }
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 } }