Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cl/_testmockcpp/overload_fn/in.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
unsigned f(int a);
void f();
14 changes: 14 additions & 0 deletions cl/_testmockcpp/overload_fn/out.go
Original file line number Diff line number Diff line change
@@ -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()
15 changes: 8 additions & 7 deletions cl/class.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ func loadFiles(ctx *pkgCtx) {
loadDecl(ctx, scope, decl)
return clang.Continue
})
scope.reorder()
ctx.compile()
}

Expand Down
50 changes: 46 additions & 4 deletions cl/ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import (
"go/ast"
"go/token"
"log"
"sort"
"strconv"

"github.com/goplus/gogen"
"github.com/goplus/lib/c"
Expand Down Expand Up @@ -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
}
Expand All @@ -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
}

Expand All @@ -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}}
Expand All @@ -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()
}
}

// -----------------------------------------------------------------------------
12 changes: 5 additions & 7 deletions cl/func.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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{
Expand Down
7 changes: 7 additions & 0 deletions cl/type_and_var.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading