diff -r 88502b1cf76f -r 7799a51dbe30 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Mon Sep 09 11:43:16 2019 -0400 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Wed Nov 27 09:00:01 2019 +0100 @@ -255,6 +255,41 @@ } } + public boolean aliveAfter(Env env, JCTree that, TreeMaker make) { + //we need to disable diagnostics temporarily; the problem is that if + //"that" contains e.g. an unreachable statement, an error + //message will be reported and will cause compilation to skip the flow analyis + //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis + //related errors, which will allow for more errors to be detected + Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); + try { + SnippetAliveAnalyzer analyzer = new SnippetAliveAnalyzer(); + + analyzer.analyzeTree(env, that, make); + return analyzer.isAlive(); + } finally { + log.popDiagnosticHandler(diagHandler); + } + } + + public boolean breaksOutOf(Env env, JCTree loop, JCTree body, TreeMaker make) { + //we need to disable diagnostics temporarily; the problem is that if + //"that" contains e.g. an unreachable statement, an error + //message will be reported and will cause compilation to skip the flow analyis + //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis + //related errors, which will allow for more errors to be detected + Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); + try { + boolean[] breaksOut = new boolean[1]; + SnippetBreakAnalyzer analyzer = new SnippetBreakAnalyzer(loop); + + analyzer.analyzeTree(env, body, make); + return analyzer.breaksOut(); + } finally { + log.popDiagnosticHandler(diagHandler); + } + } + /** * Definite assignment scan mode */ @@ -1467,6 +1502,38 @@ } /** + * Determine if alive after the given tree. + */ + class SnippetAliveAnalyzer extends AliveAnalyzer { + @Override + public void visitClassDef(JCClassDecl tree) { + //skip + } + public boolean isAlive() { + return super.alive != Liveness.DEAD; + } + } + + class SnippetBreakAnalyzer extends AliveAnalyzer { + private final JCTree loop; + private boolean breaksOut; + + public SnippetBreakAnalyzer(JCTree loop) { + this.loop = loop; + } + + @Override + public void visitBreak(JCBreak tree) { + breaksOut |= (super.alive == Liveness.ALIVE && tree.target == loop); + super.visitBreak(tree); + } + + public boolean breaksOut() { + return breaksOut; + } + } + + /** * Specialized pass that performs DA/DU on a lambda */ class LambdaAssignAnalyzer extends AssignAnalyzer {