Skip to content

Commit 2f20b0d

Browse files
committed
8273039: JShell crashes when naming variable or method "abstract" or "strictfp"
Reviewed-by: vromero
1 parent f34f119 commit 2f20b0d

File tree

3 files changed

+182
-1
lines changed

3 files changed

+182
-1
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5098,6 +5098,14 @@ public void visitAnnotation(JCAnnotation tree) {
50985098
Assert.error("should be handled in annotate");
50995099
}
51005100

5101+
@Override
5102+
public void visitModifiers(JCModifiers tree) {
5103+
//error recovery only:
5104+
Assert.check(resultInfo.pkind == KindSelector.ERR);
5105+
5106+
attribAnnotationTypes(tree.annotations, env);
5107+
}
5108+
51015109
public void visitAnnotatedType(JCAnnotatedType tree) {
51025110
attribAnnotationTypes(tree.annotations, env);
51035111
Type underlyingType = attribType(tree.underlyingType, env);

test/langtools/jdk/jshell/ErrorRecoveryTest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
/*
2525
* @test
26-
* @bug 8270139
26+
* @bug 8270139 8273039
2727
* @summary Verify error recovery in JShell
2828
* @modules jdk.compiler/com.sun.tools.javac.api
2929
* jdk.compiler/com.sun.tools.javac.main
@@ -37,6 +37,7 @@
3737
import org.testng.annotations.Test;
3838
import static jdk.jshell.Snippet.Status.NONEXISTENT;
3939
import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED;
40+
import static jdk.jshell.Snippet.Status.REJECTED;
4041

4142
@Test
4243
public class ErrorRecoveryTest extends KullaTesting {
@@ -49,4 +50,11 @@ public void testExceptionErrors() {
4950
""",
5051
ste(MAIN_SNIPPET, NONEXISTENT, RECOVERABLE_NOT_DEFINED, false, null));
5152
}
53+
54+
public void testBrokenName() {
55+
assertEval("int strictfp = 0;",
56+
DiagCheck.DIAG_ERROR,
57+
DiagCheck.DIAG_IGNORE,
58+
ste(MAIN_SNIPPET, NONEXISTENT, REJECTED, false, null));
59+
}
5260
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Copyright (c) 2021, 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 8273039
27+
* @summary Verify error recovery in Attr
28+
* @library /tools/lib
29+
* @modules jdk.compiler/com.sun.tools.javac.api
30+
* jdk.compiler/com.sun.tools.javac.main
31+
* jdk.compiler/com.sun.tools.javac.util
32+
* @build toolbox.ToolBox toolbox.JavacTask
33+
* @run main AttrRecoveryTest
34+
*/
35+
36+
import com.sun.source.tree.AnnotationTree;
37+
import com.sun.source.tree.CompilationUnitTree;
38+
import com.sun.source.tree.ErroneousTree;
39+
import com.sun.source.util.TaskEvent;
40+
import com.sun.source.util.TaskListener;
41+
import com.sun.source.util.TreePath;
42+
import com.sun.source.util.TreePathScanner;
43+
import com.sun.source.util.Trees;
44+
import java.nio.file.Files;
45+
import java.nio.file.Path;
46+
import java.nio.file.Paths;
47+
import java.util.List;
48+
import javax.lang.model.element.Element;
49+
50+
import toolbox.TestRunner;
51+
import toolbox.JavacTask;
52+
import toolbox.Task;
53+
import toolbox.ToolBox;
54+
55+
public class AttrRecoveryTest extends TestRunner {
56+
57+
ToolBox tb;
58+
59+
public static void main(String... args) throws Exception {
60+
new AttrRecoveryTest().runTests();
61+
}
62+
63+
AttrRecoveryTest() {
64+
super(System.err);
65+
tb = new ToolBox();
66+
}
67+
68+
public void runTests() throws Exception {
69+
runTests(m -> new Object[] { Paths.get(m.getName()) });
70+
}
71+
72+
@Test
73+
public void testModifiers(Path base) throws Exception {
74+
record TestCase(String name, String source, String expectedAnnotation, String... errors) {}
75+
TestCase[] tests = new TestCase[] {
76+
new TestCase("a",
77+
"""
78+
public class Test {
79+
Object i () { return int strictfp @Deprecated = 0; }
80+
}
81+
""",
82+
"java.lang.Deprecated",
83+
"Test.java:2:30: compiler.err.dot.class.expected",
84+
"Test.java:2:51: compiler.err.expected4: class, interface, enum, record",
85+
"Test.java:2:26: compiler.err.unexpected.type: kindname.value, kindname.class",
86+
"3 errors"),
87+
new TestCase("b",
88+
"""
89+
public class Test {
90+
Object i () { return int strictfp = 0; }
91+
}
92+
""",
93+
null,
94+
"Test.java:2:30: compiler.err.dot.class.expected",
95+
"Test.java:2:39: compiler.err.expected4: class, interface, enum, record",
96+
"Test.java:2:26: compiler.err.unexpected.type: kindname.value, kindname.class",
97+
"3 errors")
98+
};
99+
for (TestCase test : tests) {
100+
Path current = base.resolve("" + test.name);
101+
Path src = current.resolve("src");
102+
Path classes = current.resolve("classes");
103+
tb.writeJavaFiles(src,
104+
test.source);
105+
106+
Files.createDirectories(classes);
107+
108+
var log =
109+
new JavacTask(tb)
110+
.options("-XDrawDiagnostics",
111+
"-XDshould-stop.at=FLOW",
112+
"-Xlint:-preview")
113+
.outdir(classes)
114+
.files(tb.findJavaFiles(src))
115+
.callback(t -> {
116+
t.addTaskListener(new TaskListener() {
117+
CompilationUnitTree parsed;
118+
@Override
119+
public void finished(TaskEvent e) {
120+
switch (e.getKind()) {
121+
case PARSE -> parsed = e.getCompilationUnit();
122+
case ANALYZE ->
123+
checkAnnotationsValid(t, parsed, test.expectedAnnotation);
124+
}
125+
}
126+
});
127+
})
128+
.run(Task.Expect.FAIL, 1)
129+
.writeAll()
130+
.getOutputLines(Task.OutputKind.DIRECT);
131+
if (!List.of(test.errors).equals(log)) {
132+
throw new AssertionError("Incorrect errors, expected: " + List.of(test.errors) +
133+
", actual: " + log);
134+
}
135+
}
136+
}
137+
138+
private void checkAnnotationsValid(com.sun.source.util.JavacTask task,
139+
CompilationUnitTree cut,
140+
String expected) {
141+
boolean[] foundAnnotation = new boolean[1];
142+
Trees trees = Trees.instance(task);
143+
144+
new TreePathScanner<Void, Void>() {
145+
@Override
146+
public Void visitAnnotation(AnnotationTree node, Void p) {
147+
TreePath typePath = new TreePath(getCurrentPath(), node.getAnnotationType());
148+
Element el = trees.getElement(typePath);
149+
if (el == null || !el.equals(task.getElements().getTypeElement(expected))) {
150+
throw new AssertionError();
151+
}
152+
foundAnnotation[0] = true;
153+
return super.visitAnnotation(node, p);
154+
}
155+
156+
@Override
157+
public Void visitErroneous(ErroneousTree node, Void p) {
158+
return scan(node.getErrorTrees(), p);
159+
}
160+
}.scan(cut, null);
161+
if (foundAnnotation[0] ^ (expected != null)) {
162+
throw new AssertionError();
163+
}
164+
}
165+
}

0 commit comments

Comments
 (0)