diff --git a/cl/_testc/struct/out.go b/cl/_testc/struct/out.go index cf1af50c..bb089db9 100644 --- a/cl/_testc/struct/out.go +++ b/cl/_testc/struct/out.go @@ -4,9 +4,9 @@ import "github.com/goplus/lib/c" type Foo struct { U _llcppg_anon_0 - Shorts FooShorts + Shorts Shorts } -type FooShorts struct { +type Shorts struct { S int16 Us uint16 } diff --git a/cl/_testc/union_basic/out.go b/cl/_testc/union_basic/out.go index 7d2b3cec..884872c6 100644 --- a/cl/_testc/union_basic/out.go +++ b/cl/_testc/union_basic/out.go @@ -30,6 +30,8 @@ type BigFloat struct { } type Empty struct { } +type Opaque struct { +} func (p *Value) XGof_ref_i() *c.Int { return (*c.Int)(unsafe.Pointer(p)) diff --git a/cl/_testc/union_struct/out.go b/cl/_testc/union_struct/out.go index 677a5bf8..ceafb237 100644 --- a/cl/_testc/union_struct/out.go +++ b/cl/_testc/union_struct/out.go @@ -9,9 +9,9 @@ const XGoPackage = true type Foo struct { U _llcppg_anon_0 - Shorts FooShorts + Shorts Shorts } -type FooShorts struct { +type Shorts struct { _xgo_union [1]uint16 } type _llcppg_anon_0 struct { @@ -24,10 +24,10 @@ type _llcppg_anon_1 struct { _xgo_union [1]uint16 } -func (p *FooShorts) XGof_ref_s() *int16 { +func (p *Shorts) XGof_ref_s() *int16 { return (*int16)(unsafe.Pointer(p)) } -func (p *FooShorts) XGof_ref_us() *uint16 { +func (p *Shorts) XGof_ref_us() *uint16 { return (*uint16)(unsafe.Pointer(p)) } func (p *_llcppg_anon_0) XGof_ref_x() *c.Float { diff --git a/cl/_testcpp/enum/out.go b/cl/_testcpp/enum/out.go index c7c2eca5..4f064b83 100644 --- a/cl/_testcpp/enum/out.go +++ b/cl/_testcpp/enum/out.go @@ -19,9 +19,9 @@ const ( type BarColor c.Uint const ( - BarRed BarColor = 0 - BarGreen BarColor = 5 - BarBlue BarColor = 6 + Bar_Red BarColor = 0 + Bar_Green BarColor = 5 + Bar_Blue BarColor = 6 ) type Shape struct { @@ -29,7 +29,7 @@ type Shape struct { type ShapeKind c.Uint const ( - ShapeCircle ShapeKind = 0 - ShapeSquare ShapeKind = 1 - ShapeTriangle ShapeKind = 2 + Shape_Circle ShapeKind = 0 + Shape_Square ShapeKind = 1 + Shape_Triangle ShapeKind = 2 ) diff --git a/cl/_testcpp/struct/in.h b/cl/_testcpp/struct/in.h index e4f47dea..d7b9ed84 100644 --- a/cl/_testcpp/struct/in.h +++ b/cl/_testcpp/struct/in.h @@ -1,4 +1,23 @@ -struct Bar +struct Foo { + struct Shorts { + short s; + unsigned short us; + }; + struct { + float x; + float y; + } u; + struct Shorts shorts; +}; + +struct Bar { + struct { + short s; + unsigned short us; + }; +}; + +struct Baz { int a; public: diff --git a/cl/_testcpp/struct/out.go b/cl/_testcpp/struct/out.go index f7bbf0e6..3581c827 100644 --- a/cl/_testcpp/struct/out.go +++ b/cl/_testcpp/struct/out.go @@ -2,7 +2,26 @@ package foo import "github.com/goplus/lib/c" +type Foo struct { + U _llcppg_anon_0 + Shorts FooShorts +} +type FooShorts struct { + S int16 + Us uint16 +} +type _llcppg_anon_0 struct { + X c.Float + Y c.Float +} type Bar struct { + _llcppg_anon_1 +} +type _llcppg_anon_1 struct { + S int16 + Us uint16 +} +type Baz struct { A c.Int B c.Uint c c.Int diff --git a/cl/class.go b/cl/class.go index 325dc7bb..3764cb1b 100644 --- a/cl/class.go +++ b/cl/class.go @@ -18,7 +18,6 @@ package cl import ( "go/types" - "log" "strconv" "unsafe" @@ -106,9 +105,8 @@ func newTypeParams(ctx *pkgCtx, pkg *types.Package, cls clang.Cursor) (ret []*ty return } -func loadTemplateClass(ctx *pkgCtx, cls clang.Cursor, ns string, parent *scopeCtx) { - origName := nameWithNS(clang.String(cls), ns) - if obj, ok := ctx.addTemplateClass(ctx, origName, cls); ok { +func loadTemplateClass(ctx *pkgCtx, cls clang.Cursor, parent *scopeCtx) { + if obj, ok := ctx.addTemplateClass(ctx, cls); ok { ctx.addCompileUnit(func(ctx *pkgCtx) { compileTemplateClass(ctx, obj, parent) }) @@ -116,89 +114,88 @@ func loadTemplateClass(ctx *pkgCtx, cls clang.Cursor, ns string, parent *scopeCt } func compileTemplateClass(ctx *pkgCtx, obj *templateClass, parent *scopeCtx) { - origName := obj.name + cName := obj.cName cls := obj.decl + order := obj.order() if debugCompileDecl { - log.Println("template class", origName, "order:", obj.order()) + ctx.logf(cls, "template class %s: order - %d", cName, order) } pkg := ctx.pkg pkgTypes := pkg.Types tparams, quietIgnore := newTypeParams(ctx, pkgTypes, cls) - if quietIgnore || obj.order() >= 0 { + if quietIgnore || order >= 0 { if debugQuietIgnore { - ctx.logf(cls, "class %s: unsupported template params, ignored", clang.String(cls)) + ctx.logf(cls, "class %s: unsupported template params, ignored", cName) } return } - var clsName string - var typDecl, ok = ctx.typdecls[origName] + var typDecl, ok = ctx.typdecls[cName] if !ok { if cls.IsCursorDefinition() == 0 || cls.NumTemplateArguments() > 0 { return } - clsName = ctx.typeName(origName, true) - typDecl = newType(ctx, cls, clsName, tagClass) - ctx.typdecls[origName] = typDecl + goName := ctx.typeName(cName, true) + typDecl = newType(ctx, cls, cName, goName) + ctx.typdecls[cName] = typDecl } + if cls.IsCursorDefinition() == 0 { return // declaration only, no definition } - if clsName == "" { - clsName = ctx.typeName(origName, true) - } - initClassType(ctx, typDecl, cls, clsName, tparams, parent) + goName := typDecl.Type().Obj().Name() + initClassType(ctx, typDecl, cls, goName, tparams, parent) } -func loadClass(ctx *pkgCtx, cls clang.Cursor, ns string, kind typeTag, parent *scopeCtx) { - origName := nameWithNS(clang.String(cls), ns) +func loadClass(ctx *pkgCtx, cls clang.Cursor, kind typeTag, parent *scopeCtx) { + cName := cNameOf(cls) if debugCompileDecl { - log.Println(tagStrvals[kind] + origName) + ctx.logf(cls, "%s", tagStrvals[kind]+cName) } if cls.NumTemplateArguments() > 0 { - loadTemplateClass(ctx, cls, ns, parent) + loadTemplateClass(ctx, cls, parent) return } - var clsName string - var typDecl, ok = ctx.typdecls[origName] + var typDecl, ok = ctx.typdecls[cName] if !ok { - clsName = ctx.typeName(origName, true) - typDecl = newType(ctx, cls, clsName, kind) - ctx.typdecls[origName] = typDecl + goName := ctx.typeName(cName, true) + typDecl = newType(ctx, cls, cName, goName) + ctx.typdecls[cName] = typDecl } + if cls.IsCursorDefinition() == 0 { return // declaration only, no definition } - if clsName == "" { - clsName = ctx.typeName(origName, true) - } - initClassType(ctx, typDecl, cls, clsName, nil, parent) + goName := typDecl.Type().Obj().Name() + initClassType(ctx, typDecl, cls, goName, nil, parent) } -func newType(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag) (ret typDecl) { +func newType(ctx *pkgCtx, cls clang.Cursor, cName, goName string) (ret typDecl) { ret.defs = ctx.pkg.NewTypeDefs() - ret.TypeDecl = ret.defs.NewType(clsName, goNode(ctx, cls)) - ctx.addType(kind, cls, ret.Type()) + ret.TypeDecl = ret.defs.NewType(goName, goNode(ctx, cls)) + if cName != "" { + ctx.addType(cName, cls, ret.Type()) + } return } -func initClassType(ctx *pkgCtx, typDecl typDecl, cls clang.Cursor, clsName string, tparams []*types.TypeParam, parent *scopeCtx) bool { +func initClassType(ctx *pkgCtx, typDecl typDecl, cls clang.Cursor, goName string, tparams []*types.TypeParam, parent *scopeCtx) bool { feats := 0 - initClassTypeEx(ctx, typDecl, cls, clsName, tparams, parent, &feats) + initClassTypeEx(ctx, typDecl, cls, goName, tparams, parent, &feats) if feats&featAllIgnore != 0 { - ctx.ignoref(feats, cls, "class %s: unsupported features, ignored", clang.String(cls)) + ctx.ignoref(feats, cls, "class %s: unsupported features, ignored", goName) typDecl.Delete() return false } return true } -func initClassTypeEx(ctx *pkgCtx, typDecl typDecl, cls clang.Cursor, clsName string, tparams []*types.TypeParam, parent *scopeCtx, feats *int) { +func initClassTypeEx(ctx *pkgCtx, typDecl typDecl, cls clang.Cursor, goName string, tparams []*types.TypeParam, parent *scopeCtx, feats *int) { // Attach the doc at the TypeDefs (GenDecl) level rather than on the // TypeSpec; see the note in loadTypedef for why a spec-level doc renders as // "type// doc" here. @@ -216,7 +213,7 @@ func initClassTypeEx(ctx *pkgCtx, typDecl typDecl, cls clang.Cursor, clsName str pkg := ctx.pkg pkgTypes := pkg.Types clang.VisitChildren(cls, func(decl, parent clang.Cursor) clang.ChildVisitResult { - loadClassMember(ctx, pkgTypes, this, clsName, decl, feats) + loadClassMember(ctx, pkgTypes, this, goName, decl, feats) return clang.Continue }) if *feats&featAllIgnore != 0 { @@ -247,10 +244,10 @@ func initClassTypeEx(ctx *pkgCtx, typDecl typDecl, cls clang.Cursor, clsName str }) } -func emitClass(ctx *pkgCtx, cls clang.Cursor, clsName string, kind typeTag, parent *scopeCtx) *types.Named { - typDecl := newType(ctx, cls, clsName, kind) - if !initClassType(ctx, typDecl, cls, clsName, nil, parent) { - ctx.panicf(cls, "unsupported feature, failed to initialize class") +func emitClass(ctx *pkgCtx, cls clang.Cursor, goName string, parent *scopeCtx) *types.Named { + typDecl := newType(ctx, cls, "", goName) + if !initClassType(ctx, typDecl, cls, goName, nil, parent) { + ctx.panicf(cls, "class %s: unsupported feature, failed to initialize class", goName) } return typDecl.Type() } @@ -259,7 +256,7 @@ func isPublic(decl clang.Cursor) bool { return decl.CXXAccessSpecifier() == lc.CXXPublic } -func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName string, decl clang.Cursor, feats *int) { +func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, goName string, decl clang.Cursor, feats *int) { switch decl.Kind { case lc.Cursor_CXXMethod, lc.Cursor_FunctionTemplate, lc.Cursor_Constructor, lc.Cursor_Destructor, lc.Cursor_ConversionFunction: @@ -272,7 +269,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName st default: if decl.CXXMethodIsStatic() != 0 { if isPublic(decl) { - loadGlobalFunc(ctx, &ctx.scopeCtx, decl, clsName) + loadGlobalFunc(ctx, &ctx.scopeCtx, decl) } return } @@ -293,7 +290,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName st if ftd.Kind == lc.Cursor_UnionDecl { fldType = emitUnion(ctx, ftd, ctx.nextAnonName()) } else { - fldType = emitClass(ctx, ftd, ctx.nextAnonName(), ftd.Kind, this.scope()) + fldType = emitClass(ctx, ftd, ctx.nextAnonName(), this.scope()) } anonymous = true } @@ -314,7 +311,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName st // by the enclosing class name (the class name acts like a namespace), // mirroring how a static method is handled above. if isPublic(decl) { - loadVar(ctx, decl, clsName) + loadVar(ctx, decl) } case lc.Cursor_CXXAccessSpecifier, lc.Cursor_FriendDecl, lc.Cursor_UsingDeclaration: @@ -325,7 +322,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName st // emitted as global consts prefixed by the enclosing class name (the // class name acts like a namespace), e.g. Color_Red. if isPublic(decl) { - loadEnum(ctx, decl, clsName) + loadEnum(ctx, decl) } case lc.Cursor_TypedefDecl, lc.Cursor_TypeAliasDecl, lc.Cursor_TypeAliasTemplateDecl: @@ -334,7 +331,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName st // prefixed by the enclosing class name (the class name acts like a // namespace), e.g. Bar_iterator. if isPublic(decl) { - loadTypedef(ctx, decl, clsName, this.scope()) + loadTypedef(ctx, decl, this.scope()) } case lc.Cursor_CXXBaseSpecifier: @@ -351,7 +348,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName st case lc.Cursor_ClassDecl, lc.Cursor_StructDecl: switch { case decl.IsAnonymousRecordDecl() != 0: - hoisted := emitClass(ctx, decl, ctx.nextAnonName(), decl.Kind, this.scope()) + hoisted := emitClass(ctx, decl, ctx.nextAnonName(), this.scope()) fld := types.NewField(goNodePos(ctx, decl), pkg, hoisted.Obj().Name(), hoisted, true) this.fields = append(this.fields, fld) case decl.IsAnonymous() != 0: @@ -365,11 +362,11 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName st // field's type must resolve to a generated Go type. Its own members' // default visibility still follows C++ rules (struct: public, // class: private). - loadClass(ctx, decl, clsName, decl.Kind, this.scope()) + loadClass(ctx, decl, decl.Kind, this.scope()) } case lc.Cursor_ClassTemplate, lc.Cursor_ClassTemplatePartialSpecialization: - loadTemplateClass(ctx, decl, clsName, this.scope()) + loadTemplateClass(ctx, decl, this.scope()) case lc.Cursor_UnionDecl: switch { @@ -383,7 +380,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName st // A named nested union is emitted at package level for the same // reason as a named nested class/struct above: a field may use it // as its type even when declared in a private section. - loadUnion(ctx, decl, clsName) + loadUnion(ctx, decl) } case lc.Cursor_TemplateTypeParameter, lc.Cursor_NonTypeTemplateParameter, @@ -394,7 +391,7 @@ func loadClassMember(ctx *pkgCtx, pkg *types.Package, this *classCtx, clsName st if decl.Kind >= lc.Cursor_FirstAttr && decl.Kind <= lc.Cursor_LastAttr { return // noop } - ctx.panicf(decl, "loadClassMember: unknown kind = %v", decl.Kind) + ctx.panicf(decl, "class %s: unknown child node kind - %v", goName, decl.Kind) } } @@ -496,7 +493,7 @@ func loadOutsideMethod(ctx *pkgCtx, outsideDecl clang.Cursor) { if m, ok := ctx.fns[fnUSR]; ok { m.decl = outsideDecl } else { - ctx.logf(outsideDecl, "[WARN] method undeclared - %s", funcDisplayName(outsideDecl)) + ctx.logf(outsideDecl, "[WARN] method undeclared - %s", cNameOf(outsideDecl)) } } diff --git a/cl/compile.go b/cl/compile.go index e7a6a876..7ed29c29 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -111,8 +111,7 @@ type Config struct { // in the map, it will be renamed to the corresponding Go name. Rename map[string]string - // NSIgnore specifies a list of namespaces (their names have been converted to Go style) - // to be ignored (optional). + // NSIgnore specifies a list of C/C++ namespaces to be ignored (optional). NSIgnore []string // MacroIgnore specifies a list of C/C++ macro names to be ignored (optional). @@ -149,6 +148,10 @@ type Config struct { // generating Go variable names (optional). VarPrefix []string + // NSPrefix specifies the prefix to remove from C/C++ namespace names when generating + // Go package names (optional). + NSPrefix []string + // Class specifies a list of C/C++ typedef names to be treated as classes (optional). Class []string @@ -232,9 +235,9 @@ func NewPackage(pkgPath, pkgName string, files []Source, conf *Config) (ret Pack cflags: conf.CFlags, wrapFileHeader: conf.WrapFileHeader, typeAbbr: conf.TypeAbbr, typeAbbrSuffix: conf.TypeAbbrSuffix, typePrefix: conf.TypePrefix, typeSuffix: conf.TypeSuffix, - fnPrefix: conf.FuncPrefix, enumPrefix: conf.EnumPrefix, - macroPrefix: conf.MacroPrefix, varPrefix: conf.VarPrefix, rename: rename, - nsIgnores: conf.NSIgnore, macroIgnore: conf.MacroIgnore, typeIgnores: conf.TypeIgnore, + fnPrefix: conf.FuncPrefix, enumPrefix: conf.EnumPrefix, rename: rename, + nsPrefix: conf.NSPrefix, macroPrefix: conf.MacroPrefix, varPrefix: conf.VarPrefix, + nsIgnore: conf.NSIgnore, macroIgnore: conf.MacroIgnore, typeIgnores: conf.TypeIgnore, classes: conf.Class, nonClasses: conf.NonClass, typdecls: typdecls, pkgOf: conf.PackageOf, nameLookup: nameLookup, pubLookup: conf.PubFileLookup, fileBases: make(map[clang.File]int), fns: make(map[string]*funcObj), @@ -298,7 +301,7 @@ func loadFiles(ctx *pkgCtx, files []Source, myPkgPath string, goFileOf func(head pkg.SetCurFile(fname, true) } } - loadDecl(ctx, scope, decl, "") + loadDecl(ctx, scope, decl) return clang.Continue }) maps.Copy(lastSeen, ctx.thisSeen) @@ -306,36 +309,36 @@ func loadFiles(ctx *pkgCtx, files []Source, myPkgPath string, goFileOf func(head scope.reorder() } -func loadDecl(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor, ns string) { +func loadDecl(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor) { switch decl.Kind { case lc.Cursor_FunctionDecl: - loadGlobalFunc(ctx, scope, decl, ns) + loadGlobalFunc(ctx, scope, decl) case lc.Cursor_ClassDecl, lc.Cursor_StructDecl: - loadClass(ctx, decl, ns, decl.Kind, nil) + loadClass(ctx, decl, decl.Kind, nil) case lc.Cursor_CXXMethod, lc.Cursor_Constructor, lc.Cursor_Destructor: loadOutsideMethod(ctx, decl) case lc.Cursor_TypedefDecl, lc.Cursor_TypeAliasDecl, lc.Cursor_TypeAliasTemplateDecl: - loadTypedef(ctx, decl, ns, nil) + loadTypedef(ctx, decl, nil) case lc.Cursor_EnumDecl: - loadEnum(ctx, decl, ns) + loadEnum(ctx, decl) case lc.Cursor_MacroDefinition: loadMacro(ctx, decl) case lc.Cursor_InclusionDirective: loadInclude(ctx, decl) case lc.Cursor_Namespace: - loadNamespace(ctx, scope, decl, ns) + loadNamespace(ctx, scope, decl) case lc.Cursor_VarDecl: - loadVar(ctx, decl, ns) + loadVar(ctx, decl) case lc.Cursor_UnionDecl: - loadUnion(ctx, decl, ns) + loadUnion(ctx, decl) case lc.Cursor_LinkageSpec: // extern "C" { ... } - loadLinkageSpec(ctx, scope, decl, ns) + loadLinkageSpec(ctx, scope, decl) case lc.Cursor_MacroExpansion, lc.Cursor_StaticAssert, lc.Cursor_UsingDeclaration: // noop case lc.Cursor_FunctionTemplate: // TODO(xsw): ignore for now case lc.Cursor_ClassTemplate, lc.Cursor_ClassTemplatePartialSpecialization: - loadTemplateClass(ctx, decl, ns, nil) + loadTemplateClass(ctx, decl, nil) case lc.Cursor_UnexposedDecl, lc.Cursor_UnexposedAttr: // noop default: @@ -343,23 +346,23 @@ func loadDecl(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor, ns string) { } } -func loadNamespace(ctx *pkgCtx, scope *scopeCtx, namespace clang.Cursor, ns string) { - ns = ctx.nsName(ns, clang.String(namespace)) - if ctx.isNSIgnored(ns) { +func loadNamespace(ctx *pkgCtx, scope *scopeCtx, namespace clang.Cursor) { + cName := cNameOf(namespace) + if ctx.isNSIgnored(cName) { if debugCompileDecl { - log.Println("namespace", ns, "- ignored") + ctx.logf(namespace, "namespace %s - ignored", cName) } return } clang.VisitChildren(namespace, func(decl, parent clang.Cursor) clang.ChildVisitResult { - loadDecl(ctx, scope, decl, ns) + loadDecl(ctx, scope, decl) return clang.Continue }) } -func loadLinkageSpec(ctx *pkgCtx, scope *scopeCtx, linkage clang.Cursor, ns string) { +func loadLinkageSpec(ctx *pkgCtx, scope *scopeCtx, linkage clang.Cursor) { clang.VisitChildren(linkage, func(decl, parent clang.Cursor) clang.ChildVisitResult { - loadDecl(ctx, scope, decl, ns) + loadDecl(ctx, scope, decl) return clang.Continue }) } diff --git a/cl/ctx.go b/cl/ctx.go index ad0c50ef..da2815e7 100644 --- a/cl/ctx.go +++ b/cl/ctx.go @@ -23,7 +23,6 @@ import ( "go/types" "log" "sort" - "strings" "github.com/goplus/gogen" "github.com/goplus/lib/c" @@ -120,6 +119,7 @@ type pkgCtx struct { typeAbbrSuffix []string + nsPrefix []string fnPrefix []string varPrefix []string enumPrefix []string @@ -132,7 +132,7 @@ type pkgCtx struct { rename map[string]string // C/C++ name => Go name typeIgnores []string // C/C++ type names to be ignored macroIgnore []string // C/C++ macro names to be ignored - nsIgnores []string // Go style namespace names to be ignored + nsIgnore []string // C/C++ namespace names to be ignored nameLookup func(manglingName string) (archivePath string, ok bool) pubLookup func(pkgPath string) (pubFile string, ok bool) @@ -235,34 +235,19 @@ func (p *pkgCtx) basicTyp(kind basicKind) types.Type { } func (p *pkgCtx) aliasTypeName(cName, goName string) { - cName = trimTypeTag(cName) if _, ok := p.rename[cName]; !ok { // insert alias name if not already present p.rename[cName] = goName } } -func (p *pkgCtx) addType(kind typeTag, decl clang.Cursor, typNamed *types.Named) { - var cName string - if decl.Kind == lc.Cursor_ClassTemplate { // TODO(xsw): check if this is correct - cName = clang.String(decl) - } else { - cName = clang.String(decl.Type()) - } +func (p *pkgCtx) addType(cName string, decl clang.Cursor, typNamed *types.Named) { typObj := typeObj{typNamed.Obj(), 0} p.types[cName] = typObj p.aliasTypeName(cName, typObj.Name()) if debugCompileDecl { - log.Println("==> addType", cName, typObj.Name()) - } - - // name of typedef may be "m" instead of " m" - tag := tagStrvals[kind] - if strings.HasPrefix(cName, tag) { - p.types[cName[len(tag):]] = typObj - } else { - p.types[tag+cName] = typObj + p.logf(decl, "==> addType %s: %v", cName, typNamed) } } @@ -295,13 +280,13 @@ func (p *pkgCtx) isMacroIgnored(cName string) bool { } func (p *pkgCtx) isNSIgnored(cName string) bool { - return contains(cName, p.nsIgnores) + return contains(cName, p.nsIgnore) } // ----------------------------------------------------------------------------- type templateClass struct { - name string // go name + cName string // c/c++ full name decl clang.Cursor // AST object overloads *overloads } @@ -321,7 +306,7 @@ func (p *templateClass) order() int { } type funcObj struct { - name string // go name + cName string // c/c++ full name decl clang.Cursor // AST object overloads *overloads @@ -422,30 +407,31 @@ func (p *scopeCtx) lookupType(name string) (types.Type, bool) { return nil, false } -func (p *scopeCtx) addTemplateClass(_ *pkgCtx, name string, decl clang.Cursor) (*templateClass, bool) { +func (p *scopeCtx) addTemplateClass(ctx *pkgCtx, decl clang.Cursor) (*templateClass, bool) { + cName := cNameOf(decl) if debugCompileDecl { - log.Println("==> addTemplateClass", name, "-", clang.DisplayName(decl)) + ctx.logf(decl, "==> addTemplateClass %s", cName) } // TODO(xsw): check if the class is already added obj := &templateClass{ - name: name, - decl: decl, + cName: cName, + decl: decl, } - ovs, ok := p.overloads[name] + ovs, ok := p.overloads[cName] if ok { ovs.classes = append(ovs.classes, obj) } else { ovs = &overloads{classes: []*templateClass{obj}} - p.overloads[name] = ovs + p.overloads[cName] = ovs } obj.overloads = ovs return obj, true } -func (p *scopeCtx) addFunc(ctx *pkgCtx, name string, decl clang.Cursor, isOp bool) (*funcObj, bool) { +func (p *scopeCtx) addFunc(ctx *pkgCtx, cName string, decl clang.Cursor, isOp bool) (*funcObj, bool) { fnUSR := funcUSR(decl) if debugCompileDecl { - log.Println("==> addFunc", funcDisplayName(decl), "- USR:", fnUSR) + ctx.logf(decl, "==> addFunc %s - USR: %s", cName, fnUSR) } if fn, ok := ctx.fns[fnUSR]; ok { // re-declared @@ -456,16 +442,16 @@ func (p *scopeCtx) addFunc(ctx *pkgCtx, name string, decl clang.Cursor, isOp boo } obj := &funcObj{ - name: name, + cName: cName, decl: decl, isOperator: isOp, } - ovs, ok := p.overloads[name] + ovs, ok := p.overloads[cName] if ok { ovs.fns = append(ovs.fns, obj) } else { ovs = &overloads{fns: []*funcObj{obj}} - p.overloads[name] = ovs + p.overloads[cName] = ovs } obj.overloads = ovs ctx.fns[fnUSR] = obj diff --git a/cl/enum.go b/cl/enum.go index 488e7f02..b5c88008 100644 --- a/cl/enum.go +++ b/cl/enum.go @@ -18,7 +18,6 @@ package cl import ( "go/types" - "log" "github.com/goplus/gogen" "github.com/goplus/llcppg/clang" @@ -38,17 +37,19 @@ import ( // affects naming: ns carries the enclosing namespace/class prefix (e.g. "bar_" // or "Shape_"), so a constant Red becomes bar_Red / Shape_Red and then goes // through getPubName for the final Go name. -func loadEnum(ctx *pkgCtx, decl clang.Cursor, ns string) { - name := clang.String(decl) - origName := nameWithNS(name, ns) - anonymous := decl.IsAnonymous() != 0 +func loadEnum(ctx *pkgCtx, decl clang.Cursor) { + ns := cNS(decl) + hasName := decl.IsAnonymous() == 0 scoped := decl.EnumDeclIsScoped() != 0 - definition := decl.IsCursorDefinition() != 0 // TODO(xsw): rename to IsDefinition typ := decl.EnumDeclIntegerType() + + var cName string + if hasName { + cName = cNameWithNS(cBaseName(decl), ns) + } + if debugCompileDecl { - log.Println( - "enum", origName, clang.String(typ), "anonymous:", anonymous, - "scoped:", scoped, "definition:", definition) + ctx.logf(decl, "enum %s - hasName: %v, scoped: %v", cName, hasName, scoped) } pkg := ctx.pkg @@ -57,25 +58,25 @@ func loadEnum(ctx *pkgCtx, decl clang.Cursor, ns string) { var ok bool var typDecl typDecl var enumType types.Type - if !anonymous { - typDecl, ok = ctx.typdecls[origName] + if hasName { + typDecl, ok = ctx.typdecls[cName] if !ok { - clsName := ctx.typeName(origName, true) - typDecl = newType(ctx, decl, clsName, tagEnum) - ctx.typdecls[origName] = typDecl + goName := ctx.typeName(cName, true) + typDecl = newType(ctx, decl, cName, goName) + ctx.typdecls[cName] = typDecl feats := 0 underType := toTypeEx(ctx, pkgTypes, typ, flagIsTypeDef, &feats, nil) if feats&featAllIgnore != 0 { - ctx.panicf(decl, "enum %s: unsupported underlying type %s (%d)", name, clang.String(typ), typ.Kind) + ctx.panicf(decl, "enum %s: unsupported underlying type %s (%d)", cName, clang.String(typ), typ.Kind) } typDecl.InitType(pkg, underType) } } - if !definition { + if decl.IsCursorDefinition() == 0 { return // declaration only, no definition } - if !anonymous { + if hasName { if doc := ctx.docCommentGroup(decl); doc != nil { typDecl.defs.SetComments(doc) } @@ -85,13 +86,12 @@ func loadEnum(ctx *pkgCtx, decl clang.Cursor, ns string) { defs := pkg.NewConstDefs(pkgTypes.Scope()) // For an anonymous enum there is no type to carry the doc, so attach the // enum's doc comment to the generated const block instead. - if anonymous { + if !hasName { if doc := ctx.docCommentGroup(decl); doc != nil { defs.SetComments(doc) } - } - if scoped { - ns = origName + "_" + } else if scoped { + ns = cName } clang.VisitChildren(decl, func(item, parent clang.Cursor) clang.ChildVisitResult { if item.Kind != lc.Cursor_EnumConstantDecl { diff --git a/cl/func.go b/cl/func.go index 44498d09..6703c048 100644 --- a/cl/func.go +++ b/cl/func.go @@ -40,14 +40,14 @@ func isOperator(baseName string) bool { return false } -func loadGlobalFunc(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor, ns string) { +func loadGlobalFunc(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor) { var baseName = clang.String(decl) var name string var isOp = isOperator(baseName) if isOp { name = baseName[len(operatorPrefix):] } else { - name = nameWithNS(baseName, ns) + name = cNameOf(decl) } if obj, ok := scope.addFunc(ctx, name, decl, isOp); ok { ctx.addCompileUnit(func(ctx *pkgCtx) { @@ -65,20 +65,19 @@ func loadGlobalFunc(ctx *pkgCtx, scope *scopeCtx, decl clang.Cursor, ns string) // is non-nil, it is an instance method compiled with a "this" receiver. func compileFuncOrMethod(ctx *pkgCtx, obj *funcObj, this *classCtx) { fn := obj.decl - origName := obj.name + cName := obj.cName isOp := obj.isOperator if debugCompileDecl { fnType := clang.String(fn.Type()) - log.Println("func", origName, "-", fnType, "- isOp:", isOp) + ctx.logf(fn, "func %s: %s - isOp: %v", cName, fnType, isOp) } - if isOp { return // TODO(xsw): support operator } manglingName := clang.Mangling(fn) if manglingName == "" { - ctx.logf(fn, "func %s: no mangled symbol, skipped", clang.String(fn)) + ctx.logf(fn, "func %s: no mangled symbol, skipped", cName) return } @@ -90,18 +89,18 @@ func compileFuncOrMethod(ctx *pkgCtx, obj *funcObj, this *classCtx) { params, variadic := newParams(ctx, pkgTypes, fn, &feats, scope) results := toFuncResults(ctx, pkgTypes, fn.ResultType(), &feats, scope) if feats&featAllIgnore != 0 { - ctx.ignoref(feats, fn, "func %s: function with unsupported features, ignored", clang.String(fn)) + ctx.ignoref(feats, fn, "func %s: function with unsupported features, ignored", cName) return } if fn.IsFunctionInlined() != 0 { if ctx.cflags == "" { - ctx.ignoref(InlineFuncIgnore, fn, "func %s: inline function but no CFlags in config, ignored", clang.String(fn)) + ctx.ignoref(InlineFuncIgnore, fn, "func %s: inline function but no CFlags in config, ignored", cName) return } manglingName = wrapInlineFunc(ctx, manglingName, fn, this) } else if _, ok := ctx.nameLookup(manglingName); !ok { - ctx.logf(fn, "func %s: symbol not found in lib files, skipped", clang.String(fn)) + ctx.logf(fn, "func %s: symbol not found in lib files, skipped", cName) return } @@ -126,13 +125,13 @@ func compileFuncOrMethod(ctx *pkgCtx, obj *funcObj, this *classCtx) { recv = types.NewParam(goNodePos(ctx, fn), pkgTypes, "this", types.NewPointer(typNamed)) typName = typNamed.Obj().Name() } - fnName := ctx.funcName(origName, obj.order(), typName, typCName, this == nil, true) + fnName := ctx.funcName(cName, obj.order(), typName, typCName, this == nil, true) if recv == nil { nameInPkg = fnName } else { if typRecv != nil { if existMember(typRecv, fnName) { - newName := ctx.funcName(origName, obj.order(), "", typCName, true, true) + newName := ctx.funcName(cName, obj.order(), "", typCName, true, true) log.Printf("==> member %s.%s already exists, rename to %s\n", typName, fnName, newName) fnName = newName } diff --git a/cl/import.go b/cl/import.go index 618dcdbc..bc2ba775 100644 --- a/cl/import.go +++ b/cl/import.go @@ -177,7 +177,7 @@ func (p *pkgCtx) importPkg(pkgPath string) *types.Package { case entryType: if e.GoName == "" { - e.GoName = p.typeName(strings.ReplaceAll(e.Name, "::", "_"), true) + e.GoName = p.typeName(e.Name, true) } if o := scope.Lookup(e.GoName); o != nil { if t, ok := o.(*types.TypeName); ok { diff --git a/cl/name.go b/cl/name.go index d6e50bd7..bc97db39 100644 --- a/cl/name.go +++ b/cl/name.go @@ -22,6 +22,7 @@ import ( "strings" "github.com/goplus/llcppg/clang" + lc "github.com/llarhub/clang-c" ) // ----------------------------------------------------------------------------- @@ -36,14 +37,69 @@ func (p *pkgCtx) nextAnonName() string { return name } -// ----------------------------------------------------------------------------- - func funcUSR(decl clang.Cursor) string { return clang.USR(decl) } -func funcDisplayName(decl clang.Cursor) string { - return clang.DisplayName(decl) +// ----------------------------------------------------------------------------- + +func cNameSplit(cName string) (parts []string, hasNS bool) { + for { + pos := strings.IndexAny(cName, "_:") + if pos < 0 { + parts = append(parts, cName) + return + } + parts = append(parts, cName[:pos]) + if cName[pos] == ':' && len(cName) > pos+1 && cName[pos+1] == ':' { + hasNS = true + cName = cName[pos+2:] + } else { + cName = cName[pos+1:] + } + } +} + +func cNameWithNS(name, ns string) string { + if ns == "" { + return name + } + return ns + "::" + name +} + +func cNameOf(decl clang.Cursor) string { + cName := cBaseName(decl) + for { + decl = decl.SemanticParent() + if decl.Kind == lc.Cursor_TranslationUnit { + break + } + cName = cBaseName(decl) + "::" + cName + } + return cName +} + +func cNS(decl clang.Cursor) (ns string) { + for { + decl = decl.SemanticParent() + if decl.Kind == lc.Cursor_TranslationUnit { + return + } + name := cBaseName(decl) + if ns == "" { + ns = name + } else { + ns = name + "::" + ns + } + } +} + +func cBaseName(decl clang.Cursor) string { + return trimTypeTag(clang.String(decl)) +} + +func cTypeName(typ lc.Type) string { + return cNameOf(typ.Declaration()) } // ----------------------------------------------------------------------------- @@ -68,25 +124,35 @@ func (p *pkgCtx) macroName(name string) string { } func (p *pkgCtx) enumvalName(name, ns string) string { - if strings.HasSuffix(ns, "_") { - return p.globalName(ns, p.enumPrefix) + p.cstyleToGo(name, true) + if ns == "" { + return p.globalName(name, p.enumPrefix) + } + ns = p.globalName(ns, p.nsPrefix) + name = p.cstyleToGo(name, false) + if ns != "" { + name = ns + "_" + name + } + if v, ok := p.rename[name]; ok { + return v // special case } - return p.globalName(nameWithNS(name, ns), p.enumPrefix) + return name } -func (p *pkgCtx) typeName(name string, _ bool) string { - if v, ok := p.rename[name]; ok { +func (p *pkgCtx) typeName(cName string, _ bool) string { + if v, ok := p.rename[cName]; ok { return v // special case } - name = rmPrefix(name, p.typePrefix) - name = rmSuffix(name, p.typeSuffix) - return p.cstyleToGo(name, true) + cName = rmPrefix(cName, p.nsPrefix) + cName = rmPrefix(cName, p.typePrefix) + cName = rmSuffix(cName, p.typeSuffix) + return p.cstyleToGo(cName, true) } func (p *pkgCtx) funcName(name string, order int, typName, typCName string, global, _ bool) string { if v, ok := p.rename[name]; ok { return v // special case } + name = rmPrefix(name, p.nsPrefix) if global { name = rmPrefix(name, p.fnPrefix) if typCName != "" { @@ -140,13 +206,14 @@ func (p *pkgCtx) funcName(name string, order int, typName, typCName string, glob func (p *pkgCtx) cstyleToGo(cName string, public bool) string { rename := p.rename - parts := strings.Split(cName, "_") - if isAllUpperStart(parts) { + parts, hasNS := cNameSplit(cName) + if !hasNS && isAllUpperStart(parts) { if parts[0] == "" && public { return "X" + cName } return cName } + lastEndWithUpper := false for i := 0; i < len(parts); i++ { part := parts[i] if part == "" { @@ -156,40 +223,25 @@ func (p *pkgCtx) cstyleToGo(cName string, public bool) string { } else { parts[i] = "_" } - } else if v, ok := rename[part]; ok { - parts[i] = v + continue + } + if v, ok := rename[part]; ok && v != "" { + part = v } else if i > 0 || public { - parts[i] = cPubName(part) + if c := part[0]; 'a' <= c && c <= 'z' { + c -= 'a' - 'A' + part = string(c) + part[1:] + } } - } - return strings.Join(parts, "") -} - -func (p *pkgCtx) nsName(ns, inner string) string { - if v, ok := p.rename[inner]; ok { - inner = v // special case - } - return nsName(ns, inner) -} - -func nsName(ns, inner string) string { - if ns != "" { - c := ns[len(ns)-1] - if 'A' <= c && c <= 'Z' { - ns += "_" + c := part[len(part)-1] + endWithUpper := 'A' <= c && c <= 'Z' + if lastEndWithUpper && endWithUpper { + part = "_" + part } + lastEndWithUpper = endWithUpper + parts[i] = part } - if c := inner[0]; 'a' <= c && c <= 'z' { - return ns + string(c-'a'+'A') + inner[1:] - } - return ns + inner -} - -func nameWithNS(name, ns string) string { - if ns == "" { - return name - } - return nsName(ns, name) + return strings.Join(parts, "") } // ----------------------------------------------------------------------------- @@ -221,16 +273,6 @@ func cutPrefix(name, prefix string) string { return name } -func cPubName(name string) string { - if r := name[0]; 'a' <= r && r <= 'z' { - r -= 'a' - 'A' - return string(r) + name[1:] - } else if r == '_' { - return "X" + name - } - return name -} - func rmPrefix(name string, prefix []string) string { for _, pfx := range prefix { if strings.HasPrefix(name, pfx) { diff --git a/cl/type.go b/cl/type.go index 78dfc929..5aacf1e5 100644 --- a/cl/type.go +++ b/cl/type.go @@ -130,12 +130,12 @@ func toTypeEx(ctx *pkgCtx, pkg *types.Package, typ lc.Type, flags int, feats *in *feats |= featHasCallback return toFuncType(ctx, pkg, typ, feats) case lc.Type_Enum: - cName := clang.String(typ.Declaration().Type()) + cName := cTypeName(typ) if t, ok := ctx.typeOf(cName); ok { return t } case lc.Type_Record, lc.Type_Typedef: - cName := clang.String(typ.Declaration().Type()) + cName := cTypeName(typ) if o, ok := ctx.types[cName]; ok { if o.feats != 0 { *feats |= o.feats @@ -146,7 +146,7 @@ func toTypeEx(ctx *pkgCtx, pkg *types.Package, typ lc.Type, flags int, feats *in return o.Type() } case lc.Type_Elaborated: - cName := clang.String(typ.Named()) + cName := cTypeName(typ.Named()) if t, ok := ctx.typeOf(cName); ok { return t } diff --git a/cl/typedef.go b/cl/typedef.go index 001dfa7c..8ca6bf10 100644 --- a/cl/typedef.go +++ b/cl/typedef.go @@ -18,7 +18,6 @@ package cl import ( "go/types" - "log" "github.com/goplus/llcppg/clang" lc "github.com/llarhub/clang-c" @@ -26,18 +25,16 @@ import ( // ----------------------------------------------------------------------------- -func loadTypedef(ctx *pkgCtx, decl clang.Cursor, ns string, scope *scopeCtx) { - cName := clang.String(decl.Type()) - localName := clang.String(decl) // TODO(xsw): use full name with namespace - if ctx.isTypeIgnored(localName) { - ctx.ignoref(featQuietIgnore, decl, "typedef %s: ignored by config", localName) +func loadTypedef(ctx *pkgCtx, decl clang.Cursor, scope *scopeCtx) { + cName := cNameOf(decl) + if ctx.isTypeIgnored(cName) { + ctx.ignoref(featQuietIgnore, decl, "typedef %s: ignored by config", cName) ctx.ignoreType(cName, featQuietIgnore) return } - origName := nameWithNS(localName, ns) if decl.Kind == lc.Cursor_TypeAliasTemplateDecl { - ctx.logf(decl, "typedef %s: template type alias, skipped", localName) + ctx.logf(decl, "typedef %s: template type alias, skipped", cName) return } @@ -45,25 +42,25 @@ func loadTypedef(ctx *pkgCtx, decl clang.Cursor, ns string, scope *scopeCtx) { pkgTypes := pkg.Types underlying := decl.TypedefDeclUnderlyingType() if debugCompileDecl { - log.Println("typedef", origName, "-", clang.String(underlying)) + ctx.logf(decl, "typedef %ss: %s", cName, clang.String(underlying)) } feats := 0 tunder := toTypeEx(ctx, pkgTypes, underlying, flagIsTypeDef, &feats, scope) if feats&featQuietIgnore != 0 || isTypedefUnsupported(tunder) { - ctx.ignoref(featQuietIgnore, decl, "typedef %s: unsupported underlying type, ignored", localName) + ctx.ignoref(featQuietIgnore, decl, "typedef %s: unsupported underlying type, ignored", cName) ctx.ignoreType(cName, featQuietIgnore) return } if feats&featExplicitIgnore != 0 { - ctx.logf(decl, "typedef %s: unsupported underlying type, skipped", localName) + ctx.logf(decl, "typedef %s: unsupported underlying type, skipped", cName) ctx.ignoreType(cName, featExplicitIgnore) return } - name := ctx.typeName(origName, true) + goName := ctx.typeName(cName, true) if tn, ok := tunder.(*types.Named); ok { - if o := tn.Obj(); o.Pkg() == pkgTypes && o.Name() == name { + if o := tn.Obj(); o.Pkg() == pkgTypes && o.Name() == goName { return // already defined } } @@ -88,15 +85,15 @@ func loadTypedef(ctx *pkgCtx, decl clang.Cursor, ns string, scope *scopeCtx) { node := goNode(ctx, decl) tparams := scope.typeParams(nil) if isClass { - t := typDefs.NewType(name, node).InitType(pkg, tunder, tparams...) + t := typDefs.NewType(goName, node).InitType(pkg, tunder, tparams...) obj = t.Obj() } else { - t := typDefs.AliasTypeEx(name, tunder, tparams, node) + t := typDefs.AliasTypeEx(goName, tunder, tparams, node) obj = t.Obj() } ctx.types[cName] = typeObj{obj, feats} - ctx.aliasTypeName(cName, name) + ctx.aliasTypeName(cName, goName) } func isTypedefUnsupported(tunder types.Type) bool { diff --git a/cl/union.go b/cl/union.go index 5f0c1dc6..7f387c29 100644 --- a/cl/union.go +++ b/cl/union.go @@ -19,7 +19,6 @@ package cl import ( "fmt" "go/types" - "log" "github.com/goplus/llcppg/clang" lc "github.com/llarhub/clang-c" @@ -52,43 +51,41 @@ const unionRefPrefix = "XGof_ref_" // Whether the union is global, in a namespace, or nested inside a class only // affects naming: ns carries the enclosing prefix, so the union type name goes // through getPubName like a struct's. -func loadUnion(ctx *pkgCtx, decl clang.Cursor, ns string) { - if decl.IsCursorDefinition() == 0 { - return +func loadUnion(ctx *pkgCtx, decl clang.Cursor) { + cName := cNameOf(decl) + if debugCompileDecl { + ctx.logf(decl, "union %s", cName) } - origName := nameWithNS(clang.String(decl), ns) - if debugCompileDecl { - log.Println("union", origName) + var typDecl, ok = ctx.typdecls[cName] + if !ok { + goName := ctx.typeName(cName, true) + typDecl = newType(ctx, decl, cName, goName) + ctx.typdecls[cName] = typDecl } - uName := ctx.typeName(origName, true) - emitUnion(ctx, decl, uName) + if decl.IsCursorDefinition() == 0 { + return // declaration only, no definition + } + + initUnionType(ctx, decl, typDecl) } -// emitUnion generates the Go struct "type uName struct { _xgo_union }" -// for a union declaration together with its XGof_ref_ accessors, and -// returns the named type. It is shared by loadUnion (named/tagged unions, where -// uName comes from getPubName) and by the anonymous-union hoisting in -// loadClassMember (where uName is a "_llcppg_union_" from -// pkgCtx.nextAnonUnionName). See issue goplus/llcppg#775. -func emitUnion(ctx *pkgCtx, decl clang.Cursor, uName string) *types.Named { - pkg := ctx.pkg - typDefs := pkg.NewTypeDefs() - if doc := ctx.docCommentGroup(decl); doc != nil { - typDefs.SetComments(doc) - } - typDecl := typDefs.NewType(uName, goNode(ctx, decl)) - typNamed := typDecl.Type() - ctx.addType(tagUnion, decl, typNamed) +func emitUnion(ctx *pkgCtx, decl clang.Cursor, goName string) *types.Named { + typDecl := newType(ctx, decl, "", goName) + initUnionType(ctx, decl, typDecl) + return typDecl.Type() +} +func initUnionType(ctx *pkgCtx, decl clang.Cursor, typDecl typDecl) { + pkg := ctx.pkg typ := decl.Type() storage, ok := unionStorageType(typ) if !ok { // A union with no body (GNU empty union) has no storage: emit an empty // struct with no accessors. typDecl.InitType(pkg, types.NewStruct(nil, nil)) - return typNamed + return } typDecl.InitType(pkg, unionStruct(ctx, decl, storage)) @@ -106,13 +103,12 @@ func emitUnion(ctx *pkgCtx, decl clang.Cursor, uName string) *types.Named { return clang.Continue }) - recvPtr := types.NewPointer(typNamed) + recvPtr := types.NewPointer(typDecl.Type()) ctx.addCompileUnit(func(ctx *pkgCtx) { for _, m := range members { genUnionAccessor(ctx, recvPtr, m) } }) - return typNamed } // unionStruct builds the "type X struct { _xgo_union }" definition. diff --git a/cl/var.go b/cl/var.go index b3176f02..794b6eba 100644 --- a/cl/var.go +++ b/cl/var.go @@ -17,8 +17,6 @@ package cl import ( - "log" - "github.com/goplus/llcppg/clang" lc "github.com/llarhub/clang-c" ) @@ -33,9 +31,9 @@ import ( // class (the class name acts like a namespace, mirroring how static methods are // handled). Non-static class member variables are fields, not VarDecls, and are // handled separately in loadClassMember. -func loadVar(ctx *pkgCtx, decl clang.Cursor, ns string) { +func loadVar(ctx *pkgCtx, decl clang.Cursor) { ctx.addCompileUnit(func(ctx *pkgCtx) { - compileVar(ctx, decl, ns) + compileVar(ctx, decl) }) } @@ -51,39 +49,34 @@ func loadVar(ctx *pkgCtx, decl clang.Cursor, ns string) { // const qualifier is a property of the type, not a distinct type kind, so // toType (which switches on the type kind) already yields the unqualified Go // type without any special casing here. -func compileVar(ctx *pkgCtx, decl clang.Cursor, ns string) { - localName := clang.String(decl) +func compileVar(ctx *pkgCtx, decl clang.Cursor) { + cName := cNameOf(decl) if varHasInitExpr(ctx, decl) { - ctx.logf(decl, "var %s: has initialized expression, skipped", localName) + ctx.logf(decl, "var %s: has initialized expression, skipped", cName) return } manglingName := clang.Mangling(decl) if _, ok := ctx.nameLookup(manglingName); !ok { - ctx.logf(decl, "var %s: symbol not found in lib files, skipped", localName) + ctx.logf(decl, "var %s: symbol not found in lib files, skipped", cName) return } - pkg := ctx.pkg - pkgTypes := pkg.Types - - origName := nameWithNS(localName, ns) if debugCompileDecl { - kind := "var" - if decl.Type().IsConstQualified() != 0 { - kind = "const var" - } - log.Println(kind, origName, "-", clang.String(decl.Type())) + ctx.logf(decl, "var %s: %s", cName, clang.String(decl.Type())) } + pkg := ctx.pkg + pkgTypes := pkg.Types + feats := 0 typ := toTypeEx(ctx, pkgTypes, decl.Type(), flagIsVarDef, &feats, nil) if feats&featAllIgnore != 0 { - ctx.ignoref(feats, decl, "var %s: unsupported type, ignored", localName) + ctx.ignoref(feats, decl, "var %s: unsupported type, ignored", cName) return } - goName := ctx.varName(origName) + goName := ctx.varName(cName) ctx.forceImportUnsafe() defs := pkg.NewVarDefs(pkgTypes.Scope()).SetComments( ctx.directiveComments(decl, "\n//go:linkname "+goName+" C."+manglingName)) diff --git a/cl/vtable.go b/cl/vtable.go index 52fb1d2a..f2571ec0 100644 --- a/cl/vtable.go +++ b/cl/vtable.go @@ -221,7 +221,7 @@ func vtableSlotFunc(ctx *pkgCtx, pkg *types.Package, recvPtr types.Type, fn clan // - A non-public (private/protected) virtual method still occupies a slot but // is rendered as an unexported placeholder, so later slots keep their index // without exposing an inaccessible member. -func vtableSlots(ctx *pkgCtx, scope *classCtx, cls clang.Cursor) []vtableSlot { +func vtableSlots(ctx *pkgCtx, _ *classCtx, cls clang.Cursor) []vtableSlot { var slots []vtableSlot if primary, ok := primaryBase(cls); ok { base := primary.Type().Declaration().Definition() @@ -350,9 +350,9 @@ func overriddenRoots(m clang.Cursor) []clang.Cursor { func vtableMethodName(ctx *pkgCtx, m clang.Cursor) string { fnUSR := funcUSR(m) if fn, ok := ctx.fns[fnUSR]; ok { - return ctx.funcName(fn.name, fn.order(), "", "", false, true) + return ctx.funcName(fn.cName, fn.order(), "", "", false, true) } - panic("vtableMethodName: method not found - " + funcDisplayName(m)) + panic("vtableMethodName: method not found - " + cNameOf(m)) } // placeholderSlotName returns the field name of an anonymous (reserved) slot at diff --git a/tool/_testcpp/llvm-22.1.8-support/AtomicOrdering/out.go b/tool/_testcpp/llvm-22.1.8-support/AtomicOrdering/out.go index b7b70f5d..181da2a0 100644 --- a/tool/_testcpp/llvm-22.1.8-support/AtomicOrdering/out.go +++ b/tool/_testcpp/llvm-22.1.8-support/AtomicOrdering/out.go @@ -11,12 +11,12 @@ const LLGoPackage = "link: -L$(llvm-config --libdir) -lLLVM; -lLLVM" type AtomicOrderingCABI c.Int const ( - AtomicOrderingCABI_Relaxed AtomicOrderingCABI = 0 - AtomicOrderingCABI_Consume AtomicOrderingCABI = 1 - AtomicOrderingCABI_Acquire AtomicOrderingCABI = 2 - AtomicOrderingCABI_Release AtomicOrderingCABI = 3 - AtomicOrderingCABI_AcqRel AtomicOrderingCABI = 4 - AtomicOrderingCABI_SeqCst AtomicOrderingCABI = 5 + AtomicOrderingCABI_relaxed AtomicOrderingCABI = 0 + AtomicOrderingCABI_consume AtomicOrderingCABI = 1 + AtomicOrderingCABI_acquire AtomicOrderingCABI = 2 + AtomicOrderingCABI_release AtomicOrderingCABI = 3 + AtomicOrderingCABI_acqRel AtomicOrderingCABI = 4 + AtomicOrderingCABI_seqCst AtomicOrderingCABI = 5 ) // Atomic ordering for LLVM's memory model. diff --git a/tool/_testcpp/llvm-22.1.8-support/StringRef/out.go b/tool/_testcpp/llvm-22.1.8-support/StringRef/out.go index be613888..307870c8 100644 --- a/tool/_testcpp/llvm-22.1.8-support/StringRef/out.go +++ b/tool/_testcpp/llvm-22.1.8-support/StringRef/out.go @@ -25,7 +25,7 @@ type StringRef struct { Length c.SizeT } type StringRefIterator = *c.Char -type StringRefConstStringRefIterator = *c.Char +type StringRefConstIterator = *c.Char type StringRefSizeType = c.SizeT type StringRefValueType = c.Char diff --git a/tool/_testcpp/llvm-22.1.8-support/llcppg-adt.cfg b/tool/_testcpp/llvm-22.1.8-support/llcppg-adt.cfg index 04bfcad7..6b944dcb 100644 --- a/tool/_testcpp/llvm-22.1.8-support/llcppg-adt.cfg +++ b/tool/_testcpp/llvm-22.1.8-support/llcppg-adt.cfg @@ -3,10 +3,10 @@ "Dir": "./include/llvm/ADT", "Class": [], "NonClass": [], - "FuncPrefix": ["Llvm"], - "EnumPrefix": ["Llvm"], - "TypePrefix": ["Llvm"], - "VarPrefix": ["Llvm"], + "FuncPrefix": ["llvm::", "Llvm"], + "EnumPrefix": ["llvm::", "Llvm"], + "TypePrefix": ["llvm::", "Llvm"], + "VarPrefix": ["llvm::", "Llvm"], "MacroPrefix": ["LLVM_"], "TypeAbbr": { }, diff --git a/tool/_testcpp/llvm-22.1.8-support/llcppg-system.cfg b/tool/_testcpp/llvm-22.1.8-support/llcppg-system.cfg index ecc7c238..390fa1a3 100644 --- a/tool/_testcpp/llvm-22.1.8-support/llcppg-system.cfg +++ b/tool/_testcpp/llvm-22.1.8-support/llcppg-system.cfg @@ -11,9 +11,10 @@ ], "Class": [], "NonClass": [], - "FuncPrefix": ["Llvm"], - "EnumPrefix": ["Llvm"], - "TypePrefix": ["Llvm"], + "NSPrefix": ["llvm::"], + "FuncPrefix": ["llvm::", "Llvm"], + "EnumPrefix": [], + "TypePrefix": [], "TypeSuffix": ["_t"], "MacroPrefix": ["LLVM_"], "TypeAbbr": { diff --git a/tool/_testcpp/llvm-22.1.8-support/system/AtomicOrdering.go b/tool/_testcpp/llvm-22.1.8-support/system/AtomicOrdering.go index f42787ad..77795dd7 100644 --- a/tool/_testcpp/llvm-22.1.8-support/system/AtomicOrdering.go +++ b/tool/_testcpp/llvm-22.1.8-support/system/AtomicOrdering.go @@ -11,12 +11,12 @@ import "github.com/goplus/lib/c" type AtomicOrderingCABI c.Int const ( - AtomicOrderingCABI_Relaxed AtomicOrderingCABI = 0 - AtomicOrderingCABI_Consume AtomicOrderingCABI = 1 - AtomicOrderingCABI_Acquire AtomicOrderingCABI = 2 - AtomicOrderingCABI_Release AtomicOrderingCABI = 3 - AtomicOrderingCABI_AcqRel AtomicOrderingCABI = 4 - AtomicOrderingCABI_SeqCst AtomicOrderingCABI = 5 + AtomicOrderingCABI_relaxed AtomicOrderingCABI = 0 + AtomicOrderingCABI_consume AtomicOrderingCABI = 1 + AtomicOrderingCABI_acquire AtomicOrderingCABI = 2 + AtomicOrderingCABI_release AtomicOrderingCABI = 3 + AtomicOrderingCABI_acqRel AtomicOrderingCABI = 4 + AtomicOrderingCABI_seqCst AtomicOrderingCABI = 5 ) // Atomic ordering for LLVM's memory model. diff --git a/tool/config.go b/tool/config.go index 50278909..c46ba697 100644 --- a/tool/config.go +++ b/tool/config.go @@ -38,6 +38,7 @@ type Config struct { Deps []string `json:"Deps"` // dependencies (module paths), optional Class []string `json:"Class"` // typedef names to be treated as classes NonClass []string `json:"NonClass"` // typedef names to be treated as non-classes + NSPrefix []string `json:"NSPrefix"` // namespace prefix to remove FuncPrefix []string `json:"FuncPrefix"` // global function prefix to remove VarPrefix []string `json:"VarPrefix"` // global variable prefix to remove EnumPrefix []string `json:"EnumPrefix"` // enum value prefix to remove diff --git a/tool/gen.go b/tool/gen.go index 3c1216ed..085f3280 100644 --- a/tool/gen.go +++ b/tool/gen.go @@ -186,6 +186,7 @@ func (cfg *Config) NewPackage(pkgPath, pkgName, workDir string, index clang.Inde CFlags: cfg.CFlags, Class: cfg.Class, NonClass: cfg.NonClass, + NSPrefix: cfg.NSPrefix, FuncPrefix: cfg.FuncPrefix, VarPrefix: cfg.VarPrefix, EnumPrefix: cfg.EnumPrefix, diff --git a/tool/gen_test.go b/tool/gen_test.go index 7a7a051d..6f52687a 100644 --- a/tool/gen_test.go +++ b/tool/gen_test.go @@ -126,6 +126,7 @@ func testSingleFile(t *testing.T, idx clang.Index, pkgDir, headerDir, headerFile Language: lang, Class: conf.Class, NonClass: conf.NonClass, + NSPrefix: conf.NSPrefix, FuncPrefix: conf.FuncPrefix, EnumPrefix: conf.EnumPrefix, MacroPrefix: conf.MacroPrefix,