This commit is contained in:
Jesper Wilhelmsson 2020-06-19 00:30:46 +02:00
commit a16994ff7b
30 changed files with 851 additions and 104 deletions

View File

@ -640,4 +640,5 @@ f143729ca00ec14a98ea5c7f73acba88da97746e jdk-15+23
93813843680bbe1b7efbca56c03fd137f20a2c31 jdk-16+0
93813843680bbe1b7efbca56c03fd137f20a2c31 jdk-15+27
4a485c89d5a08b495961835f5308a96038678aeb jdk-16+1
06c9f89459daba98395fad726100feb44f89ba71 jdk-15+28
bcbe7b8a77b8971bc221c0be1bd2abb6fb68c2d0 jdk-16+2

View File

@ -2555,7 +2555,7 @@ JVM_ENTRY(void, JVM_RegisterWhiteBoxMethods(JNIEnv* env, jclass wbclass))
{
if (WhiteBoxAPI) {
// Make sure that wbclass is loaded by the null classloader
InstanceKlass* ik = InstanceKlass::cast(JNIHandles::resolve(wbclass)->klass());
InstanceKlass* ik = InstanceKlass::cast(java_lang_Class::as_Klass(JNIHandles::resolve(wbclass)));
Handle loader(THREAD, ik->class_loader());
if (loader.is_null()) {
WhiteBox::register_methods(env, wbclass, thread, methods, sizeof(methods) / sizeof(methods[0]));

View File

@ -548,6 +548,9 @@ public class TypeAnnotations {
*/
private Type rewriteArrayType(ArrayType type, List<TypeCompound> annotations, TypeAnnotationPosition pos) {
ArrayType tomodify = new ArrayType(type);
if (type.isVarargs()) {
tomodify = tomodify.makeVarargs();
}
ArrayType res = tomodify;
List<TypePathEntry> loc = List.nil();

View File

@ -3040,7 +3040,14 @@ public class Attr extends JCTree.Visitor {
} finally {
localEnv.info.scope.leave();
if (needsRecovery) {
attribTree(that, env, recoveryInfo);
Type prevResult = result;
try {
attribTree(that, env, recoveryInfo);
} finally {
if (result == Type.recoveryType) {
result = prevResult;
}
}
}
}
}

View File

@ -221,17 +221,6 @@ public class DocCommentParser {
}
break;
case '>':
newline = false;
addPendingText(trees, bp - 1);
trees.add(m.at(bp).newErroneousTree(newString(bp, bp + 1), diagSource, "dc.bad.gt"));
nextChar();
if (textStart == -1) {
textStart = bp;
lastNonWhite = -1;
}
break;
case '{':
inlineTag(trees);
break;

View File

@ -3140,9 +3140,6 @@ compiler.misc.where.description.intersection.1=\
compiler.err.dc.bad.entity=\
bad HTML entity
compiler.err.dc.bad.gt=\
bad use of ''>''
compiler.err.dc.bad.inline.tag=\
incorrect use of inline tag

View File

@ -40,6 +40,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.imageio.ImageIO;
@ -250,9 +251,14 @@ final class DesktopIntegration {
data.put("APPLICATION_ICON",
iconFile != null ? iconFile.installPath().toString() : null);
data.put("DEPLOY_BUNDLE_CATEGORY", MENU_GROUP.fetchFrom(params));
data.put("APPLICATION_LAUNCHER",
thePackage.installedApplicationLayout().launchersDirectory().resolve(
LinuxAppImageBuilder.getLauncherName(params)).toString());
String appLauncher = thePackage.installedApplicationLayout().launchersDirectory().resolve(
LinuxAppImageBuilder.getLauncherName(params)).toString();
if (Pattern.compile("\\s").matcher(appLauncher).find()) {
// Path contains whitespace(s). Enclose in double quotes.
appLauncher = "\"" + appLauncher + "\"";
}
data.put("APPLICATION_LAUNCHER", appLauncher);
return data;
}

View File

@ -0,0 +1,86 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package org.graalvm.compiler.core.test;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.options.OptionValues;
import org.junit.Test;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class DeepUnrollingTest extends SubprocessTest {
public static void loops() {
for (int i = 0; i < 6; i++) {
for (int n = 2; n < 30; n++) {
for (int j = 1; j <= n; j++) {
for (int k = 1; k <= j; k++) {
// nop
}
}
}
}
}
public static int reference(int a, int n) {
int v = a;
for (int i = 0; i < n; i++) {
if (v % 2 == 0) {
v = v / 2;
} else {
v = 3 * v + 1;
}
}
return v;
}
public void loopTest() {
// warmup
time("reference");
time("loops");
long reference = time("reference");
long loops = time("loops");
// observed ratio is ~20-30x. Pathological case before fix was ~300x
assertTrue("Compilation of the loop nest is too slow", loops < reference * 45);
}
public long time(String methodName) {
ResolvedJavaMethod method = getResolvedJavaMethod(methodName);
OptionValues options = new OptionValues(getInitialOptions(),
GraalOptions.FullUnroll, true);
long start = System.nanoTime();
getCode(method, null, true, false, options);
long end = System.nanoTime();
return TimeUnit.NANOSECONDS.toMillis(end - start);
}
@Test
public void test() throws IOException, InterruptedException {
launchSubprocess(this::loopTest);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -24,6 +24,11 @@
package org.graalvm.compiler.loop.phases;
import java.util.Comparator;
import java.util.List;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import org.graalvm.compiler.core.common.GraalOptions;
import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugContext;
@ -32,11 +37,24 @@ import org.graalvm.compiler.loop.LoopPolicies;
import org.graalvm.compiler.loop.LoopsData;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.spi.CoreProviders;
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
public class LoopFullUnrollPhase extends LoopPhase<LoopPolicies> {
public static class Options {
@Option(help = "", type = OptionType.Expert) public static final OptionKey<Integer> FullUnrollMaxApplication = new OptionKey<>(60);
}
private static final CounterKey FULLY_UNROLLED_LOOPS = DebugContext.counter("FullUnrolls");
public static final Comparator<LoopEx> LOOP_COMPARATOR;
static {
ToDoubleFunction<LoopEx> loopFreq = e -> e.loop().getHeader().getFirstPredecessor().getRelativeFrequency();
ToIntFunction<LoopEx> loopDepth = e -> e.loop().getDepth();
LOOP_COMPARATOR = Comparator.comparingDouble(loopFreq).thenComparingInt(loopDepth).reversed();
}
private final CanonicalizerPhase canonicalizer;
public LoopFullUnrollPhase(CanonicalizerPhase canonicalizer, LoopPolicies policies) {
@ -50,11 +68,14 @@ public class LoopFullUnrollPhase extends LoopPhase<LoopPolicies> {
DebugContext debug = graph.getDebug();
if (graph.hasLoops()) {
boolean peeled;
int applications = 0;
do {
peeled = false;
final LoopsData dataCounted = new LoopsData(graph);
dataCounted.detectedCountedLoops();
for (LoopEx loop : dataCounted.countedLoops()) {
List<LoopEx> countedLoops = dataCounted.countedLoops();
countedLoops.sort(LOOP_COMPARATOR);
for (LoopEx loop : countedLoops) {
if (getPolicies().shouldFullUnroll(loop)) {
debug.log("FullUnroll %s", loop);
LoopTransformations.fullUnroll(loop, context, canonicalizer);
@ -65,7 +86,8 @@ public class LoopFullUnrollPhase extends LoopPhase<LoopPolicies> {
}
}
dataCounted.deleteUnusedNodes();
} while (peeled);
applications++;
} while (peeled && applications < Options.FullUnrollMaxApplication.getValue(graph.getOptions()));
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 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
@ -25,8 +25,6 @@
package org.graalvm.compiler.loop;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import jdk.internal.vm.compiler.collections.EconomicMap;
@ -92,8 +90,8 @@ public class LoopsData {
return loops;
}
public Collection<LoopEx> countedLoops() {
List<LoopEx> counted = new LinkedList<>();
public List<LoopEx> countedLoops() {
List<LoopEx> counted = new ArrayList<>();
for (LoopEx loop : loops()) {
if (loop.isCounted()) {
counted.add(loop);

View File

@ -49,6 +49,8 @@ import javax.lang.model.element.PackageElement;
import javax.tools.FileObject;
import javax.tools.JavaFileManager.Location;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -145,6 +147,15 @@ public class DocFilesHandlerImpl implements DocFilesHandler {
return;
}
for (DocFile srcfile: srcdir.list()) {
// ensure that the name is a valid component in an eventual full path
// and so avoid an equivalent check lower down in the file manager
// that throws IllegalArgumentException
if (!isValidFilename(srcfile)) {
configuration.messages.warning("doclet.Copy_Ignored_warning",
srcfile.getPath());
continue;
}
DocFile destfile = dstdir.resolve(srcfile.getName());
if (srcfile.isFile()) {
if (destfile.exists() && !first) {
@ -169,6 +180,16 @@ public class DocFilesHandlerImpl implements DocFilesHandler {
}
}
private boolean isValidFilename(DocFile f) {
try {
String n = f.getName();
URI u = new URI(n);
return u.getPath().equals(n);
} catch (URISyntaxException e) {
return false;
}
}
private void handleHtmlFile(DocFile srcfile, DocPath dstPath) throws DocFileIOException {
Utils utils = configuration.utils;
FileObject fileObject = srcfile.getFileObject();

View File

@ -55,6 +55,7 @@ Please file a bug against the javadoc tool via the Java bug reporting page\n\
for duplicates. Include error messages and the following diagnostic in your report. Thank you.
doclet.File_not_found=File not found: {0}
doclet.Copy_Overwrite_warning=File {0} not copied to {1} due to existing file with same name...
doclet.Copy_Ignored_warning=File {0} not copied: invalid name
doclet.Copying_File_0_To_Dir_1=Copying file {0} to directory {1}...
doclet.Copying_File_0_To_File_1=Copying file {0} to file {1}...
doclet.No_Public_Classes_To_Document=No public or protected classes found to document.

View File

@ -28,7 +28,19 @@ package gc.z;
* @requires vm.gc.Z & !vm.graal.enabled
* @summary Test ZGC uncommit unused memory
* @run main/othervm -XX:+UseZGC -Xlog:gc*,gc+heap=debug,gc+stats=off -Xms128M -Xmx512M -XX:ZUncommitDelay=10 gc.z.TestUncommit true 2
*/
/*
* @test TestUncommit
* @requires vm.gc.Z & !vm.graal.enabled
* @summary Test ZGC uncommit unused memory
* @run main/othervm -XX:+UseZGC -Xlog:gc*,gc+heap=debug,gc+stats=off -Xms512M -Xmx512M -XX:ZUncommitDelay=10 gc.z.TestUncommit false 1
*/
/*
* @test TestUncommit
* @requires vm.gc.Z & !vm.graal.enabled
* @summary Test ZGC uncommit unused memory
* @run main/othervm -XX:+UseZGC -Xlog:gc*,gc+heap=debug,gc+stats=off -Xms128M -Xmx512M -XX:ZUncommitDelay=10 -XX:-ZUncommit gc.z.TestUncommit false 1
*/

View File

@ -30,12 +30,12 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import org.testng.annotations.Test;
import static java.lang.System.out;
import static org.testng.Assert.assertEquals;
@ -116,13 +116,12 @@ public class StreamRefTest {
public void basicRefWithInvalidA() throws Exception {
out.println("\n---");
var a = new A(3);
Field f = A.class.getDeclaredField("x");
f.setAccessible(true);
f.set(a, -3); // a "bad" value
var b = new B(a);
assert a.x() == -3;
var byteStream = serialize(a, b);
var bytes = serializeToBytes(a, b);
// injects a bad (negative) value for field x (of record A), in the stream
updateIntValue(3, -3, bytes, 40);
var byteStream = new ObjectInputStream(new ByteArrayInputStream(bytes));
InvalidObjectException ioe = expectThrows(IOE, () -> deserializeOne(byteStream));
out.println("caught expected IOE: " + ioe);
@ -138,13 +137,12 @@ public class StreamRefTest {
public void reverseBasicRefWithInvalidA() throws Exception {
out.println("\n---");
var a = new A(3);
Field f = A.class.getDeclaredField("x");
f.setAccessible(true);
f.set(a, -3); // a "bad" value
var b = new B(a);
assert a.x() == -3;
var byteStream = serialize(b, a);
var bytes = serializeToBytes(b, a);
// injects a bad (negative) value for field x (of record A), in the stream
updateIntValue(3, -3, bytes, 96);
var byteStream = new ObjectInputStream(new ByteArrayInputStream(bytes));
InvalidObjectException ioe = expectThrows(IOE, () -> deserializeOne(byteStream));
out.println("caught expected IOE: " + ioe);
@ -209,14 +207,35 @@ public class StreamRefTest {
// ---
static void assertExpectedIntValue(int expectedValue, byte[] bytes, int offset)
throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(bytes, offset, 4);
DataInputStream dis = new DataInputStream(bais);
assertEquals(dis.readInt(), expectedValue);
}
static void updateIntValue(int expectedValue, int newValue, byte[] bytes, int offset)
throws IOException
{
assertExpectedIntValue(expectedValue, bytes, offset);
bytes[offset + 0] = (byte)((newValue >>> 24) & 0xFF);
bytes[offset + 1] = (byte)((newValue >>> 16) & 0xFF);
bytes[offset + 2] = (byte)((newValue >>> 8) & 0xFF);
bytes[offset + 3] = (byte)((newValue >>> 0) & 0xFF);
assertExpectedIntValue(newValue, bytes, offset);
}
static ObjectInputStream serialize(Object... objs) throws IOException {
return new ObjectInputStream(new ByteArrayInputStream(serializeToBytes(objs)));
}
static byte[] serializeToBytes(Object... objs) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
for (Object obj : objs)
oos.writeObject(obj);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
return new ObjectInputStream(bais);
return baos.toByteArray();
}
@SuppressWarnings("unchecked")

View File

@ -28,6 +28,7 @@ import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -332,6 +333,73 @@ public class LinuxHelper {
}
});
});
test.addInstallVerifier(cmd -> {
// Verify .desktop files.
try (var files = Files.walk(cmd.appLayout().destktopIntegrationDirectory(), 1)) {
List<Path> desktopFiles = files
.filter(path -> path.getFileName().toString().endsWith(".desktop"))
.collect(Collectors.toList());
if (!integrated) {
TKit.assertStringListEquals(List.of(),
desktopFiles.stream().map(Path::toString).collect(
Collectors.toList()),
"Check there are no .desktop files in the package");
}
for (var desktopFile : desktopFiles) {
verifyDesktopFile(cmd, desktopFile);
}
}
});
}
private static void verifyDesktopFile(JPackageCommand cmd, Path desktopFile)
throws IOException {
TKit.trace(String.format("Check [%s] file BEGIN", desktopFile));
List<String> lines = Files.readAllLines(desktopFile);
TKit.assertEquals("[Desktop Entry]", lines.get(0), "Check file header");
Map<String, String> data = lines.stream()
.skip(1)
.peek(str -> TKit.assertTextStream("=").predicate(String::contains).apply(Stream.of(str)))
.map(str -> {
String components[] = str.split("=(?=.+)");
if (components.length == 1) {
return Map.entry(str.substring(0, str.length() - 1), "");
}
return Map.entry(components[0], components[1]);
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> {
TKit.assertUnexpected("Multiple values of the same key");
return null;
}));
final Set<String> mandatoryKeys = new HashSet(Set.of("Name", "Comment",
"Exec", "Icon", "Terminal", "Type", "Categories"));
mandatoryKeys.removeAll(data.keySet());
TKit.assertTrue(mandatoryKeys.isEmpty(), String.format(
"Check for missing %s keys in the file", mandatoryKeys));
for (var e : Map.of("Type", "Application", "Terminal", "false").entrySet()) {
String key = e.getKey();
TKit.assertEquals(e.getValue(), data.get(key), String.format(
"Check value of [%s] key", key));
}
// Verify value of `Exec` property in .desktop files are escaped if required
String launcherPath = data.get("Exec");
if (Pattern.compile("\\s").matcher(launcherPath).find()) {
TKit.assertTrue(launcherPath.startsWith("\"")
&& launcherPath.endsWith("\""),
"Check path to the launcher is enclosed in double quotes");
launcherPath = launcherPath.substring(1, launcherPath.length() - 1);
}
Stream.of(launcherPath, data.get("Icon"))
.map(Path::of)
.map(cmd::pathToUnpackedPackageFile)
.forEach(TKit::assertFileExists);
TKit.trace(String.format("Check [%s] file END", desktopFile));
}
static void initFileAssociationsTestFile(Path testFile) {

View File

@ -166,6 +166,8 @@ public class ShortcutHintTest {
"Exec=APPLICATION_LAUNCHER",
"Terminal=false",
"Type=Application",
"Comment=",
"Icon=APPLICATION_ICON",
"Categories=DEPLOY_BUNDLE_CATEGORY",
expectedVersionString
));

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 8008949 8234051
* @bug 8008949 8234051 8245696
* @summary doclet crashes if HTML files in module doc-files directories
* @library /tools/lib ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@ -33,6 +33,8 @@
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import toolbox.ToolBox;
import javadoc.tester.JavadocTester;
@ -134,4 +136,43 @@ public class TestDocFiles extends JavadocTester {
checkOutput("m/p/doc-files/pkg-file.html", true,
"Package HTML file");
}
@Test
public void testBadFiles(Path base) throws IOException {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"package p; public class C { }");
Path df = src.resolve("p").resolve("doc-files");
// note that '?' may be an illegal filename character on some systems (e.g. Windows)
List<String> cases = List.of("valid", "#bad#", "#bad", "bad#bad", "bad?bad");
List<Path> files = new ArrayList<>();
for (String s : cases) {
try {
Path f = df.resolve(s);
tb.writeFile(f, "dummy contents");
files.add(f);
} catch (Throwable t) {
out.println("Cannot write doc-file " + s);
}
}
javadoc("-d", base.resolve("out").toString(),
"--source-path", src.toString(),
"p");
checkExit(Exit.OK);
// only check for those files
for (Path f : files) {
if (f.getFileName().toString().contains("valid")) {
checkOutput("p/doc-files/" + f.getFileName(), true,
"dummy contents");
} else {
// be careful handing file separator characters in the message
checkOutput(Output.OUT, true,
"warning - File " + f + " not copied: invalid name");
}
}
}
}

View File

@ -39,6 +39,8 @@ public class TestJavaFX extends JavadocTester {
public static void main(String... args) throws Exception {
TestJavaFX tester = new TestJavaFX();
tester.setAutomaticCheckAccessibility(false);
tester.setAutomaticCheckLinks(false);
tester.runTests();
}
@ -353,6 +355,6 @@ public class TestJavaFX extends JavadocTester {
checkExit(Exit.OK);
// make sure the doclet indeed emits the warning
checkOutput(Output.OUT, true, "C.java:0: warning - invalid usage of tag >");
checkOutput(Output.OUT, true, "C.java:0: warning - invalid usage of tag <");
}
}

View File

@ -28,7 +28,7 @@ public class C {
/**
* Defines the number of cycles in this animation. The {@code cycleCount}
* may be {@code INDEFINITE} for animations that repeat indefinitely.
* Now we add a > to deliberately cause an Html error.
* Now we add <> to deliberately cause an Html error.
* @defaultValue 11
* @since JavaFX 8.0
*/

View File

@ -46,7 +46,7 @@ public class TestPackageHtml extends JavadocTester {
"-sourcepath", testSrc,
"pkg1");
checkExit(Exit.ERROR);
checkOutput(Output.OUT, true, "package.html:5: error: bad use of '>'");
checkOutput(Output.OUT, true, "package.html:4: error: malformed HTML");
}
// Doclet must handle empty body in package.html, must

View File

@ -1,8 +1,7 @@
<HTML>
<BODY>
<!-- generate a syntax error to verify that the file is parsed -->
<pre>
&lt;opaque value="TRUE"/>
<123 value="TRUE"/>
</pre>
</BODY>
</HTML>

View File

@ -1,10 +1,8 @@
InvalidTag.java:14: error: unknown tag: String
* List<String> list = new ArrayList<>();
^
InvalidTag.java:14: error: malformed HTML
* List<String> list = new ArrayList<>();
^
InvalidTag.java:14: error: bad use of '>'
* List<String> list = new ArrayList<>();
^
3 errors
2 errors

View File

@ -0,0 +1,13 @@
/*
* @test /nodynamiccopyright/
* @bug 8238735
* @summary javac should fail without throwing NPE
* @compile/fail/ref=T8238735.out -XDrawDiagnostics T8238735.java
*/
class T8238735 {
public static void main(String[] args) {
boolean first = true;
first = first ? false : (boolean)(() -> false) ;
}
}

View File

@ -0,0 +1,2 @@
T8238735.java:11:43: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: boolean)
1 error

View File

@ -1,32 +0,0 @@
/*
* Copyright (c) 2012, 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.
*/
// key: compiler.err.dc.bad.gt
// key: compiler.note.note
// key: compiler.note.proc.messager
// run: backdoor
// options: -processor DocCommentProcessor -proc:only
/** > */
class BadGreaterThan { }

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 7021614 8078320
* @bug 7021614 8078320 8247788
* @summary extend com.sun.source API to support parsing javadoc comments
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.file
@ -93,13 +93,8 @@ DocComment[DOC_COMMENT, pos:1
void bad_gt() { }
/*
DocComment[DOC_COMMENT, pos:1
firstSentence: 3
Text[TEXT, pos:1, abc_]
Erroneous[ERRONEOUS, pos:5
code: compiler.err.dc.bad.gt
body: >
]
Text[TEXT, pos:6, _def]
firstSentence: 1
Text[TEXT, pos:1, abc_>_def]
body: empty
block tags: empty
]
@ -111,18 +106,13 @@ DocComment[DOC_COMMENT, pos:1
void bad_chars_start();
/*
DocComment[DOC_COMMENT, pos:1
firstSentence: 5
firstSentence: 3
Text[TEXT, pos:1, abc_]
Erroneous[ERRONEOUS, pos:5
code: compiler.err.dc.malformed.html
body: <
]
Text[TEXT, pos:6, p_123]
Erroneous[ERRONEOUS, pos:11
code: compiler.err.dc.bad.gt
body: >
]
Text[TEXT, pos:12, _def]
Text[TEXT, pos:6, p_123>_def]
body: empty
block tags: empty
]
@ -134,18 +124,13 @@ DocComment[DOC_COMMENT, pos:1
void bad_chars_end();
/*
DocComment[DOC_COMMENT, pos:1
firstSentence: 5
firstSentence: 3
Text[TEXT, pos:1, abc_]
Erroneous[ERRONEOUS, pos:5
code: compiler.err.dc.malformed.html
body: <
]
Text[TEXT, pos:6, /p_123]
Erroneous[ERRONEOUS, pos:12
code: compiler.err.dc.bad.gt
body: >
]
Text[TEXT, pos:13, _def]
Text[TEXT, pos:6, /p_123>_def]
body: empty
block tags: empty
]

View File

@ -1130,6 +1130,26 @@ public class RecordCompilationTests extends CompilationTestCase {
this.args = args;
}
}
""",
"""
record R(@A int... ints) {}
@java.lang.annotation.Target({
java.lang.annotation.ElementType.TYPE_USE,
java.lang.annotation.ElementType.RECORD_COMPONENT})
@interface A {}
""",
"""
record R(@A int... ints) {
R(@A int... ints) {
this.ints = ints;
}
}
@java.lang.annotation.Target({
java.lang.annotation.ElementType.TYPE_USE,
java.lang.annotation.ElementType.RECORD_COMPONENT})
@interface A {}
"""
)) {
assertOK(source);

View File

@ -0,0 +1,487 @@
/*
* 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
* @summary test binary compatibility rules for sealed classes
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* jdk.compiler/com.sun.tools.javac.util
* jdk.compiler/com.sun.tools.javac.code
* jdk.jdeps/com.sun.tools.classfile
* @build toolbox.ToolBox toolbox.JavacTask
* @run main BinaryCompatibilityTests
*/
import java.util.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.IntStream;
import com.sun.tools.classfile.*;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.util.Assert;
import toolbox.TestRunner;
import toolbox.ToolBox;
import toolbox.JavaTask;
import toolbox.JavacTask;
import toolbox.Task;
import toolbox.Task.OutputKind;
import static com.sun.tools.classfile.ConstantPool.*;
public class BinaryCompatibilityTests extends TestRunner {
ToolBox tb;
BinaryCompatibilityTests() {
super(System.err);
tb = new ToolBox();
}
protected void runTests() throws Exception {
runTests(m -> new Object[]{Paths.get(m.getName())});
}
public static void main(String... args) throws Exception {
BinaryCompatibilityTests t = new BinaryCompatibilityTests();
t.runTests();
}
Path[] findJavaFiles(Path... paths) throws IOException {
return tb.findJavaFiles(paths);
}
@Test
public void testCompatibilityAfterMakingSuperclassSealed(Path base) throws Exception {
// sealing a super class which was not sealed, should fail with IncompatibleClassChangeError
testCompatibilityAfterModifyingSupertype(
base,
"""
package pkg;
public class Super {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
public sealed class Super permits Sub1 {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
final class Sub1 extends Super {}
""",
"""
package pkg;
class Sub extends Super {}
""",
true
);
}
@Test
public void testCompatibilityAfterMakingSuperInterfaceSealed(Path base) throws Exception {
// sealing a super interface which was not sealed, should fail with IncompatibleClassChangeError
testCompatibilityAfterModifyingSupertype(
base,
"""
package pkg;
public interface Super {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
public sealed interface Super permits Sub1 {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
final class Sub1 implements Super {}
""",
"""
package pkg;
class Sub implements Super {}
""",
true
);
}
/* 1- compiles the first version of the superclass source code along with the subclass source code
* 2- executes the super class just to make sure that it works
* 3- compiles the second version of the super class along with the class file of the subclass
* 4- executes the super class and makes sure that the VM throws IncompatibleClassChangeError or not
* depending on the shouldFail argument
*/
private void testCompatibilityAfterModifyingSupertype(
Path base,
String superClassCode1,
String superClassCode2,
String subClassCode,
boolean shouldFail) throws Exception {
Path src = base.resolve("src");
Path pkg = src.resolve("pkg");
Path superClass = pkg.resolve("Super");
Path sub = pkg.resolve("Sub");
// super class initially not sealed
tb.writeJavaFiles(superClass, superClassCode1);
tb.writeJavaFiles(sub, subClassCode);
Path out = base.resolve("out");
Files.createDirectories(out);
new JavacTask(tb)
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()))
.outdir(out)
.files(findJavaFiles(pkg))
.run();
// let's execute to check that it's working
String output = new JavaTask(tb)
.vmOptions("--enable-preview")
.classpath(out.toString())
.classArgs("pkg.Super")
.run()
.writeAll()
.getOutput(Task.OutputKind.STDOUT);
// let's first check that it runs wo issues
if (!output.contains("done")) {
throw new AssertionError("execution of Super didn't finish");
}
// now lets change the super class
tb.writeJavaFiles(superClass, superClassCode2);
new JavacTask(tb)
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()))
.classpath(out)
.outdir(out)
.files(findJavaFiles(superClass))
.run();
if (shouldFail) {
// let's now check that there is an IncompatibleClassChangeError
output = new JavaTask(tb)
.vmOptions("--enable-preview")
.classpath(out.toString())
.classArgs("pkg.Super")
.run(Task.Expect.FAIL)
.writeAll()
.getOutput(Task.OutputKind.STDERR);
if (!output.startsWith("Exception in thread \"main\" java.lang.IncompatibleClassChangeError")) {
throw new AssertionError("java.lang.IncompatibleClassChangeError expected");
}
} else {
new JavaTask(tb)
.vmOptions("--enable-preview")
.classpath(out.toString())
.classArgs("pkg.Super")
.run(Task.Expect.SUCCESS);
}
}
@Test
public void testRemoveSealedModifierToClass(Path base) throws Exception {
// should execute without error
testCompatibilityAfterModifyingSupertype(
base,
"""
package pkg;
public sealed class Super permits pkg.Sub {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
public class Super {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
final class Sub extends Super {}
""",
false
);
}
@Test
public void testRemoveSealedModifierToInterface(Path base) throws Exception {
// should execute without error
testCompatibilityAfterModifyingSupertype(
base,
"""
package pkg;
public sealed interface Super permits pkg.Sub {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
public interface Super {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
final class Sub implements Super {}
""",
false
);
}
@Test
public void testAddNonSealedModifierToClass(Path base) throws Exception {
// should execute without error
testCompatibilityOKAfterSubclassChange(
base,
"""
package pkg;
public sealed class Super permits pkg.Sub {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
final class Sub extends Super {}
""",
"""
package pkg;
non-sealed class Sub extends Super {}
"""
);
}
@Test
public void testAddNonSealedModifierToInterface(Path base) throws Exception {
// should execute without error
testCompatibilityOKAfterSubclassChange(
base,
"""
package pkg;
public sealed interface Super permits pkg.Sub {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
final class Sub implements Super {}
""",
"""
package pkg;
non-sealed class Sub implements Super {}
"""
);
}
@Test
public void testRemoveNonSealedModifier(Path base) throws Exception {
// should execute without error
testCompatibilityOKAfterSubclassChange(
base,
"""
package pkg;
public sealed class Super permits pkg.Sub {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
non-sealed class Sub extends Super {}
""",
"""
package pkg;
final class Sub extends Super {}
"""
);
}
@Test
public void testRemoveNonSealedModifierFromInterface(Path base) throws Exception {
// should execute without error
testCompatibilityOKAfterSubclassChange(
base,
"""
package pkg;
public sealed interface Super permits pkg.Sub {
public static void main(String... args) {
pkg.Sub sub = new pkg.Sub();
System.out.println("done");
}
}
""",
"""
package pkg;
non-sealed class Sub implements Super {}
""",
"""
package pkg;
final class Sub implements Super {}
"""
);
}
/* 1- compiles the the superclass source code along with the first version of the subclass source code
* 2- executes the super class just to make sure that it works
* 3- compiles the second version of the subclass along with the class file of the superclass
* 4- executes the super class and makes sure that it executes successfully
*/
private void testCompatibilityOKAfterSubclassChange(
Path base,
String superClassCode,
String subClassCode1,
String subClassCode2) throws Exception {
Path src = base.resolve("src");
Path pkg = src.resolve("pkg");
Path superClass = pkg.resolve("Super");
Path sub = pkg.resolve("Sub");
// super class initially sealed
tb.writeJavaFiles(superClass, superClassCode);
tb.writeJavaFiles(sub, subClassCode1);
Path out = base.resolve("out");
Files.createDirectories(out);
new JavacTask(tb)
.outdir(out)
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()))
.files(findJavaFiles(pkg))
.run();
// let's execute to check that it's working
String output = new JavaTask(tb)
.classpath(out.toString())
.vmOptions("--enable-preview")
.classArgs("pkg.Super")
.run()
.writeAll()
.getOutput(Task.OutputKind.STDOUT);
// let's first check that it runs wo issues
if (!output.contains("done")) {
throw new AssertionError("execution of Super didn't finish");
}
// now lets remove the non-sealed modifier from class Sub
tb.writeJavaFiles(sub, subClassCode2);
new JavacTask(tb)
.options("--enable-preview",
"-source", Integer.toString(Runtime.version().feature()))
.classpath(out)
.outdir(out)
.files(findJavaFiles(sub))
.run();
// should execute without issues
output = new JavaTask(tb)
.vmOptions("--enable-preview")
.classpath(out.toString())
.classArgs("pkg.Super")
.run()
.writeAll()
.getOutput(Task.OutputKind.STDOUT);
// let's first check that it runs wo issues
if (!output.contains("done")) {
throw new AssertionError("execution of Super didn't finish");
}
}
@Test
public void testAfterChangingPermitsClause(Path base) throws Exception {
// the VM will throw IncompatibleClassChangeError
testCompatibilityAfterModifyingSupertype(
base,
"""
package pkg;
public sealed class Super permits pkg.Sub1, Sub2 {
public static void main(String... args) {
pkg.Sub1 sub = new pkg.Sub1();
System.out.println("done");
}
}
final class Sub2 extends Super {}
""",
"""
package pkg;
public sealed class Super permits Sub2 {
public static void main(String... args) {
pkg.Sub1 sub = new pkg.Sub1();
System.out.println("done");
}
}
final class Sub2 extends Super {}
""",
"""
package pkg;
final class Sub1 extends Super {}
""",
true
);
}
}