src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java
changeset 59285 7799a51dbe30
parent 55306 ea43db53de91
--- 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<AttrContext> 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<AttrContext> 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 {