Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8245767: jextract crashes with typedef on a opaque struct or union #181

Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -69,6 +69,7 @@
private Map<Declaration, String> structClassNames = new HashMap<>();
private List<String> structSources = new ArrayList<>();
private Set<String> nestedClassNames = new HashSet<>();
private Set<Declaration.Typedef> unresolvedStructTypedefs = new HashSet<>();
private int nestedClassNameCount = 0;
/*
* We may have case-insensitive name collision! A C program may have
@@ -87,6 +88,10 @@ private String structClassName(Declaration decl) {
return structClassNames.computeIfAbsent(decl, d -> uniqueNestedClassName("C" + d.name()));
}

private boolean structDefinitionSeen(Declaration decl) {
return structClassNames.containsKey(decl);
}

// have we seen this Variable earlier?
protected boolean variableSeen(Declaration.Variable tree) {
return !variables.add(tree);
@@ -137,6 +142,13 @@ private static String getCLangConstantsHolder() {
for (String src : structSources) {
builder.addContent(src);
}
// check if unresolved typedefs can be resolved now!
for (Declaration.Typedef td : unresolvedStructTypedefs) {
Declaration.Scoped structDef = ((Type.Declared)td.type()).tree();
if (structDefinitionSeen(structDef)) {
builder.emitTypedef(uniqueNestedClassName("C" + td.name()), structClassName(structDef));
}
}
builder.classEnd();
try {
List<JavaFileObject> files = new ArrayList<>();
@@ -325,7 +337,26 @@ public Void visitTypedef(Declaration.Typedef tree, Declaration parent) {
if (s.name().isEmpty()) {
visitScoped(s, tree);
} else {
builder.emitTypedef(uniqueNestedClassName("C" + tree.name()), structClassName(s));
/*
* If typedef is seen after the struct/union definition, we can generate subclass
* right away. If not, we've to save it and revisit after all the declarations are
* seen. This is to support forward declaration of typedefs.
*
* typedef struct Foo Bar;
*
* struct Foo {
* int x, y;
* };
*/
if (structDefinitionSeen(s)) {
builder.emitTypedef(uniqueNestedClassName("C" + tree.name()), structClassName(s));
} else {
/*
* Definition of typedef'ed struct/union not seen yet. May be the definition comes later.
* Save it to visit at the end of all declarations.
*/
unresolvedStructTypedefs.add(tree);
}
}
}
break;
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

import java.nio.file.Path;

import org.testng.annotations.Test;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

/*
* @test
* @modules jdk.incubator.jextract
* @library /test/lib
* @build JextractToolRunner
* @bug 8245767
* @summary jextract crashes with typedef on a opaque struct or union
* @run testng/othervm -Dforeign.restricted=permit Test8245767
*/
public class Test8245767 extends JextractToolRunner {
@Test
public void testTypedefs() {
Path test8245767Output = getOutputFilePath("test8245767_gen");
Path test8245767H = getInputFilePath("test8245767.h");
run("-d", test8245767Output.toString(), test8245767H.toString()).checkSuccess();
try(Loader loader = classLoader(test8245767Output)) {
Class<?> cls = loader.loadClass("test8245767_h");
assertNotNull(cls);

// no class should be generated for typedef on opaque struct
Class<?> fooCls = loader.loadClass("test8245767_h$CFoo");
assertNull(fooCls);

// check Point_t
Class<?> point_tCls = loader.loadClass("test8245767_h$CPoint_t");
assertNotNull(point_tCls);

// check Point
Class<?> pointCls = loader.loadClass("test8245767_h$CPoint");
assertNotNull(pointCls);
assertTrue(pointCls.isAssignableFrom(point_tCls));
} finally {
deleteDir(test8245767Output);
}
}
}
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

typedef struct _Bar Foo;

typedef struct Point Point_t;

struct Point {
int x, y;
};