From 2407b9da6ff47cf1fda0b9a12b7bff6c87758fed Mon Sep 17 00:00:00 2001 From: Jorn Vernee Date: Thu, 3 Sep 2020 13:12:44 +0000 Subject: [PATCH] 8252756: jextract does not handle VLAs/Incomplete Arrays/Flexible arrays Reviewed-by: mcimadamore --- .../jextract/impl/RecordLayoutComputer.java | 10 +-- .../jextract/impl/UnionLayoutComputer.java | 4 ++ .../jdk/internal/jextract/impl/Utils.java | 20 ------ .../incompleteArray/IncompleteArrayTest.java | 68 +++++++++++++++++++ .../incompleteArray/incompleteArray.h | 27 ++++++++ 5 files changed, 104 insertions(+), 25 deletions(-) create mode 100644 test/jdk/tools/jextract/incompleteArray/IncompleteArrayTest.java create mode 100644 test/jdk/tools/jextract/incompleteArray/incompleteArray.h diff --git a/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/RecordLayoutComputer.java b/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/RecordLayoutComputer.java index 8dcd2de0028..8972a4e2592 100644 --- a/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/RecordLayoutComputer.java +++ b/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/RecordLayoutComputer.java @@ -32,6 +32,7 @@ import jdk.internal.clang.Cursor; import jdk.internal.clang.CursorKind; import jdk.internal.clang.Type; +import jdk.internal.clang.TypeKind; import java.nio.ByteOrder; import java.util.ArrayList; @@ -70,10 +71,6 @@ static MemoryLayout compute(long offsetInParent, Type parent, Type type) { } final MemoryLayout compute() { - if (Utils.hasIncompleteArray(cursor)) { - //for now do this - incomplete arrays not supported well in clang - return MemoryLayout.ofStruct(MemoryLayout.ofPaddingBits(cursor.type().size() * 8)); - } Stream fieldCursors = Utils.flattenableChildren(cursor); for (Cursor fc : fieldCursors.collect(Collectors.toList())) { /* @@ -124,7 +121,10 @@ MemoryLayout fieldLayout(Cursor c) { } long fieldSize(Cursor c) { - return c.isBitField()? c.getBitFieldWidth() : c.type().size() * 8; + if (c.type().kind() == TypeKind.IncompleteArray) { + return 0; + } + return c.isBitField() ? c.getBitFieldWidth() : c.type().size() * 8; } //Todo: fixme diff --git a/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/UnionLayoutComputer.java b/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/UnionLayoutComputer.java index bf6c0fb974d..2928f81ef40 100644 --- a/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/UnionLayoutComputer.java +++ b/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/UnionLayoutComputer.java @@ -31,6 +31,7 @@ import jdk.incubator.foreign.ValueLayout; import jdk.internal.clang.Cursor; import jdk.internal.clang.Type; +import jdk.internal.clang.TypeKind; import java.util.List; @@ -69,6 +70,9 @@ MemoryLayout fieldLayout(Cursor c) { @Override long fieldSize(Cursor c) { + if (c.type().kind() == TypeKind.IncompleteArray) { + return 0; + } return c.type().size() * 8; } diff --git a/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/Utils.java b/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/Utils.java index b2da305d826..1a913d53d9a 100644 --- a/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/Utils.java +++ b/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/Utils.java @@ -201,26 +201,6 @@ static Stream flattenableChildren(Cursor c) { .filter(cx -> cx.isAnonymousStruct() || cx.kind() == CursorKind.FieldDecl); } - static Optional lastChild(Cursor c) { - List children = flattenableChildren(c) - .collect(Collectors.toList()); - return children.isEmpty() ? Optional.empty() : Optional.of(children.get(children.size() - 1)); - } - - static boolean hasIncompleteArray(Cursor c) { - switch (c.kind()) { - case FieldDecl: - return c.type().kind() == TypeKind.IncompleteArray; - case UnionDecl: - return flattenableChildren(c) - .anyMatch(Utils::hasIncompleteArray); - case StructDecl: - return lastChild(c).map(Utils::hasIncompleteArray).orElse(false); - default: - throw new IllegalStateException("Unhandled cursor kind: " + c.kind()); - } - } - // return builtin Record types accessible from the given Type static Stream getBuiltinRecordTypes(Type type) { List recordTypes = new ArrayList<>(); diff --git a/test/jdk/tools/jextract/incompleteArray/IncompleteArrayTest.java b/test/jdk/tools/jextract/incompleteArray/IncompleteArrayTest.java new file mode 100644 index 00000000000..3f0aade41a1 --- /dev/null +++ b/test/jdk/tools/jextract/incompleteArray/IncompleteArrayTest.java @@ -0,0 +1,68 @@ +/* + * 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. + */ + +/* + * @test + * @library .. /test/lib + * @modules jdk.incubator.jextract + * + * @run testng/othervm -Dforeign.restricted=permit IncompleteArrayTest + */ + +import jdk.incubator.foreign.MemoryLayout; +import org.testng.annotations.Test; + +import static jdk.incubator.foreign.CSupport.C_INT; +import static jdk.incubator.foreign.CSupport.C_POINTER; +import static org.testng.Assert.*; + +import java.nio.file.Path; + +public class IncompleteArrayTest extends JextractToolRunner { + + @Test + public void testIncompleteArray() { + Path output = getOutputFilePath("incompleteArray_out"); + Path input = getInputFilePath("incompleteArray.h"); + run( + "-t", "org.jextract", + "-d", output, + "--", + input).checkSuccess(); + try (Loader loader = classLoader(output)) { + Class cls = loader.loadClass("org.jextract.incompleteArray_h$Foo"); + assertNotNull(cls); + + MemoryLayout actualLayout = findLayout(cls); + MemoryLayout expectedLayout = MemoryLayout.ofStruct( + C_INT.withName("size"), + MemoryLayout.ofPaddingBits(32), + MemoryLayout.ofSequence(C_POINTER).withName("data") + ).withName("Foo"); + assertEquals(actualLayout, expectedLayout); + } finally { + //deleteDir(output); + } + } + +} diff --git a/test/jdk/tools/jextract/incompleteArray/incompleteArray.h b/test/jdk/tools/jextract/incompleteArray/incompleteArray.h new file mode 100644 index 00000000000..82d7d848e61 --- /dev/null +++ b/test/jdk/tools/jextract/incompleteArray/incompleteArray.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +struct Foo { + int size; + void* data[]; // incomplete array +};