diff --git a/cmd/genbindings/clang2il.go b/cmd/genbindings/clang2il.go index b38b98d6..aa5d0e47 100644 --- a/cmd/genbindings/clang2il.go +++ b/cmd/genbindings/clang2il.go @@ -185,6 +185,14 @@ func processTypedef(node map[string]interface{}, addNamePrefix string) (CppTyped return CppTypedef{}, errors.New("processTypedef: ???") } +type visibilityState int + +const ( + VsPublic visibilityState = 1 + VsProtected = 2 + VsPrivate = 3 +) + // processClassType parses a single C++ class definition into our intermediate format. func processClassType(node map[string]interface{}, addNamePrefix string) (CppClass, error) { var ret CppClass @@ -229,10 +237,10 @@ func processClassType(node map[string]interface{}, addNamePrefix string) (CppCla } } - // Check if this was 'struct' (default visible) or 'class' (default invisible) - visibility := true + // Check if this was 'struct' (default public) or 'class' (default private) + visibility := VsPublic if tagUsed, ok := node["tagUsed"].(string); ok && tagUsed == "class" { - visibility = false + visibility = VsPrivate } // Check if this is an abstract class @@ -289,9 +297,11 @@ nextMethod: switch access { case "public": - visibility = true - case "private", "protected": - visibility = false + visibility = VsPublic + case "protected": + visibility = VsProtected + case "private": + visibility = VsPrivate default: panic("unexpected access visibility '" + access + "'") } @@ -315,7 +325,7 @@ nextMethod: // Child class type definition e.g. QAbstractEventDispatcher::TimerInfo // Parse as a whole child class - if !visibility { + if visibility != VsPublic { continue // Skip private/protected } @@ -341,7 +351,7 @@ nextMethod: case "EnumDecl": // Child class enum - if !visibility { + if visibility != VsPublic { continue // Skip private/protected } @@ -359,7 +369,7 @@ nextMethod: // This is an implicit ctor. Therefore the class is constructable // even if we're currently in a `private:` block. - } else if !visibility { + } else if visibility != VsPublic { continue // Skip private/protected } @@ -403,7 +413,8 @@ nextMethod: continue } - if !visibility { + if visibility != VsPublic { + // TODO Is there any use case for allowing MIQT to overload a virtual destructor? ret.CanDelete = false continue } @@ -415,8 +426,12 @@ nextMethod: } case "CXXMethodDecl": - if !visibility { - continue // Skip private/protected + + // If this is a virtual method, we want to allow overriding it even + // if it is protected + // But we can only call it if it is public + if visibility == VsPrivate { + continue // Skip private, ALLOW protected } // Check if this is `= delete` @@ -648,6 +663,10 @@ func parseMethod(node map[string]interface{}, mm *CppMethod) error { mm.IsStatic = true } + if virtual, ok := node["virtual"].(bool); ok && virtual { + mm.IsVirtual = true + } + if methodInner, ok := node["inner"].([]interface{}); ok { paramCounter := 0 for _, methodObj := range methodInner {