From 8d1c871de3d0378ae4fa42d6fabf5e8aa0686bdc Mon Sep 17 00:00:00 2001 From: mappu Date: Tue, 19 Nov 2024 19:24:50 +1300 Subject: [PATCH] genbindings/inherits: direct vs indirect inheritance --- cmd/genbindings/clang2il.go | 2 +- cmd/genbindings/emitgo.go | 4 ++- cmd/genbindings/intermediate.go | 44 +++++++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/cmd/genbindings/clang2il.go b/cmd/genbindings/clang2il.go index 9ad21f94..e8747a5b 100644 --- a/cmd/genbindings/clang2il.go +++ b/cmd/genbindings/clang2il.go @@ -265,7 +265,7 @@ func processClassType(node map[string]interface{}, addNamePrefix string) (CppCla if typ, ok := base["type"].(map[string]interface{}); ok { if qualType, ok := typ["qualType"].(string); ok { - ret.Inherits = append(ret.Inherits, qualType) + ret.DirectInherits = append(ret.DirectInherits, qualType) } } } diff --git a/cmd/genbindings/emitgo.go b/cmd/genbindings/emitgo.go index ff67fe94..80324043 100644 --- a/cmd/genbindings/emitgo.go +++ b/cmd/genbindings/emitgo.go @@ -709,7 +709,9 @@ import "C" `) // Embed all inherited types to directly allow calling inherited methods - for _, base := range c.Inherits { + // Only include the direct inherits; the recursive inherits will exist + // on these types already + for _, base := range c.DirectInherits { if pkg, ok := KnownClassnames[base]; ok && pkg.PackageName != gfs.currentPackageName { // Cross-package parent class diff --git a/cmd/genbindings/intermediate.go b/cmd/genbindings/intermediate.go index eff54906..2ed07665 100644 --- a/cmd/genbindings/intermediate.go +++ b/cmd/genbindings/intermediate.go @@ -372,13 +372,13 @@ func (e CppEnum) ShortEnumName() string { } type CppClass struct { - ClassName string - Abstract bool - Ctors []CppMethod // only use the parameters - Inherits []string // other class names - Methods []CppMethod - Props []CppProperty - CanDelete bool + ClassName string + Abstract bool + Ctors []CppMethod // only use the parameters + DirectInherits []string // other class names. This only includes direct inheritance - use AllInherits() to find recursive inheritance + Methods []CppMethod + Props []CppProperty + CanDelete bool ChildTypedefs []CppTypedef ChildClassdefs []CppClass @@ -431,7 +431,10 @@ func (c *CppClass) VirtualMethods() []CppMethod { retNames[m.CppCallTarget()] = struct{}{} } - for _, inh := range c.Inherits { + // Only allow virtual overrides for direct inherits, not all inherits - + // Go will automatically allow virtual overrides for the base type because + // the parent struct is nested + for _, inh := range c.DirectInherits { // AllInherits() { cinfo, ok := KnownClassnames[inh] if !ok { panic("Class " + c.ClassName + " inherits from unknown class " + inh) @@ -481,6 +484,31 @@ func (c *CppClass) VirtualMethods() []CppMethod { return ret } +// AllInherits recursively finds and lists all the parent classes of this class. +func (c *CppClass) AllInherits() []string { + var ret []string + + // FIXME prevent duplicates arising from diamond inheritance + + for _, baseClass := range c.DirectInherits { + + ret = append(ret, baseClass) + + // And everything that class inherits - unless - we've seen it before + baseClassInfo, ok := KnownClassnames[baseClass] + if !ok { + panic("Class " + c.ClassName + " inherits from unknown class " + baseClass) + } + + recurseInfo := baseClassInfo.Class.AllInherits() + for _, childClass := range recurseInfo { + ret = append(ret, childClass) + } + } + + return ret +} + type CppTypedef struct { Alias string UnderlyingType CppParameter