8233655: NPE at jdk.compiler/com.sun.tools.javac.comp.Flow$FlowAnalyzer.visitApply

Ensuring that errors reported during speculative attribution that belong to a different file are not lost.

Reviewed-by: mcimadamore
This commit is contained in:
Jan Lahoda 2020-01-15 11:31:16 +01:00
parent 006b5e0f96
commit 8787b9a66d
2 changed files with 62 additions and 3 deletions

View File

@ -505,14 +505,15 @@ public class DeferredAttr extends JCTree.Visitor {
/**
* Attribute the given tree, mostly reverting side-effects applied to shared
* compiler state. Exceptions include the ArgumentAttr.argumentTypeCache,
* changes to which may be preserved if localCache is null.
* changes to which may be preserved if localCache is null and errors reported
* outside of the speculatively attributed tree.
*/
<Z> JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo,
Supplier<DiagnosticHandler> diagHandlerCreator, AttributionMode attributionMode,
LocalCacheContext localCache) {
Env<AttrContext> speculativeEnv = env.dup(tree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner)));
speculativeEnv.info.attributionMode = attributionMode;
Log.DiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator != null ? diagHandlerCreator.get() : new DeferredDiagnosticHandler(log);
Log.DiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator != null ? diagHandlerCreator.get() : new DeferredAttrDiagHandler(log, tree);
DeferredCompletionFailureHandler.Handler prevCFHandler = dcfh.setHandler(dcfh.speculativeCodeHandler);
Queues prevQueues = annotate.setQueues(new Queues());
int nwarnings = log.nwarnings;
@ -531,6 +532,35 @@ public class DeferredAttr extends JCTree.Visitor {
}
}
}
//where
static class DeferredAttrDiagHandler extends Log.DeferredDiagnosticHandler {
static class PosScanner extends TreeScanner {
DiagnosticPosition pos;
boolean found = false;
PosScanner(DiagnosticPosition pos) {
this.pos = pos;
}
@Override
public void scan(JCTree tree) {
if (tree != null &&
tree.pos() == pos) {
found = true;
}
super.scan(tree);
}
}
DeferredAttrDiagHandler(Log log, JCTree newTree) {
super(log, d -> {
PosScanner posScanner = new PosScanner(d.getDiagnosticPosition());
posScanner.scan(newTree);
return posScanner.found;
});
}
}
/**
* A deferred context is created on each method check. A deferred context is

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 8177068
* @bug 8177068 8233655
* @summary CompletionFailures occurring during speculative attribution should
* not be lost forever.
* @library /tools/lib
@ -72,6 +72,7 @@ public class NoCompletionFailureSkipOnSpeculativeAttribution {
public static void main(String[] args) throws Exception {
new NoCompletionFailureSkipOnSpeculativeAttribution().test();
new NoCompletionFailureSkipOnSpeculativeAttribution().test8233655();
}
public void test() throws Exception {
@ -101,4 +102,32 @@ public class NoCompletionFailureSkipOnSpeculativeAttribution {
Assert.check(output.equals(expectedOutput));
}
public void test8233655() throws Exception {
ToolBox tb = new ToolBox();
tb.writeJavaFiles(Paths.get("."),
"public class Test {" +
" private <T> T test(Class<?> c) {\n" +
" Class<?> c2 = test(test(Helper.class));\n" +
" return null;\n" +
" }\n" +
"}",
"public class Helper extends Unknown {}");
List<String> output = new JavacTask(tb)
.sourcepath(".")
.options("-XDrawDiagnostics")
.classpath(".")
.files("Test.java")
.run(Task.Expect.FAIL)
.writeAll()
.getOutputLines(Task.OutputKind.DIRECT);
List<String> expectedOutput = List.of(
"Helper.java:1:29: compiler.err.cant.resolve: kindname.class, Unknown, , ",
"1 error"
);
Assert.check(output.equals(expectedOutput));
}
}