From 377ab9312fed117d2ecafc017b66678625f72085 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Wed, 16 Sep 2026 07:49:52 +0800 Subject: [PATCH] cl: overloads.reorder --- cl/_testmockcpp/overload_fn/in.h | 2 ++ cl/_testmockcpp/overload_fn/out.go | 14 +++++++++ cl/class.go | 15 ++++----- cl/compile.go | 1 + cl/ctx.go | 50 +++++++++++++++++++++++++++--- cl/func.go | 12 +++---- cl/type_and_var.go | 7 +++++ 7 files changed, 83 insertions(+), 18 deletions(-) create mode 100644 cl/_testmockcpp/overload_fn/in.h create mode 100644 cl/_testmockcpp/overload_fn/out.go diff --git a/cl/_testmockcpp/overload_fn/in.h b/cl/_testmockcpp/overload_fn/in.h new file mode 100644 index 00000000..05789ce7 --- /dev/null +++ b/cl/_testmockcpp/overload_fn/in.h @@ -0,0 +1,2 @@ +unsigned f(int a); +void f(); diff --git a/cl/_testmockcpp/overload_fn/out.go b/cl/_testmockcpp/overload_fn/out.go new file mode 100644 index 00000000..e684bc04 --- /dev/null +++ b/cl/_testmockcpp/overload_fn/out.go @@ -0,0 +1,14 @@ +package foo + +import ( + "github.com/goplus/lib/c" + _ "unsafe" +) + +const XGoPackage = true + +//go:linkname F__1 C._Z1fi +func F__1(a c.Int) c.Uint + +//go:linkname F__0 C._Z1fv +func F__0() diff --git a/cl/class.go b/cl/class.go index e8df6a13..6b175d1f 100644 --- a/cl/class.go +++ b/cl/class.go @@ -47,19 +47,20 @@ func compileClass(ctx *pkgCtx, scope *classCtx, cls clang.Cursor) { } pkg := ctx.pkg pkgTypes := pkg.Types - clsName, rewritten := ctx.getPubName(origName) + clsName, rewritten := ctx.getPubName(origName, -1) typDecl := pkg.NewTypeDefs().NewType(clsName, goNode(ctx, cls)) typStruc := types.NewStruct(scope.fields, nil) typNamed := typDecl.InitType(pkg, typStruc) if rewritten { - scope := pkgTypes.Scope() - substObj(pkgTypes, scope, origName, typNamed.Obj()) + substObj(pkgTypes, pkgTypes.Scope(), origName, typNamed.Obj()) } + scope.reorder() for _, method := range scope.publicMethods { - if method.outsideDecl.Kind != 0 { - compileFuncOrMethod(ctx, method.outsideDecl, typNamed) + obj := method.obj + if decl := method.outsideDecl; decl.Kind != 0 { + compileFuncOrMethod(ctx, decl, obj, typNamed) } else { - compileFuncOrMethod(ctx, method.obj.decl, typNamed) + compileFuncOrMethod(ctx, obj.decl, obj, typNamed) } } } @@ -97,7 +98,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, cls *classCtx, decl clang. fldType := toType(ctx, pkg, decl.Type(), flagIsStructField) fldName := origName if cls.inPublic { - fldName, _ = ctx.getPubName(origName) + fldName, _ = ctx.getPubName(origName, -1) } fld := types.NewField(goNodePos(ctx, decl), pkg, fldName, fldType, false) cls.fields = append(cls.fields, fld) diff --git a/cl/compile.go b/cl/compile.go index ab41f767..523314d2 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -144,6 +144,7 @@ func loadFiles(ctx *pkgCtx) { loadDecl(ctx, scope, decl) return clang.Continue }) + scope.reorder() ctx.compile() } diff --git a/cl/ctx.go b/cl/ctx.go index 08bf6977..e3641d0f 100644 --- a/cl/ctx.go +++ b/cl/ctx.go @@ -20,6 +20,8 @@ import ( "go/ast" "go/token" "log" + "sort" + "strconv" "github.com/goplus/gogen" "github.com/goplus/lib/c" @@ -137,8 +139,11 @@ func (p *pkgCtx) compile() { } } -func (p *pkgCtx) getPubName(fnName string) (pubName string, rewritten bool) { +func (p *pkgCtx) getPubName(fnName string, order int) (pubName string, rewritten bool) { pubName = cPubName(fnName) + if order >= 0 { + return pubName + "__" + strconv.FormatInt(int64(order), 36), true + } rewritten = fnName != pubName return } @@ -159,15 +164,47 @@ type overloads struct { items []*object } +func (p *overloads) reorder() { + items := p.items + if len(items) > 1 { + sort.SliceStable(items, func(i, j int) bool { + a, b := items[i].decl, items[j].decl + na, nb := a.NumArguments(), b.NumArguments() + if na != nb { + return na < nb + } + for k := range c.Uint(na) { + ta, tb := a.Argument(k).Type(), b.Argument(k).Type() + if ret := cmpType(ta, tb); ret != 0 { + return ret < 0 + } + } + return false + }) + } +} + type object struct { name string decl clang.Cursor overloads *overloads - idx int // index in overloads.items +} + +// order returns the order of the object in the overloads list. +// -1 means no order (only one overload, or not found). +func (p *object) order() int { + items := p.overloads.items + if len(items) > 1 { + for i, obj := range items { + if obj == p { + return i + } + } + } + return -1 } type scopeCtx struct { - ns string overloads map[string]*overloads // name => overload items } @@ -179,7 +216,6 @@ func (p *scopeCtx) addObject(decl clang.Cursor) *object { } ovs, ok := p.overloads[name] if ok { - obj.idx = len(ovs.items) ovs.items = append(ovs.items, obj) } else { ovs = &overloads{items: []*object{obj}} @@ -189,4 +225,10 @@ func (p *scopeCtx) addObject(decl clang.Cursor) *object { return obj } +func (p *scopeCtx) reorder() { + for _, o := range p.overloads { + o.reorder() + } +} + // ----------------------------------------------------------------------------- diff --git a/cl/func.go b/cl/func.go index f4c947eb..f965a985 100644 --- a/cl/func.go +++ b/cl/func.go @@ -32,14 +32,13 @@ import ( func loadGlobalFunc(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor) { obj := scope.addObject(decl) ctx.compiles = append(ctx.compiles, func(ctx *pkgCtx) { - _ = obj - compileFuncOrMethod(ctx, decl, nil) + compileFuncOrMethod(ctx, decl, obj, nil) }) } -func compileFuncOrMethod(ctx *pkgCtx, fn clang.Cursor, typNamed *types.Named) { +func compileFuncOrMethod(ctx *pkgCtx, fn clang.Cursor, obj *object, typNamed *types.Named) { manglingName := clang.Mangling(fn) - origName := clang.String(fn) + origName := obj.name if fn.IsFunctionInlined() != 0 { if ctx.cflags == "" { if debugCompileDecl { @@ -64,7 +63,7 @@ func compileFuncOrMethod(ctx *pkgCtx, fn clang.Cursor, typNamed *types.Named) { var recv *types.Var var nameInPkg string - var fnName, rewritten = ctx.getPubName(origName) + var fnName, rewritten = ctx.getPubName(origName, obj.order()) if typNamed == nil { nameInPkg = fnName } else { @@ -88,8 +87,7 @@ func compileFuncOrMethod(ctx *pkgCtx, fn clang.Cursor, typNamed *types.Named) { }, }) if rewritten { - scope := pkg.Types.Scope() - substObj(pkg.Types, scope, origName, f) + substObj(pkgTypes, pkgTypes.Scope(), origName, f) } } else { f.SetComments(pkg, &ast.CommentGroup{ diff --git a/cl/type_and_var.go b/cl/type_and_var.go index 0593cc6f..69189fc9 100644 --- a/cl/type_and_var.go +++ b/cl/type_and_var.go @@ -123,6 +123,13 @@ func toFuncResults(ctx *pkgCtx, pkg *types.Package, retType lc.Type) (results *t // ----------------------------------------------------------------------------- +func cmpType(ta, tb lc.Type) int { + // TODO(xsw): c++ overload support + return int(ta.Kind - tb.Kind) +} + +// ----------------------------------------------------------------------------- + func substObj(pkg *types.Package, scope *types.Scope, origName string, real types.Object) { old := scope.Insert(gogen.NewSubst(token.NoPos, pkg, origName, real)) if old != nil {