From cf0b6ffb23f2be38e6ed32e2413ab14a43692efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Guillemet?= Date: Sun, 7 Jan 2024 13:32:49 +0100 Subject: [PATCH] Fix tracking of virtual inheritance for downcasting --- .../org/bytedeco/javacpp/tools/Parser.java | 61 +++++++++++++------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/bytedeco/javacpp/tools/Parser.java b/src/main/java/org/bytedeco/javacpp/tools/Parser.java index 2194023d..b07c694d 100644 --- a/src/main/java/org/bytedeco/javacpp/tools/Parser.java +++ b/src/main/java/org/bytedeco/javacpp/tools/Parser.java @@ -98,17 +98,40 @@ public Parser(Logger logger, Properties properties, String encoding, String line String lineSeparator = null; /** Java names of classes needing upcast from their subclasses. */ Set upcasts = new HashSet<>(); - /** Classes that have a base class appearing as key in this map need a downcast constructor. The associated value gives the class to downcast from. */ - Map> downcasts = new HashMap<>(); + + static private class Inheritance { + Type base; + boolean virtual; + + public Inheritance(Type b, boolean v) { + base = b; + virtual = v; + } + + @Override + public boolean equals(Object o) { + Inheritance i = (Inheritance) o; + return i != null && i.base.equals(base) && i.virtual == virtual; + } + + @Override + public int hashCode() { + return base.hashCode() + (virtual ? 1 : 0); + } + } + + /** Classes that have a base class appearing as a key in this map need a downcast constructor. + * The associated value gives the class to downcast from and whether the inheritance is virtual. */ + Map> downcasts = new HashMap<>(); /** Java names of classes recognized as polymorphic. */ Set polymorphicClasses = new HashSet<>(); - private void addDowncast(String base, Type from) { - Set types = downcasts.get(base); - if (types == null) { - downcasts.put(base, types = new HashSet<>(1)); + private void addDowncast(String base, Type from, boolean virtual) { + Set inh = downcasts.get(base); + if (inh == null) { + downcasts.put(base, inh = new HashSet<>(1)); } - types.add(from); + inh.add(new Inheritance(from, virtual)); } static String removeAnnotations(String s) { @@ -3450,9 +3473,9 @@ boolean using(Context context, DeclarationList declList) throws ParserException return true; } - String downcast(Type derived, Type base) { + String downcast(Type derived, Type base, boolean virtual) { final String downcastType; - if (base.virtual) { + if (virtual) { if (polymorphicClasses.contains(base.javaName)) { downcastType = "dynamic"; } else { @@ -3676,10 +3699,10 @@ boolean group(Context context, DeclarationList declList) throws ParserException /* Propagate the need for downcasting from base classes */ for (Type t : baseClasses) { - Set froms = downcasts.get(t.cppName); + Set froms = downcasts.get(t.cppName); if (froms != null) { - for (Type from : froms) { - addDowncast(type.cppName, from); + for (Inheritance from : froms) { + addDowncast(type.cppName, from.base, t.virtual || from.virtual); } } } @@ -3713,7 +3736,7 @@ boolean group(Context context, DeclarationList declList) throws ParserException Info baseInfo = infoMap.getFirst(t.cppName); if (!t.javaName.equals("Pointer") && (baseInfo == null || !baseInfo.skip)) { casts += upcast(type, t, false); - addDowncast(t.cppName, t); + addDowncast(t.cppName, t, false); } } } @@ -3724,11 +3747,11 @@ boolean group(Context context, DeclarationList declList) throws ParserException if (upcasts.contains(base.javaName)) { // Base classes explicitly set as needing upcast in infoMap casts += upcast(type, base, true); - addDowncast(base.cppName, base); + addDowncast(base.cppName, base, false); } else if (polymorphicClasses.contains(base.javaName) && base.virtual) { // In this case we know we need upcast casts += upcast(type, base, false); - addDowncast(base.cppName, base); + addDowncast(base.cppName, base, false); } decl.signature = type.javaName; @@ -3954,17 +3977,17 @@ boolean group(Context context, DeclarationList declList) throws ParserException } } - Set froms = downcasts.get(base.cppName); - for (Type t : froms != null ? froms : new HashSet()) { + Set froms = downcasts.get(base.cppName); + for (Inheritance i : froms != null ? froms : new HashSet()) { boolean found = false; for (Declaration d : declList2) { - if ((shortName + "_" + t.javaName).equals(d.signature)) { + if ((shortName + "_" + i.base.javaName).equals(d.signature)) { found = true; break; } } if (!found) { - constructors += downcast(type, t); + constructors += downcast(type, i.base, i.virtual || base.virtual); } }