Skip to content

Commit fd13e1c

Browse files
committed
8358801: javac produces class that does not pass verifier.
Reviewed-by: mcimadamore, liach
1 parent 6c9236c commit fd13e1c

File tree

2 files changed

+144
-0
lines changed
  • src/jdk.compiler/share/classes/com/sun/tools/javac/jvm
  • test/langtools/tools/javac/patterns

2 files changed

+144
-0
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,13 +756,25 @@ public CondItem genCond(JCTree _tree, boolean markBranches) {
756756
}
757757
CondItem result = genCond(tree.expr, markBranches);
758758
code.endScopes(limit);
759+
//make sure variables defined in the let expression are not included
760+
//in the defined variables for jumps that go outside of this let
761+
//expression:
762+
undefineVariablesInChain(result.falseJumps, limit);
763+
undefineVariablesInChain(result.trueJumps, limit);
759764
return result;
760765
} else {
761766
CondItem result = genExpr(_tree, syms.booleanType).mkCond();
762767
if (markBranches) result.tree = _tree;
763768
return result;
764769
}
765770
}
771+
//where:
772+
private void undefineVariablesInChain(Chain toClear, int limit) {
773+
while (toClear != null) {
774+
toClear.state.defined.excludeFrom(limit);
775+
toClear = toClear.next;
776+
}
777+
}
766778

767779
public Code getCode() {
768780
return code;
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/**
25+
* @test
26+
* @bug 8358801
27+
* @summary Verify variables introduced by let expressions are correctly undefined
28+
* @library /tools/lib
29+
*/
30+
31+
import java.nio.file.Files;
32+
import java.nio.file.Path;
33+
import java.nio.file.Paths;
34+
import java.util.Arrays;
35+
36+
import javax.tools.JavaFileObject;
37+
import javax.tools.ToolProvider;
38+
39+
import com.sun.source.util.JavacTask;
40+
import java.lang.classfile.ClassFile;
41+
import java.util.ArrayList;
42+
import java.util.List;
43+
import java.util.Objects;
44+
import javax.tools.JavaCompiler;
45+
46+
import toolbox.JavaTask;
47+
import toolbox.Task;
48+
import toolbox.TestRunner;
49+
import toolbox.ToolBox;
50+
51+
public class T8358801 extends TestRunner {
52+
private ToolBox tb;
53+
54+
public static void main(String... args) throws Exception {
55+
new T8358801().runTests();
56+
}
57+
58+
T8358801() {
59+
super(System.err);
60+
tb = new ToolBox();
61+
}
62+
63+
public void runTests() throws Exception {
64+
runTests(m -> new Object[] { Paths.get(m.getName()) });
65+
}
66+
67+
@Test
68+
public void testPatternsInJava(Path base) throws Exception {
69+
Path classes = base.resolve("classes");
70+
71+
List<JavaFileObject> files = new ArrayList<>();
72+
files.add(new ToolBox.JavaSource(
73+
"""
74+
public class Main {
75+
private boolean test(String s, int i) {
76+
if (s.subSequence(0, 1) instanceof Runnable r) {
77+
return true;
78+
}
79+
80+
switch (i) {
81+
case 0:
82+
String clashing1 = null;
83+
String clashing2 = null;
84+
String clashing3 = null;
85+
String clashing4 = null;
86+
return true;
87+
default:
88+
System.out.println("correct");
89+
return true;
90+
}
91+
}
92+
93+
public static void main(String[] args) {
94+
new Main().test("hello", 1);
95+
}
96+
}
97+
"""
98+
));
99+
100+
if (Files.exists(classes)) {
101+
tb.cleanDirectory(classes);
102+
} else {
103+
Files.createDirectories(classes);
104+
}
105+
106+
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
107+
Iterable<String> options = Arrays.asList("-d", classes.toString());
108+
JavacTask task = (JavacTask) compiler.getTask(null, null, null, options, null, files);
109+
110+
task.generate();
111+
112+
List<VerifyError> errors = ClassFile.of().verify(classes.resolve("Main.class"));
113+
114+
if (!errors.isEmpty()) {
115+
throw new AssertionError("verify errors found: " + errors);
116+
}
117+
118+
List<String> log =
119+
new JavaTask(tb).classpath(classes.toString())
120+
.className("Main")
121+
.run()
122+
.writeAll()
123+
.getOutputLines(Task.OutputKind.STDOUT);
124+
List<String> expected = List.of("correct");
125+
126+
if (!Objects.equals(log, expected)) {
127+
throw new AssertionError("Incorrect result, expected: " + expected +
128+
", got: " + log);
129+
}
130+
}
131+
132+
}

0 commit comments

Comments
 (0)