Skip to content
4 changes: 2 additions & 2 deletions cl/_testc/struct/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 2 additions & 0 deletions cl/_testc/union_basic/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
8 changes: 4 additions & 4 deletions cl/_testc/union_struct/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
12 changes: 6 additions & 6 deletions cl/_testcpp/enum/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ 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 {
}
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
)
21 changes: 20 additions & 1 deletion cl/_testcpp/struct/in.h
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
19 changes: 19 additions & 0 deletions cl/_testcpp/struct/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
105 changes: 51 additions & 54 deletions cl/class.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package cl

import (
"go/types"
"log"
"strconv"
"unsafe"

Expand Down Expand Up @@ -106,99 +105,97 @@ 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)
})
}
}

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.
Expand All @@ -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 {
Expand Down Expand Up @@ -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()
}
Expand All @@ -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:
Expand All @@ -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
}
Expand All @@ -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
}
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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:
Expand All @@ -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 {
Expand All @@ -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,
Expand All @@ -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)
}
}

Expand Down Expand Up @@ -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))
}
}

Expand Down
Loading
Loading