langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java
changeset 19502 f30b3ef165ea
parent 19122 1841f2fa76de
child 19933 5182bc65845b
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Fri Aug 16 10:32:42 2013 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java	Thu Aug 15 22:33:43 2013 +0200
@@ -224,7 +224,7 @@
         }
         try {
             new AliveAnalyzer().analyzeTree(env, that, make);
-            new FlowAnalyzer().analyzeTree(env, that, make);
+            new LambdaFlowAnalyzer().analyzeTree(env, that, make);
         } finally {
             if (!speculative) {
                 log.popDiagnosticHandler(diagHandler);
@@ -1259,12 +1259,24 @@
             ListBuffer<FlowPendingExit> prevPending = pendingExits;
             try {
                 pendingExits = ListBuffer.lb();
-                caught = List.of(syms.throwableType); //inhibit exception checking
+                caught = tree.getDescriptorType(types).getThrownTypes();
                 thrown = List.nil();
                 scan(tree.body);
-                tree.inferredThrownTypes = thrown;
-            }
-            finally {
+                List<FlowPendingExit> exits = pendingExits.toList();
+                pendingExits = new ListBuffer<FlowPendingExit>();
+                while (exits.nonEmpty()) {
+                    FlowPendingExit exit = exits.head;
+                    exits = exits.tail;
+                    if (exit.thrown == null) {
+                        Assert.check(exit.tree.hasTag(RETURN));
+                    } else {
+                        // uncaught throws will be reported later
+                        pendingExits.append(exit);
+                    }
+                }
+
+                errorUncaught();
+            } finally {
                 pendingExits = prevPending;
                 caught = prevCaught;
                 thrown = prevThrown;
@@ -1303,6 +1315,33 @@
     }
 
     /**
+     * Specialized pass that performs inference of thrown types for lambdas.
+     */
+    class LambdaFlowAnalyzer extends FlowAnalyzer {
+        @Override
+        public void visitLambda(JCLambda tree) {
+            if (tree.type != null &&
+                    tree.type.isErroneous()) {
+                return;
+            }
+            List<Type> prevCaught = caught;
+            List<Type> prevThrown = thrown;
+            ListBuffer<FlowPendingExit> prevPending = pendingExits;
+            try {
+                pendingExits = ListBuffer.lb();
+                caught = List.of(syms.throwableType);
+                thrown = List.nil();
+                scan(tree.body);
+                tree.inferredThrownTypes = thrown;
+            } finally {
+                pendingExits = prevPending;
+                caught = prevCaught;
+                thrown = prevThrown;
+            }
+        }
+    }
+
+    /**
      * This pass implements (i) definite assignment analysis, which ensures that
      * each variable is assigned when used and (ii) definite unassignment analysis,
      * which ensures that no final variable is assigned more than once. This visitor