8237041: AssertionError in parsing
Avoid parser crash for deeply nested classes without closing braces, improve error recovery for classes without an opening brace. Reviewed-by: vromero
This commit is contained in:
parent
c663323043
commit
0504064717
@ -444,7 +444,7 @@ public class JavacParser implements Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
S.errPos(pos);
|
S.errPos(pos);
|
||||||
if (token.pos == errorPos) {
|
if (token.pos == errorPos && token.kind != EOF) {
|
||||||
//check for a possible infinite loop in parsing:
|
//check for a possible infinite loop in parsing:
|
||||||
Assert.check(count++ < RECOVERY_THRESHOLD);
|
Assert.check(count++ < RECOVERY_THRESHOLD);
|
||||||
} else {
|
} else {
|
||||||
@ -4048,6 +4048,8 @@ public class JavacParser implements Parser {
|
|||||||
skip(false, true, false, false);
|
skip(false, true, false, false);
|
||||||
if (token.kind == LBRACE)
|
if (token.kind == LBRACE)
|
||||||
nextToken();
|
nextToken();
|
||||||
|
else
|
||||||
|
return List.nil();
|
||||||
}
|
}
|
||||||
ListBuffer<JCTree> defs = new ListBuffer<>();
|
ListBuffer<JCTree> defs = new ListBuffer<>();
|
||||||
while (token.kind != RBRACE && token.kind != EOF) {
|
while (token.kind != RBRACE && token.kind != EOF) {
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913 8228451
|
* @bug 7073631 7159445 7156633 8028235 8065753 8205418 8205913 8228451 8237041
|
||||||
* @summary tests error and diagnostics positions
|
* @summary tests error and diagnostics positions
|
||||||
* @author Jan Lahoda
|
* @author Jan Lahoda
|
||||||
* @modules jdk.compiler/com.sun.tools.javac.api
|
* @modules jdk.compiler/com.sun.tools.javac.api
|
||||||
@ -1512,6 +1512,58 @@ public class JavacParserTest extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test //JDK-8237041
|
||||||
|
void testDeepNestingNoClose() throws IOException {
|
||||||
|
//verify that many nested unclosed classes do not crash javac
|
||||||
|
//due to the safety fallback in JavacParser.reportSyntaxError:
|
||||||
|
String code = "package t; class Test {\n";
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
code += "class C" + i + " {\n";
|
||||||
|
}
|
||||||
|
JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, List.of("-XDdev"),
|
||||||
|
null, Arrays.asList(new MyFileObject(code)));
|
||||||
|
Result result = ct.doCall();
|
||||||
|
assertEquals("Expected a (plain) error, got: " + result, result, Result.ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test //JDK-8237041
|
||||||
|
void testErrorRecoveryClassNotBrace() throws IOException {
|
||||||
|
//verify the AST form produced for classes without opening brace
|
||||||
|
//(classes without an opening brace do not nest the upcoming content):
|
||||||
|
String code = """
|
||||||
|
package t;
|
||||||
|
class Test {
|
||||||
|
String.class,
|
||||||
|
String.class,
|
||||||
|
class A
|
||||||
|
public
|
||||||
|
class B
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, List.of("-XDdev"),
|
||||||
|
null, Arrays.asList(new MyFileObject(code)));
|
||||||
|
String ast = ct.parse().iterator().next().toString();
|
||||||
|
String expected = """
|
||||||
|
package t;
|
||||||
|
\n\
|
||||||
|
class Test {
|
||||||
|
String.<error> <error>;
|
||||||
|
\n\
|
||||||
|
class <error> {
|
||||||
|
}
|
||||||
|
\n\
|
||||||
|
class <error> {
|
||||||
|
}
|
||||||
|
\n\
|
||||||
|
class A {
|
||||||
|
}
|
||||||
|
\n\
|
||||||
|
public class B {
|
||||||
|
}
|
||||||
|
}""";
|
||||||
|
assertEquals("Unexpected AST, got:\n" + ast, expected, ast);
|
||||||
|
}
|
||||||
|
|
||||||
void run(String[] args) throws Exception {
|
void run(String[] args) throws Exception {
|
||||||
int passed = 0, failed = 0;
|
int passed = 0, failed = 0;
|
||||||
final Pattern p = (args != null && args.length > 0)
|
final Pattern p = (args != null && args.length > 0)
|
||||||
|
@ -60,9 +60,8 @@ public class T6439826 extends AbstractProcessor {
|
|||||||
System.err.print(s);
|
System.err.print(s);
|
||||||
// Expect the following 2 diagnostics, and no output to log
|
// Expect the following 2 diagnostics, and no output to log
|
||||||
// Foo.java:1: illegal character: \35
|
// Foo.java:1: illegal character: \35
|
||||||
// Foo.java:1: reached end of file while parsing
|
|
||||||
System.err.println(dl.count + " diagnostics; " + s.length() + " characters");
|
System.err.println(dl.count + " diagnostics; " + s.length() + " characters");
|
||||||
if (dl.count != 2 || s.length() != 0)
|
if (dl.count != 1 || s.length() != 0)
|
||||||
throw new AssertionError("unexpected output from compiler");
|
throw new AssertionError("unexpected output from compiler");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ public class RecordCompilationTests extends CompilationTestCase {
|
|||||||
|
|
||||||
public void testMalformedDeclarations() {
|
public void testMalformedDeclarations() {
|
||||||
assertFail("compiler.err.premature.eof", "record R()");
|
assertFail("compiler.err.premature.eof", "record R()");
|
||||||
assertFail("compiler.err.premature.eof", "record R();");
|
assertFail("compiler.err.expected", "record R();");
|
||||||
assertFail("compiler.err.illegal.start.of.type", "record R(,) { }");
|
assertFail("compiler.err.illegal.start.of.type", "record R(,) { }");
|
||||||
assertFail("compiler.err.illegal.start.of.type", "record R((int x)) { }");
|
assertFail("compiler.err.illegal.start.of.type", "record R((int x)) { }");
|
||||||
assertFail("compiler.err.record.header.expected", "record R { }");
|
assertFail("compiler.err.record.header.expected", "record R { }");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user