Skip to content

Commit 864acb5

Browse files
committedDec 14, 2023
7903608: Cyclic initialization leads to NPE in header class with global variable
Reviewed-by: jvernee
1 parent 169664c commit 864acb5

File tree

14 files changed

+330
-72
lines changed

14 files changed

+330
-72
lines changed
 

‎src/main/java/org/openjdk/jextract/impl/HeaderFileBuilder.java

+15-26
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,9 @@ public void addVar(Declaration.Variable varTree, Optional<String> fiName) {
6262
if (Utils.isArray(varTree.type()) || Utils.isStructOrUnion(varTree.type())) {
6363
emitGlobalSegment(layoutVar, javaName, nativeName, varTree);
6464
} else if (Utils.isPointer(varTree.type()) || Utils.isPrimitive(varTree.type())) {
65-
String vhConstant = emitGlobalVarHandle(javaName, layoutVar);
6665
String segmentConstant = emitGlobalSegment(layoutVar, javaName, nativeName, null);
67-
emitGlobalGetter(segmentConstant, vhConstant, javaName, varTree, "Getter for variable:");
68-
emitGlobalSetter(segmentConstant, vhConstant, javaName, varTree, "Setter for variable:");
66+
emitGlobalGetter(segmentConstant, layoutVar, javaName, varTree, "Getter for variable:");
67+
emitGlobalSetter(segmentConstant, layoutVar, javaName, varTree, "Setter for variable:");
6968
fiName.ifPresent(s -> emitFunctionalInterfaceGetter(s, javaName));
7069
} else {
7170
throw new IllegalArgumentException("Tree type not handled: " + varTree.type());
@@ -292,27 +291,27 @@ private static MemoryLayout variadicLayout(Class<?> c) {
292291
""");
293292
}
294293

295-
private void emitGlobalGetter(String segmentConstant, String vhConstant, String javaName,
294+
private void emitGlobalGetter(String segmentConstant, String layoutVar, String javaName,
296295
Declaration.Variable decl, String docHeader) {
297296
incrAlign();
298297
emitDocComment(decl, docHeader);
299298
Class<?> type = Utils.carrierFor(decl.type());
300299
appendLines(STR."""
301300
public static \{type.getSimpleName()} \{javaName}$get() {
302-
return (\{type.getSimpleName()}) \{vhConstant}.get(\{segmentConstant}(), 0L);
301+
return \{segmentConstant}.get(\{layoutVar}, 0L);
303302
}
304303
""");
305304
decrAlign();
306305
}
307306

308-
private void emitGlobalSetter(String segmentConstant, String vhConstant, String javaName,
307+
private void emitGlobalSetter(String segmentConstant, String layoutVar, String javaName,
309308
Declaration.Variable decl, String docHeader) {
310309
incrAlign();
311310
emitDocComment(decl, docHeader);
312311
Class<?> type = Utils.carrierFor(decl.type());
313312
appendLines(STR."""
314313
public static void \{javaName}$set(\{type.getSimpleName()} x) {
315-
\{vhConstant}.set(\{segmentConstant}(), 0L, x);
314+
\{segmentConstant}.set(\{layoutVar}, 0L, x);
316315
}
317316
""");
318317
decrAlign();
@@ -334,31 +333,21 @@ class Holder {
334333
}
335334
""");
336335
decrAlign();
337-
return mangledName;
336+
return STR."\{mangledName}()";
338337
}
339338

340339
private String emitVarLayout(Type varType, String javaName) {
341340
String mangledName = mangleName(javaName, MemoryLayout.class);
341+
String layoutType = Utils.layoutCarrierFor(varType).getSimpleName();
342342
appendIndentedLines(STR."""
343-
private static final MemoryLayout \{mangledName} = \{layoutString(varType)};
344-
345-
\{MEMBER_MODS} MemoryLayout \{mangledName}() {
346-
return \{mangledName};
347-
}
348-
""");
349-
return mangledName;
350-
}
351-
352-
private String emitGlobalVarHandle(String javaName, String layoutVar) {
353-
String mangledName = mangleName(javaName, VarHandle.class);
354-
appendIndentedLines(STR."""
355-
private static final VarHandle \{mangledName} = \{layoutVar}.varHandle();
356-
357-
\{MEMBER_MODS} VarHandle \{mangledName}() {
358-
return \{mangledName};
343+
\{MEMBER_MODS} \{layoutType} \{mangledName}() {
344+
class Holder {
345+
static final \{layoutType} LAYOUT = \{layoutString(varType)};
346+
}
347+
return Holder.LAYOUT;
359348
}
360349
""");
361-
return mangledName;
350+
return STR."\{mangledName}()";
362351
}
363352

364353
private void emitConstant(Class<?> javaType, String constantName, Object value, Declaration declaration) {
@@ -421,7 +410,7 @@ private void emitPrimitiveTypedefLayout(String javaName, Type type, Declaration
421410
incrAlign();
422411
emitDocComment(declaration);
423412
appendLines(STR."""
424-
public static final \{Utils.valueLayoutCarrierFor(type).getSimpleName()} \{javaName} = \{layoutString(type)};
413+
public static final \{Utils.layoutCarrierFor(type).getSimpleName()} \{javaName} = \{layoutString(type)};
425414
""");
426415
decrAlign();
427416
}

‎src/main/java/org/openjdk/jextract/impl/SourceFileBuilder.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,12 @@ void decrAlign() {
9191
align--;
9292
}
9393

94+
public JavaFileObject toFile(String suffix, Function<String, String> finisher) {
95+
return Utils.fileFromString(packageName, STR."\{className}\{suffix}", finisher.apply(sb.toString()));
96+
}
97+
9498
public JavaFileObject toFile(Function<String, String> finisher) {
95-
return Utils.fileFromString(packageName, className, finisher.apply(sb.toString()));
99+
return toFile("", finisher);
96100
}
97101

98102
public JavaFileObject toFile() {

‎src/main/java/org/openjdk/jextract/impl/StructBuilder.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -246,9 +246,9 @@ private void emitIndexedFieldSetter(String javaName, Type varType, String offset
246246

247247
private void emitLayoutDecl() {
248248
appendIndentedLines(STR."""
249-
private static final MemoryLayout $LAYOUT = \{structOrUnionLayoutString(structType)};
249+
private static final GroupLayout $LAYOUT = \{structOrUnionLayoutString(structType)};
250250
251-
public static final MemoryLayout $LAYOUT() {
251+
public static final GroupLayout $LAYOUT() {
252252
return $LAYOUT;
253253
}
254254
""");

‎src/main/java/org/openjdk/jextract/impl/ToplevelBuilder.java

+41-27
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,20 @@ class ToplevelBuilder implements OutputFactory.Builder {
4343
private static final int DECLS_PER_HEADER_CLASS = Integer.getInteger("jextract.decls.per.header", 1000);
4444

4545
private int declCount;
46-
private final List<SourceFileBuilder> builders = new ArrayList<>();
47-
private final HeaderFileBuilder firstHeader;
46+
private final List<SourceFileBuilder> headerBuilders = new ArrayList<>();
47+
private final List<SourceFileBuilder> otherBuilders = new ArrayList<>();
4848
private HeaderFileBuilder lastHeader;
49-
private int headersCount;
5049
private final ClassDesc headerDesc;
5150

5251
ToplevelBuilder(String packageName, String headerClassName, List<String> libraries) {
5352
this.headerDesc = ClassDesc.of(packageName, headerClassName);
5453
SourceFileBuilder sfb = SourceFileBuilder.newSourceFile(packageName, headerClassName);
55-
lastHeader = firstHeader = createFirstHeader(sfb, libraries);
54+
headerBuilders.add(sfb);
55+
lastHeader = createFirstHeader(sfb, libraries);
5656
}
5757

5858
private static HeaderFileBuilder createFirstHeader(SourceFileBuilder sfb, List<String> libraries) {
59-
HeaderFileBuilder first = new HeaderFileBuilder(sfb, sfb.className(), "#{SUPER}", sfb.className());
59+
HeaderFileBuilder first = new HeaderFileBuilder(sfb, STR."\{sfb.className()}#{SUFFIX}", null, sfb.className());
6060
first.classBegin();
6161
first.emitFirstHeaderPreamble(libraries);
6262
// emit basic primitive types
@@ -77,24 +77,42 @@ private static HeaderFileBuilder createFirstHeader(SourceFileBuilder sfb, List<S
7777
} else {
7878
first.appendIndentedLines("public static final ValueLayout.OfLong C_LONG = ValueLayout.JAVA_LONG;");
7979
}
80+
first.emitRuntimeHelperMethods();
8081
return first;
8182
}
8283

8384
public List<JavaFileObject> toFiles() {
84-
boolean hasOneHeader = lastHeader == firstHeader;
85-
if (hasOneHeader) {
86-
firstHeader.emitRuntimeHelperMethods();
87-
}
8885
lastHeader.classEnd();
8986

9087
List<JavaFileObject> files = new ArrayList<>();
91-
files.add(firstHeader.sourceFileBuilder().toFile(s -> s.replace("extends #{SUPER}",
92-
hasOneHeader ? "" : "extends " + lastHeader.className())));
93-
files.addAll(builders.stream()
88+
89+
if (headerBuilders.size() == 1) {
90+
files.add(headerBuilders.get(0).toFile(s -> s.replace("#{SUFFIX}", "")));
91+
} else {
92+
// adjust suffixes so that the last header class becomes the main header class,
93+
// and extends all the other header classes
94+
int suffix = headerBuilders.size() - 1;
95+
for (SourceFileBuilder header : headerBuilders) {
96+
String currentSuffix = suffix == 0 ?
97+
"" : // main header class, drop the suffix
98+
STR."_\{suffix}";
99+
String prevSuffix = STR."_\{suffix + 1}";
100+
files.add(header.toFile(currentSuffix,
101+
s -> s.replace("#{SUFFIX}", currentSuffix)
102+
.replace("#{PREV_SUFFIX}", prevSuffix)));
103+
suffix--;
104+
}
105+
}
106+
// add remaining builders
107+
files.addAll(otherBuilders.stream()
94108
.map(SourceFileBuilder::toFile).toList());
95109
return files;
96110
}
97111

112+
public String mainHeaderClassName() {
113+
return headerDesc.displayName();
114+
}
115+
98116
public String packageName() {
99117
return headerDesc.packageName();
100118
}
@@ -125,41 +143,37 @@ public void addTypedef(Declaration.Typedef typedefTree, String superClass, Type
125143
nextHeader().emitPointerTypedef(typedefTree, javaName);
126144
} else {
127145
SourceFileBuilder sfb = SourceFileBuilder.newSourceFile(packageName(), javaName);
128-
TypedefBuilder.generate(sfb, sfb.className(), superClass, firstHeader.className(), typedefTree);
129-
builders.add(sfb);
146+
TypedefBuilder.generate(sfb, sfb.className(), superClass, mainHeaderClassName(), typedefTree);
147+
otherBuilders.add(sfb);
130148
}
131149
}
132150

133151
@Override
134152
public StructBuilder addStruct(Declaration.Scoped tree) {
135153
SourceFileBuilder sfb = SourceFileBuilder.newSourceFile(packageName(), JavaName.getOrThrow(tree));
136-
builders.add(sfb);
137-
StructBuilder structBuilder = new StructBuilder(sfb, "public", sfb.className(), null, firstHeader.className(), tree);
154+
otherBuilders.add(sfb);
155+
StructBuilder structBuilder = new StructBuilder(sfb, "public", sfb.className(), null, mainHeaderClassName(), tree);
138156
structBuilder.begin();
139157
return structBuilder;
140158
}
141159

142160
@Override
143161
public void addFunctionalInterface(String name, Type.Function funcType) {
144162
SourceFileBuilder sfb = SourceFileBuilder.newSourceFile(packageName(), name);
145-
builders.add(sfb);
146-
FunctionalInterfaceBuilder.generate(sfb, sfb.className(), null, firstHeader.className(), funcType,
163+
otherBuilders.add(sfb);
164+
FunctionalInterfaceBuilder.generate(sfb, sfb.className(), null, mainHeaderClassName(), funcType,
147165
funcType.parameterNames().map(NameMangler::javaSafeIdentifiers));
148166
}
149167

150168
private HeaderFileBuilder nextHeader() {
151169
if (declCount == DECLS_PER_HEADER_CLASS) {
152-
boolean wasFirstHeader = lastHeader == firstHeader;
153-
if (wasFirstHeader) {
154-
firstHeader.emitRuntimeHelperMethods();
155-
}
156-
String className = headerDesc.displayName() + "_" + ++headersCount;
157-
SourceFileBuilder sfb = SourceFileBuilder.newSourceFile(packageName(), className);
158-
HeaderFileBuilder headerFileBuilder = new HeaderFileBuilder(sfb, sfb.className(),
159-
wasFirstHeader ? null : lastHeader.className(), firstHeader.className());
170+
SourceFileBuilder sfb = SourceFileBuilder.newSourceFile(packageName(), mainHeaderClassName());
171+
String className = mainHeaderClassName() + "#{SUFFIX}";
172+
HeaderFileBuilder headerFileBuilder = new HeaderFileBuilder(sfb, className,
173+
mainHeaderClassName() + "#{PREV_SUFFIX}", mainHeaderClassName());
160174
lastHeader.classEnd();
161175
headerFileBuilder.classBegin();
162-
builders.add(sfb);
176+
headerBuilders.add(sfb);
163177
lastHeader = headerFileBuilder;
164178
declCount = 1;
165179
return headerFileBuilder;

‎src/main/java/org/openjdk/jextract/impl/Utils.java

+16-9
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
package org.openjdk.jextract.impl;
2828

2929
import org.openjdk.jextract.Declaration;
30+
import org.openjdk.jextract.Declaration.Constant;
3031
import org.openjdk.jextract.Type;
3132
import org.openjdk.jextract.Type.Delegated;
3233
import org.openjdk.jextract.Type.Delegated.Kind;
@@ -38,7 +39,9 @@
3839
import javax.tools.SimpleJavaFileObject;
3940
import java.lang.foreign.AddressLayout;
4041
import java.io.IOException;
42+
import java.lang.foreign.GroupLayout;
4143
import java.lang.foreign.MemorySegment;
44+
import java.lang.foreign.SequenceLayout;
4245
import java.lang.foreign.ValueLayout;
4346
import java.lang.invoke.MethodType;
4447
import java.net.URI;
@@ -237,15 +240,19 @@ public static Class<?> carrierFor(Type.Primitive p) {
237240
};
238241
}
239242

240-
public static Class<?> valueLayoutCarrierFor(Type t) {
241-
if (t instanceof Delegated delegated && delegated.kind() == Delegated.Kind.POINTER) {
242-
return AddressLayout.class;
243-
} else if (t instanceof Type.Primitive p) {
244-
Class<?> clazz = carrierFor(p);
245-
return CARRIERS_TO_LAYOUT_CARRIERS.get(clazz);
246-
} else {
247-
throw new UnsupportedOperationException(t.toString());
248-
}
243+
public static Class<?> layoutCarrierFor(Type t) {
244+
return switch (t) {
245+
case Type.Array _ -> SequenceLayout.class;
246+
case Delegated delegated when delegated.kind() == Kind.POINTER -> AddressLayout.class;
247+
case Delegated delegated -> layoutCarrierFor(delegated.type());
248+
case Type.Primitive primitive -> {
249+
Class<?> clazz = carrierFor(primitive);
250+
yield CARRIERS_TO_LAYOUT_CARRIERS.get(clazz);
251+
}
252+
case Type.Declared declared when isStructOrUnion(declared) -> GroupLayout.class;
253+
case Type.Declared declared when isEnum(declared) -> layoutCarrierFor(((Constant)declared.tree().members().get(0)).type());
254+
default -> throw new UnsupportedOperationException(t.toString());
255+
};
249256
}
250257

251258
static final Map<Class<?>, Class<?>> CARRIERS_TO_LAYOUT_CARRIERS = Map.of(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 only, as
6+
* published by the Free Software Foundation.
7+
*
8+
* This code is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
* version 2 for more details (a copy is included in the LICENSE file that
12+
* accompanied this code).
13+
*
14+
* You should have received a copy of the GNU General Public License version
15+
* 2 along with this work; if not, write to the Free Software Foundation,
16+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*
18+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19+
* or visit www.oracle.com if you need additional information or have any
20+
* questions.
21+
*/
22+
23+
import org.testng.annotations.Test;
24+
25+
import static org.testng.Assert.*;
26+
27+
import test.jextract.clinit.*;
28+
29+
import java.lang.foreign.ValueLayout;
30+
31+
/*
32+
* @test id=classes
33+
* @library /lib
34+
* @run main/othervm JtregJextract -t test.jextract.clinit -Djextract.decls.per.header=1 clinit_global.h
35+
* @build TestGlobal
36+
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestGlobal
37+
*/
38+
/*
39+
* @test id=sources
40+
* @library /lib
41+
* @run main/othervm JtregJextractSources -t test.jextract.clinit -Djextract.decls.per.header=1 clinit_global.h
42+
* @build TestGlobal
43+
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestGlobal
44+
*/
45+
public class TestGlobal {
46+
47+
@Test
48+
public void testGlobal() {
49+
ValueLayout layout = clinit_global_h.C_INT;
50+
assertNotNull(layout);
51+
assertEquals(layout, clinit_global_h.global1$LAYOUT());
52+
assertEquals(layout, clinit_global_h.global2$LAYOUT());
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 only, as
6+
* published by the Free Software Foundation.
7+
*
8+
* This code is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
* version 2 for more details (a copy is included in the LICENSE file that
12+
* accompanied this code).
13+
*
14+
* You should have received a copy of the GNU General Public License version
15+
* 2 along with this work; if not, write to the Free Software Foundation,
16+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*
18+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19+
* or visit www.oracle.com if you need additional information or have any
20+
* questions.
21+
*/
22+
23+
import org.testng.annotations.Test;
24+
import test.jextract.clinit.*;
25+
26+
import java.lang.foreign.GroupLayout;
27+
import java.lang.foreign.ValueLayout;
28+
29+
import static org.testng.Assert.*;
30+
31+
/*
32+
* @test id=classes
33+
* @library /lib
34+
* @run main/othervm JtregJextract -t test.jextract.clinit -Djextract.decls.per.header=1 clinit_struct.h
35+
* @build TestStruct
36+
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestStruct
37+
*/
38+
/*
39+
* @test id=sources
40+
* @library /lib
41+
* @run main/othervm JtregJextractSources -t test.jextract.clinit -Djextract.decls.per.header=1 clinit_struct.h
42+
* @build TestStruct
43+
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestStruct
44+
*/
45+
public class TestStruct {
46+
47+
@Test
48+
public void TestStruct() {
49+
ValueLayout layout = clinit_struct_h.C_INT;
50+
assertNotNull(layout);
51+
GroupLayout pointLayout = Point.$LAYOUT();
52+
assertNotNull(pointLayout);
53+
assertEquals(pointLayout.memberLayouts().get(0).withoutName(), layout);
54+
assertEquals(pointLayout.memberLayouts().get(1).withoutName(), layout);
55+
}
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 only, as
6+
* published by the Free Software Foundation.
7+
*
8+
* This code is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
* version 2 for more details (a copy is included in the LICENSE file that
12+
* accompanied this code).
13+
*
14+
* You should have received a copy of the GNU General Public License version
15+
* 2 along with this work; if not, write to the Free Software Foundation,
16+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*
18+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19+
* or visit www.oracle.com if you need additional information or have any
20+
* questions.
21+
*/
22+
23+
import org.testng.annotations.Test;
24+
25+
import static org.testng.Assert.*;
26+
27+
import test.jextract.clinit.*;
28+
29+
import java.lang.foreign.ValueLayout;
30+
31+
/*
32+
* @test id=classes
33+
* @library /lib
34+
* @run main/othervm JtregJextract -l Func -t test.jextract.clinit -Djextract.decls.per.header=1 clinit_typedef.h
35+
* @build TestTypedef
36+
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestTypedef
37+
*/
38+
/*
39+
* @test id=sources
40+
* @library /lib
41+
* @run main/othervm JtregJextractSources -t test.jextract.clinit -Djextract.decls.per.header=1 clinit_typedef.h
42+
* @build TestTypedef
43+
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestTypedef
44+
*/
45+
public class TestTypedef {
46+
47+
@Test
48+
public void TestTypedef() {
49+
ValueLayout layout = clinit_typedef_h.C_INT;
50+
assertNotNull(layout);
51+
assertEquals(layout, clinit_typedef_h.one);
52+
assertEquals(layout, clinit_typedef_h.two);
53+
assertEquals(layout, clinit_typedef_h.three);
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 only, as
6+
* published by the Free Software Foundation.
7+
*
8+
* This code is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
* version 2 for more details (a copy is included in the LICENSE file that
12+
* accompanied this code).
13+
*
14+
* You should have received a copy of the GNU General Public License version
15+
* 2 along with this work; if not, write to the Free Software Foundation,
16+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*
18+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19+
* or visit www.oracle.com if you need additional information or have any
20+
* questions.
21+
*/
22+
23+
#ifdef _WIN64
24+
#define EXPORT __declspec(dllexport)
25+
#else
26+
#define EXPORT
27+
#endif
28+
29+
EXPORT int global1;
30+
EXPORT int global2;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 only, as
6+
* published by the Free Software Foundation.
7+
*
8+
* This code is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
* version 2 for more details (a copy is included in the LICENSE file that
12+
* accompanied this code).
13+
*
14+
* You should have received a copy of the GNU General Public License version
15+
* 2 along with this work; if not, write to the Free Software Foundation,
16+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*
18+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19+
* or visit www.oracle.com if you need additional information or have any
20+
* questions.
21+
*/
22+
23+
struct Point {
24+
int x;
25+
int y;
26+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
*
4+
* This code is free software; you can redistribute it and/or modify it
5+
* under the terms of the GNU General Public License version 2 only, as
6+
* published by the Free Software Foundation.
7+
*
8+
* This code is distributed in the hope that it will be useful, but WITHOUT
9+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11+
* version 2 for more details (a copy is included in the LICENSE file that
12+
* accompanied this code).
13+
*
14+
* You should have received a copy of the GNU General Public License version
15+
* 2 along with this work; if not, write to the Free Software Foundation,
16+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17+
*
18+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19+
* or visit www.oracle.com if you need additional information or have any
20+
* questions.
21+
*/
22+
23+
typedef int one;
24+
typedef one two;
25+
typedef two three;

‎test/jtreg/generator/packed/TestPackedStructs.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
/*
4141
* @test id=sources
4242
* @library /lib
43-
* @run main/othervm JtregJextractSources -l Func -t test.jextract.packedstructs packedstructs.h
43+
* @run main/othervm JtregJextractSources -t test.jextract.packedstructs packedstructs.h
4444
* @build TestPackedStructs
4545
* @run testng/othervm --enable-native-access=ALL-UNNAMED TestPackedStructs
4646
*/

‎test/lib/testlib/JextractToolRunner.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,15 @@ protected Method checkMethod(Class<?> cls, String name, MethodType type) {
235235
protected Method checkMethod(Class<?> cls, String name, Class<?> returnType, Class<?>... args) {
236236
Method m = findMethod(cls, name, args);
237237
assertNotNull(m);
238-
assertEquals(m.getReturnType(), returnType);
238+
assertTrue(returnType.isAssignableFrom(m.getReturnType())); // tolerate more specific type
239239
assertEquals(m.getParameterTypes(), args);
240240
return m;
241241
}
242242

243243
protected static MemoryLayout findLayout(Class<?> cls, String name) {
244244
Method method = findMethod(cls, name + "$LAYOUT");
245245
assertNotNull(method);
246-
assertEquals(method.getReturnType(), MemoryLayout.class);
246+
assertTrue(MemoryLayout.class.isAssignableFrom(method.getReturnType()));
247247
try {
248248
return (MemoryLayout)method.invoke(null);
249249
} catch (Exception exp) {

‎test/testng/org/openjdk/jextract/test/toolprovider/TestClassGeneration.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,8 @@ public void testGlobal(String name, Class<?> expectedType, MemoryLayout expected
170170
Method addr_getter = checkMethod(cls, name + "$SEGMENT", MemorySegment.class);
171171
MemorySegment segment = (MemorySegment)addr_getter.invoke(null);
172172

173-
Method vh_getter = checkMethod(cls, name + "$VH", VarHandle.class);
174-
VarHandle vh = (VarHandle) vh_getter.invoke(null);
175-
assertEquals(vh.varType(), expectedType);
176-
assertEquals(vh.get(segment, 0L), expectedValue);
173+
Method getter = checkMethod(cls, name + "$get", expectedType);
174+
assertEquals(getter.invoke(segment), expectedValue);
177175

178176
checkMethod(cls, name + "$get", expectedType);
179177
checkMethod(cls, name + "$set", void.class, expectedType);

0 commit comments

Comments
 (0)
Please sign in to comment.