diff --git a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/OutputFactory.java b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/OutputFactory.java index 23a5a3cd6a0..c69a1f5b5cf 100644 --- a/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/OutputFactory.java +++ b/src/jdk.incubator.jextract/share/classes/jdk/incubator/jextract/tool/OutputFactory.java @@ -70,6 +70,11 @@ private final String pkgName; private StructBuilder structBuilder; private List structSources = new ArrayList<>(); + private Set structClassNames = new HashSet<>(); + private int structClassNameCount = 0; + private String uniqueStructClassName(String name) { + return structClassNames.add(name.toLowerCase())? name : (name + "$" + structClassNameCount++); + } // have we seen this Variable earlier? protected boolean variableSeen(Declaration.Variable tree) { @@ -223,7 +228,7 @@ public Void visitScoped(Declaration.Scoped d, Declaration parent) { return null; } String name = d.name(); - if (name.isEmpty() && parent != null) { + if (parent instanceof Declaration.Typedef) { name = parent.name(); } @@ -234,10 +239,20 @@ public Void visitScoped(Declaration.Scoped d, Declaration parent) { case STRUCT: case UNION: { structClass = true; - this.structBuilder = new StructBuilder("C" + name, pkgName, constantHelper); + /* + * We may have case-insensitive name collision! A C program may have + * defined structs with the names FooS, fooS, FoOs, fOOs. Because we + * map structs and unions to nested classes of header classes, such + * a case-insensitive name collision is problematic. This is because in + * a case-insensitive file system javac will overwrite classes for + * Header$CFooS, Header$CfooS, Header$CFoOs and so on! We solve this by + * generating unique case-insensitive names for classes. + */ + String structClassName = uniqueStructClassName("C" + name); + this.structBuilder = new StructBuilder(structClassName, pkgName, constantHelper); structBuilder.incrAlign(); structBuilder.classBegin(); - structBuilder.addLayoutGetter("C" + name, d.layout().get()); + structBuilder.addLayoutGetter(structClassName, d.layout().get()); break; } } @@ -309,9 +324,7 @@ public Void visitTypedef(Declaration.Typedef tree, Declaration parent) { Type type = tree.type(); if (type instanceof Type.Declared) { Declaration.Scoped s = ((Type.Declared) type).tree(); - // only generate unnamed for now - // skip typedef with different name - if (s.name().isEmpty()) { + if (!s.name().equals(tree.name())) { return visitScoped(s, tree); } } diff --git a/test/jdk/tools/jextract/RepeatedDeclsTest.java b/test/jdk/tools/jextract/RepeatedDeclsTest.java index d7088207bee..56639fc96f1 100644 --- a/test/jdk/tools/jextract/RepeatedDeclsTest.java +++ b/test/jdk/tools/jextract/RepeatedDeclsTest.java @@ -83,23 +83,32 @@ public void repeatedDecls() { checkIntGetter(cls, "Y", 2); // check Point layout - Class pointCls = loader.loadClass("repeatedDecls_h$CPoint"); - MemoryLayout pointLayout = findLayout(pointCls); - assertNotNull(pointLayout); - assertTrue(((GroupLayout)pointLayout).isStruct()); - checkFieldABIType(pointLayout, "i", Type.INT); - checkFieldABIType(pointLayout, "j", Type.INT); + checkPoint(loader.loadClass("repeatedDecls_h$CPoint")); + checkPoint(loader.loadClass("repeatedDecls_h$CPoint_t")); + checkPoint(loader.loadClass("repeatedDecls_h$CPOINT$0")); // check Point3D layout - Class point3DCls = loader.loadClass("repeatedDecls_h$CPoint3D"); - MemoryLayout point3DLayout = findLayout(point3DCls); - assertNotNull(point3DLayout); - assertTrue(((GroupLayout)point3DLayout).isStruct()); - checkFieldABIType(point3DLayout, "i", Type.INT); - checkFieldABIType(point3DLayout, "j", Type.INT); - checkFieldABIType(point3DLayout, "k", Type.INT); + checkPoint3D(loader.loadClass("repeatedDecls_h$CPoint3D")); + checkPoint3D(loader.loadClass("repeatedDecls_h$CPoint3D_t")); } finally { deleteDir(repeatedDeclsOutput); } } + + private void checkPoint(Class pointCls) { + MemoryLayout pointLayout = findLayout(pointCls); + assertNotNull(pointLayout); + assertTrue(((GroupLayout)pointLayout).isStruct()); + checkFieldABIType(pointLayout, "i", Type.INT); + checkFieldABIType(pointLayout, "j", Type.INT); + } + + private void checkPoint3D(Class point3DCls) { + MemoryLayout point3DLayout = findLayout(point3DCls); + assertNotNull(point3DLayout); + assertTrue(((GroupLayout)point3DLayout).isStruct()); + checkFieldABIType(point3DLayout, "i", Type.INT); + checkFieldABIType(point3DLayout, "j", Type.INT); + checkFieldABIType(point3DLayout, "k", Type.INT); + } } diff --git a/test/jdk/tools/jextract/repeatedDecls.h b/test/jdk/tools/jextract/repeatedDecls.h index 5d08e08f07a..e3170cf79ad 100644 --- a/test/jdk/tools/jextract/repeatedDecls.h +++ b/test/jdk/tools/jextract/repeatedDecls.h @@ -61,14 +61,16 @@ struct Point { }; typedef struct Point POINT; +typedef struct Point Point_t; + double distance(struct Point p); double distance(POINT p); -struct Point3D { +typedef struct Point3D { int i; int j; int k; -}; +} Point3D_t; struct Point3D; enum RGBColor;