8271254: javac generates unreachable code when using empty semicolon statement

Reviewed-by: vromero
This commit is contained in:
Guoxiong Li 2021-09-14 14:46:21 +00:00
parent 8974b95886
commit fe89dd3b0d
2 changed files with 101 additions and 9 deletions
src/jdk.compiler/share/classes/com/sun/tools/javac/jvm
test/langtools/tools/javac/T8022186

@ -1510,8 +1510,8 @@ public class Gen extends JCTree.Visitor {
//where
/** Generate code for a try or synchronized statement
* @param body The body of the try or synchronized statement.
* @param catchers The lis of catch clauses.
* @param env the environment current for the body.
* @param catchers The list of catch clauses.
* @param env The current environment of the body.
*/
void genTry(JCTree body, List<JCCatch> catchers, Env<GenContext> env) {
int limit = code.nextreg;
@ -1523,7 +1523,13 @@ public class Gen extends JCTree.Visitor {
code.statBegin(TreeInfo.endPos(body));
genFinalizer(env);
code.statBegin(TreeInfo.endPos(env.tree));
Chain exitChain = code.branch(goto_);
Chain exitChain;
boolean actualTry = env.tree.hasTag(TRY);
if (startpc == endpc && actualTry) {
exitChain = code.branch(dontgoto);
} else {
exitChain = code.branch(goto_);
}
endFinalizerGap(env);
env.info.finalize.afterBody();
boolean hasFinalizer =
@ -1541,7 +1547,7 @@ public class Gen extends JCTree.Visitor {
}
endFinalizerGap(env);
}
if (hasFinalizer) {
if (hasFinalizer && (startpc != endpc || !actualTry)) {
// Create a new register segment to avoid allocating
// the same variables in finalizers and other statements.
code.newRegSegment();

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2021, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 8022186
* @bug 8022186 8271254
* @summary javac generates dead code if a try with an empty body has a finalizer
* @modules jdk.jdeps/com.sun.tools.classfile
* jdk.compiler/com.sun.tools.javac.util
@ -53,8 +53,10 @@ public class DeadCodeGeneratedForEmptyTryTest {
}
void run() throws Exception {
checkClassFile(Paths.get(System.getProperty("test.classes"),
this.getClass().getName() + "$Test.class"));
for (int i = 1; i <= 8; i++) {
checkClassFile(Paths.get(System.getProperty("test.classes"),
this.getClass().getName() + "$Test" + i + ".class"));
}
}
int utf8Index;
@ -62,6 +64,7 @@ public class DeadCodeGeneratedForEmptyTryTest {
ConstantPool constantPool;
void checkClassFile(final Path path) throws Exception {
numberOfRefToStr = 0;
ClassFile classFile = ClassFile.read(
new BufferedInputStream(Files.newInputStream(path)));
constantPool = classFile.constant_pool;
@ -155,9 +158,92 @@ public class DeadCodeGeneratedForEmptyTryTest {
}
public class Test {
public class Test1 {
void methodToLookFor() {
try {
// empty intentionally
} finally {
System.out.println("STR_TO_LOOK_FOR");
}
}
}
public class Test2 {
void methodToLookFor() {
try {
// empty intentionally
} catch (Exception e) {
System.out.println("EXCEPTION");
} finally {
System.out.println("STR_TO_LOOK_FOR");
}
}
}
public class Test3 {
void methodToLookFor() {
try {
; // skip statement intentionally
} finally {
System.out.println("STR_TO_LOOK_FOR");
}
}
}
public class Test4 {
void methodToLookFor() {
try {
; // skip statement intentionally
} catch (Exception e) {
System.out.println("EXCEPTION");
} finally {
System.out.println("STR_TO_LOOK_FOR");
}
}
}
public class Test5 {
void methodToLookFor() {
try {
// empty try statement
try { } finally { }
} finally {
System.out.println("STR_TO_LOOK_FOR");
}
}
}
public class Test6 {
void methodToLookFor() {
try {
// empty try statement
try { } catch (Exception e) { } finally { }
} catch (Exception e) {
System.out.println("EXCEPTION");
} finally {
System.out.println("STR_TO_LOOK_FOR");
}
}
}
public class Test7 {
void methodToLookFor() {
try {
// empty try statement with skip statement
try { ; } finally { }
} finally {
System.out.println("STR_TO_LOOK_FOR");
}
}
}
public class Test8 {
void methodToLookFor() {
try {
// empty try statement with skip statement
try { ; } catch (Exception e) { } finally { }
} catch (Exception e) {
System.out.println("EXCEPTION");
} finally {
System.out.println("STR_TO_LOOK_FOR");
}