From 48caf474854c33eb2a345b4cfa3e6b048e84dac5 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Tue, 29 Sep 2026 22:47:28 +0800 Subject: [PATCH] cl compileFuncOrMethod: skip template method --- cl/_testcpp/template_class/in.h | 11 +++++++++++ cl/_testcpp/template_class/out.go | 5 +++++ cl/class.go | 6 +++--- cl/compile.go | 2 +- cl/ctx.go | 28 +++++++++++++++++----------- cl/func.go | 20 +++++++++++++------- cl/vtable.go | 6 +++--- clang/mangling_withprefix.go | 3 +++ 8 files changed, 56 insertions(+), 25 deletions(-) create mode 100644 cl/_testcpp/template_class/in.h create mode 100644 cl/_testcpp/template_class/out.go diff --git a/cl/_testcpp/template_class/in.h b/cl/_testcpp/template_class/in.h new file mode 100644 index 00000000..77b1cc05 --- /dev/null +++ b/cl/_testcpp/template_class/in.h @@ -0,0 +1,11 @@ +template +class Foo { +private: + T value; + +public: + Foo(T val) : value(val) {} + ~Foo() {} + + void g(T val) {} +}; diff --git a/cl/_testcpp/template_class/out.go b/cl/_testcpp/template_class/out.go new file mode 100644 index 00000000..f06c291d --- /dev/null +++ b/cl/_testcpp/template_class/out.go @@ -0,0 +1,5 @@ +package foo + +type Foo[T any] struct { + value T +} diff --git a/cl/class.go b/cl/class.go index 9cc91bb4..86f8402f 100644 --- a/cl/class.go +++ b/cl/class.go @@ -449,11 +449,11 @@ func baseClass(ctx *pkgCtx, decl clang.Cursor) *types.TypeName { } func loadOutsideMethod(ctx *pkgCtx, outsideDecl clang.Cursor) { - manglingName := clang.Mangling(outsideDecl) - if m, ok := ctx.funcs[manglingName]; ok { + fnUSR := funcUSR(outsideDecl) + if m, ok := ctx.fns[fnUSR]; ok { m.decl = outsideDecl } else { - log.Panicln("method undeclared -", clang.DisplayName(outsideDecl)) + log.Panicln("method undeclared -", funcDisplayName(outsideDecl)) } } diff --git a/cl/compile.go b/cl/compile.go index b7fa0d53..9fe2ff28 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -222,7 +222,7 @@ func NewPackage(pkgPath, pkgName string, files []Source, conf *Config) (ret Pack nsIgnores: conf.NSIgnore, typeIgnores: conf.TypeIgnore, rename: rename, classes: conf.Class, nonClasses: conf.NonClass, typdecls: typdecls, pkgOf: conf.PackageOf, nameLookup: nameLookup, pubLookup: conf.PubFileLookup, - fileBases: make(map[clang.File]int), funcs: make(map[string]*funcObj), + fileBases: make(map[clang.File]int), fns: make(map[string]*funcObj), macroVals: make(map[string]any), types: make(map[string]typeObj), lastSeen: make(map[string]none), impPkgs: make(map[string]none), } diff --git a/cl/ctx.go b/cl/ctx.go index c87a3512..49cce108 100644 --- a/cl/ctx.go +++ b/cl/ctx.go @@ -137,7 +137,7 @@ type pkgCtx struct { fileBases map[clang.File]int // clang.File => base macroVals map[string]any // macroName => value - funcs map[string]*funcObj // manglingName => func object + fns map[string]*funcObj // fnUSR => func object types map[string]typeObj // c/c++ fullName => type name object (include external types) typdecls map[string]typDecl // c/c++ fullName => type declaration object (only local types) impPkgs map[string]none // imported package path set @@ -469,8 +469,7 @@ type funcObj struct { decl clang.Cursor // AST object overloads *overloads - manglingName string // c/c++ mangling name - isOperator bool + isOperator bool } // order returns the order of the object in the overloads list. @@ -549,12 +548,12 @@ func (p *scopeCtx) addTemplate(_ *pkgCtx, name string, decl clang.Cursor, isClas } func (p *scopeCtx) addFunc(ctx *pkgCtx, name string, decl clang.Cursor, isOp bool) (*funcObj, bool) { + fnUSR := funcUSR(decl) if debugCompileDecl { - log.Println("==> addFunc", name, clang.String(decl.Type())) + log.Println("==> addFunc", funcDisplayName(decl), "- USR:", fnUSR) } - manglingName := clang.Mangling(decl) - if fn, ok := ctx.funcs[manglingName]; ok { // re-declared + if fn, ok := ctx.fns[fnUSR]; ok { // re-declared if decl.IsFunctionInlined() != 0 { fn.decl = decl // use the latest inline decl } @@ -562,10 +561,9 @@ func (p *scopeCtx) addFunc(ctx *pkgCtx, name string, decl clang.Cursor, isOp boo } obj := &funcObj{ - name: name, - decl: decl, - manglingName: manglingName, - isOperator: isOp, + name: name, + decl: decl, + isOperator: isOp, } ovs, ok := p.overloads[name] if ok { @@ -575,7 +573,7 @@ func (p *scopeCtx) addFunc(ctx *pkgCtx, name string, decl clang.Cursor, isOp boo p.overloads[name] = ovs } obj.overloads = ovs - ctx.funcs[manglingName] = obj + ctx.fns[fnUSR] = obj return obj, true } @@ -586,6 +584,14 @@ func (p *scopeCtx) reorder() { } } +func funcUSR(decl clang.Cursor) string { + return clang.GoStringAndDispose(decl.USR()) +} + +func funcDisplayName(decl clang.Cursor) string { + return clang.DisplayName(decl) +} + /* func substObj(pkg *types.Package, scope *types.Scope, origName string, real types.Object) { old := scope.Insert(gogen.NewSubst(0, pkg, origName, real)) diff --git a/cl/func.go b/cl/func.go index 08d973c8..2bf7f796 100644 --- a/cl/func.go +++ b/cl/func.go @@ -68,15 +68,21 @@ func compileFuncOrMethod(ctx *pkgCtx, obj *funcObj, this *classCtx) { fn := obj.decl origName := obj.name isOp := obj.isOperator - deleted := fn.CXXMethodIsDeleted() if debugCompileDecl { fnType := clang.String(fn.Type()) - log.Println("func", origName, "-", fnType, "- isOp:", isOp, "deleted:", deleted) + log.Println("func", origName, "-", fnType, "- isOp:", isOp) } + if isOp { return // TODO(xsw): support operator } + manglingName := clang.Mangling(fn) + if manglingName == "" { + log.Println("func skipped: no mangling name for", origName) + return + } + pkg := ctx.pkg pkgTypes := pkg.Types @@ -91,7 +97,6 @@ func compileFuncOrMethod(ctx *pkgCtx, obj *funcObj, this *classCtx) { return } - manglingName := clang.Mangling(fn) if fn.IsFunctionInlined() != 0 { if ctx.cflags == "" { if debugCompileDecl { @@ -270,19 +275,20 @@ func newParam(ctx *pkgCtx, pkg *types.Package, decl clang.Cursor, i c.Int, feats } typ := toTypeEx(ctx, pkg, declTyp, flagIsParam, feats, scope) if declName != "" { - avoidKeyword(&declName) + declName = avoidKeyword(declName) } else { declName = "_llcppg_param" + strconv.Itoa(int(i)+1) } return types.NewParam(goNodePos(ctx, decl), pkg, declName, typ) } -func avoidKeyword(name *string) { - switch *name { +func avoidKeyword(name string) string { + switch name { case "map", "type", "range", "chan", "var", "func", "go", "select", "defer", "package", "import", "interface", "fallthrough": - *name += "_" + return name + "_" } + return name } // ----------------------------------------------------------------------------- diff --git a/cl/vtable.go b/cl/vtable.go index f1c20851..c382103d 100644 --- a/cl/vtable.go +++ b/cl/vtable.go @@ -330,11 +330,11 @@ func overriddenRoots(m clang.Cursor) []clang.Cursor { } func vtableMethodName(ctx *pkgCtx, m clang.Cursor) string { - manglingName := clang.Mangling(m) - if fn, ok := ctx.funcs[manglingName]; ok { + fnUSR := funcUSR(m) + if fn, ok := ctx.fns[fnUSR]; ok { return ctx.funcName(fn.name, fn.order(), "", "", false, true) } - panic("vtableMethodName: method not found - " + manglingName) + panic("vtableMethodName: method not found - " + funcDisplayName(m)) } // placeholderSlotName returns the field name of an anonymous (reserved) slot at diff --git a/clang/mangling_withprefix.go b/clang/mangling_withprefix.go index 69aa2a91..247f22d8 100644 --- a/clang/mangling_withprefix.go +++ b/clang/mangling_withprefix.go @@ -31,6 +31,9 @@ func Mangling(fn Cursor) string { m := fn.Mangling() manglingName := c.GoString(m.CStr()) m.Dispose() + if manglingName == "" { + return "" + } return manglingName[1:] }