mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-16 10:53:31 +00:00
8168480: Speculative attribution of lambda causes NPE in Flow
Flow attempts to analyze too much of a lambda body during attribution Reviewed-by: vromero
This commit is contained in:
parent
5078ccdb18
commit
d072e7faa4
@ -29,6 +29,7 @@ package com.sun.tools.javac.comp;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Scope.WriteableScope;
|
||||
import com.sun.tools.javac.tree.*;
|
||||
@ -224,7 +225,7 @@ public class Flow {
|
||||
diagHandler = new Log.DiscardDiagnosticHandler(log);
|
||||
}
|
||||
try {
|
||||
new AliveAnalyzer().analyzeTree(env, that, make);
|
||||
new LambdaAliveAnalyzer().analyzeTree(env, that, make);
|
||||
} finally {
|
||||
if (!speculative) {
|
||||
log.popDiagnosticHandler(diagHandler);
|
||||
@ -241,19 +242,7 @@ public class Flow {
|
||||
//related errors, which will allow for more errors to be detected
|
||||
Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
|
||||
try {
|
||||
new AssignAnalyzer() {
|
||||
WriteableScope enclosedSymbols = WriteableScope.create(env.enclClass.sym);
|
||||
@Override
|
||||
public void visitVarDef(JCVariableDecl tree) {
|
||||
enclosedSymbols.enter(tree.sym);
|
||||
super.visitVarDef(tree);
|
||||
}
|
||||
@Override
|
||||
protected boolean trackable(VarSymbol sym) {
|
||||
return enclosedSymbols.includes(sym) &&
|
||||
sym.owner.kind == MTH;
|
||||
}
|
||||
}.analyzeTree(env, that);
|
||||
new LambdaAssignAnalyzer(env).analyzeTree(env, that);
|
||||
LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer();
|
||||
flowAnalyzer.analyzeTree(env, that, make);
|
||||
return flowAnalyzer.inferredThrownTypes;
|
||||
@ -1340,6 +1329,79 @@ public class Flow {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized pass that performs reachability analysis on a lambda
|
||||
*/
|
||||
class LambdaAliveAnalyzer extends AliveAnalyzer {
|
||||
|
||||
boolean inLambda;
|
||||
|
||||
@Override
|
||||
public void visitReturn(JCReturn tree) {
|
||||
//ignore lambda return expression (which might not even be attributed)
|
||||
recordExit(new PendingExit(tree));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLambda(JCLambda tree) {
|
||||
if (inLambda || tree.getBodyKind() == BodyKind.EXPRESSION) {
|
||||
return;
|
||||
}
|
||||
inLambda = true;
|
||||
try {
|
||||
super.visitLambda(tree);
|
||||
} finally {
|
||||
inLambda = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassDef(JCClassDecl tree) {
|
||||
//skip
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized pass that performs DA/DU on a lambda
|
||||
*/
|
||||
class LambdaAssignAnalyzer extends AssignAnalyzer {
|
||||
WriteableScope enclosedSymbols;
|
||||
boolean inLambda;
|
||||
|
||||
LambdaAssignAnalyzer(Env<AttrContext> env) {
|
||||
enclosedSymbols = WriteableScope.create(env.enclClass.sym);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLambda(JCLambda tree) {
|
||||
if (inLambda) {
|
||||
return;
|
||||
}
|
||||
inLambda = true;
|
||||
try {
|
||||
super.visitLambda(tree);
|
||||
} finally {
|
||||
inLambda = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitVarDef(JCVariableDecl tree) {
|
||||
enclosedSymbols.enter(tree.sym);
|
||||
super.visitVarDef(tree);
|
||||
}
|
||||
@Override
|
||||
protected boolean trackable(VarSymbol sym) {
|
||||
return enclosedSymbols.includes(sym) &&
|
||||
sym.owner.kind == MTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassDef(JCClassDecl tree) {
|
||||
//skip
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized pass that performs inference of thrown types for lambdas.
|
||||
*/
|
||||
|
||||
125
langtools/test/tools/javac/lambda/8168480/T8168480.java
Normal file
125
langtools/test/tools/javac/lambda/8168480/T8168480.java
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 8168480
|
||||
* @summary Speculative attribution of lambda causes NPE in Flow
|
||||
* @compile T8168480.java
|
||||
*/
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class T8168480 {
|
||||
void f(Runnable r) { }
|
||||
void s(Supplier<Runnable> r) { }
|
||||
|
||||
private void testVoid(boolean cond) {
|
||||
f(() ->
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}.run());
|
||||
|
||||
f(() ->
|
||||
f(() -> {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}));
|
||||
|
||||
f(() -> {
|
||||
if (cond) {
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}.run();
|
||||
} else {
|
||||
f(() -> {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void testReturn(boolean cond) {
|
||||
s(() ->
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
s(() ->
|
||||
() -> {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
s(() -> {
|
||||
if (cond) {
|
||||
return new Runnable() {
|
||||
public void run() {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return () -> {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
s(() -> {
|
||||
return cond ?
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} : () -> {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
s(() -> cond ?
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} : () -> {
|
||||
switch (42) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
12
langtools/test/tools/javac/lambda/8168480/T8168480b.java
Normal file
12
langtools/test/tools/javac/lambda/8168480/T8168480b.java
Normal file
@ -0,0 +1,12 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8168480
|
||||
* @summary Speculative attribution of lambda causes NPE in Flow
|
||||
* @compile/fail/ref=T8168480b.out -XDrawDiagnostics T8168480b.java
|
||||
*/
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class T8168480b {
|
||||
Supplier<Runnable> ssr = () -> () -> { while (true); System.err.println("Hello"); };
|
||||
}
|
||||
2
langtools/test/tools/javac/lambda/8168480/T8168480b.out
Normal file
2
langtools/test/tools/javac/lambda/8168480/T8168480b.out
Normal file
@ -0,0 +1,2 @@
|
||||
T8168480b.java:11:57: compiler.err.unreachable.stmt
|
||||
1 error
|
||||
Loading…
x
Reference in New Issue
Block a user