changeset 52951:e4ba5414c8b4

8214031: Assertion error in value break statement with conditional operator in switch expression Summary: Correcting handling of boolean-valued switch expressions when true/false; generating them directly rather than desugaring in Lower. Reviewed-by: mcimadamore
author jlahoda
date Mon, 03 Dec 2018 10:37:36 +0100
parents df065f8356d7
children 9501a7b59111
files src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java test/langtools/tools/javac/switchexpr/CRT.java test/langtools/tools/javac/switchexpr/DefiniteAssignment1.java test/langtools/tools/javac/switchexpr/DefiniteAssignment2.java test/langtools/tools/javac/switchexpr/DefiniteAssignment2.out test/langtools/tools/javac/switchexpr/ExpressionSwitch-old.out test/langtools/tools/javac/switchexpr/ExpressionSwitch.java test/langtools/tools/javac/switchexpr/ExpressionSwitchBugsInGen.java test/langtools/tools/javac/switchexpr/ExpressionSwitchEmbedding.java
diffstat 14 files changed, 1260 insertions(+), 179 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Dec 03 12:35:27 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Dec 03 10:37:36 2018 +0100
@@ -300,7 +300,7 @@
      * Base visitor class for all visitors implementing dataflow analysis logic.
      * This class define the shared logic for handling jumps (break/continue statements).
      */
-    static abstract class BaseAnalyzer<P extends BaseAnalyzer.PendingExit> extends TreeScanner {
+    static abstract class BaseAnalyzer extends TreeScanner {
 
         enum JumpKind {
             BREAK(JCTree.Tag.BREAK) {
@@ -328,7 +328,7 @@
         /** The currently pending exits that go from current inner blocks
          *  to an enclosing block, in source order.
          */
-        ListBuffer<P> pendingExits;
+        ListBuffer<PendingExit> pendingExits;
 
         /** A pending exit.  These are the statements return, break, and
          *  continue.  In addition, exception-throwing expressions or
@@ -351,20 +351,20 @@
         abstract void markDead();
 
         /** Record an outward transfer of control. */
-        void recordExit(P pe) {
+        void recordExit(PendingExit pe) {
             pendingExits.append(pe);
             markDead();
         }
 
         /** Resolve all jumps of this statement. */
         private Liveness resolveJump(JCTree tree,
-                         ListBuffer<P> oldPendingExits,
+                         ListBuffer<PendingExit> oldPendingExits,
                          JumpKind jk) {
             boolean resolved = false;
-            List<P> exits = pendingExits.toList();
+            List<PendingExit> exits = pendingExits.toList();
             pendingExits = oldPendingExits;
             for (; exits.nonEmpty(); exits = exits.tail) {
-                P exit = exits.head;
+                PendingExit exit = exits.head;
                 if (exit.tree.hasTag(jk.treeTag) &&
                         jk.getTarget(exit.tree) == tree) {
                     exit.resolveJump();
@@ -378,11 +378,11 @@
 
         /** Resolve all continues of this statement. */
         Liveness resolveContinues(JCTree tree) {
-            return resolveJump(tree, new ListBuffer<P>(), JumpKind.CONTINUE);
+            return resolveJump(tree, new ListBuffer<PendingExit>(), JumpKind.CONTINUE);
         }
 
         /** Resolve all breaks of this statement. */
-        Liveness resolveBreaks(JCTree tree, ListBuffer<P> oldPendingExits) {
+        Liveness resolveBreaks(JCTree tree, ListBuffer<PendingExit> oldPendingExits) {
             return resolveJump(tree, oldPendingExits, JumpKind.BREAK);
         }
 
@@ -412,7 +412,7 @@
      * The output of this analysis pass are used by other analyzers. This analyzer
      * sets the 'finallyCanCompleteNormally' field in the JCTry class.
      */
-    class AliveAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
+    class AliveAnalyzer extends BaseAnalyzer {
 
         /** A flag that indicates whether the last statement could
          *  complete normally.
@@ -831,7 +831,7 @@
      * thrown is declared or caught. The analyzer uses some info that has been set by
      * the liveliness analyzer.
      */
-    class FlowAnalyzer extends BaseAnalyzer<FlowAnalyzer.FlowPendingExit> {
+    class FlowAnalyzer extends BaseAnalyzer {
 
         /** A flag that indicates whether the last statement could
          *  complete normally.
@@ -851,11 +851,11 @@
          */
         List<Type> caught;
 
-        class FlowPendingExit extends BaseAnalyzer.PendingExit {
+        class ThrownPendingExit extends BaseAnalyzer.PendingExit {
 
             Type thrown;
 
-            FlowPendingExit(JCTree tree, Type thrown) {
+            ThrownPendingExit(JCTree tree, Type thrown) {
                 super(tree);
                 this.thrown = thrown;
             }
@@ -871,21 +871,23 @@
         /** Complain that pending exceptions are not caught.
          */
         void errorUncaught() {
-            for (FlowPendingExit exit = pendingExits.next();
+            for (PendingExit exit = pendingExits.next();
                  exit != null;
                  exit = pendingExits.next()) {
+                Assert.check(exit instanceof ThrownPendingExit);
+                ThrownPendingExit thrownExit = (ThrownPendingExit) exit;
                 if (classDef != null &&
                     classDef.pos == exit.tree.pos) {
                     log.error(exit.tree.pos(),
-                              Errors.UnreportedExceptionDefaultConstructor(exit.thrown));
+                              Errors.UnreportedExceptionDefaultConstructor(thrownExit.thrown));
                 } else if (exit.tree.hasTag(VARDEF) &&
                         ((JCVariableDecl)exit.tree).sym.isResourceVariable()) {
                     log.error(exit.tree.pos(),
-                              Errors.UnreportedExceptionImplicitClose(exit.thrown,
+                              Errors.UnreportedExceptionImplicitClose(thrownExit.thrown,
                                                                       ((JCVariableDecl)exit.tree).sym.name));
                 } else {
                     log.error(exit.tree.pos(),
-                              Errors.UnreportedExceptionNeedToCatchOrThrow(exit.thrown));
+                              Errors.UnreportedExceptionNeedToCatchOrThrow(thrownExit.thrown));
                 }
             }
         }
@@ -896,7 +898,7 @@
         void markThrown(JCTree tree, Type exc) {
             if (!chk.isUnchecked(tree.pos(), exc)) {
                 if (!chk.isHandled(exc, caught)) {
-                    pendingExits.append(new FlowPendingExit(tree, exc));
+                    pendingExits.append(new ThrownPendingExit(tree, exc));
                 }
                 thrown = chk.incl(exc, thrown);
             }
@@ -914,7 +916,7 @@
             JCClassDecl classDefPrev = classDef;
             List<Type> thrownPrev = thrown;
             List<Type> caughtPrev = caught;
-            ListBuffer<FlowPendingExit> pendingExitsPrev = pendingExits;
+            ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
             Lint lintPrev = lint;
             boolean anonymousClass = tree.name == names.empty;
             pendingExits = new ListBuffer<>();
@@ -1024,12 +1026,12 @@
 
                 scan(tree.body);
 
-                List<FlowPendingExit> exits = pendingExits.toList();
+                List<PendingExit> exits = pendingExits.toList();
                 pendingExits = new ListBuffer<>();
                 while (exits.nonEmpty()) {
-                    FlowPendingExit exit = exits.head;
+                    PendingExit exit = exits.head;
                     exits = exits.tail;
-                    if (exit.thrown == null) {
+                    if (!(exit instanceof ThrownPendingExit)) {
                         Assert.check(exit.tree.hasTag(RETURN));
                     } else {
                         // uncaught throws will be reported later
@@ -1059,7 +1061,7 @@
         }
 
         public void visitDoLoop(JCDoWhileLoop tree) {
-            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
             scan(tree.body);
             resolveContinues(tree);
@@ -1068,7 +1070,7 @@
         }
 
         public void visitWhileLoop(JCWhileLoop tree) {
-            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
             scan(tree.cond);
             scan(tree.body);
@@ -1077,7 +1079,7 @@
         }
 
         public void visitForLoop(JCForLoop tree) {
-            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             scan(tree.init);
             pendingExits = new ListBuffer<>();
             if (tree.cond != null) {
@@ -1091,7 +1093,7 @@
 
         public void visitForeachLoop(JCEnhancedForLoop tree) {
             visitVarDef(tree.var);
-            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             scan(tree.expr);
             pendingExits = new ListBuffer<>();
             scan(tree.body);
@@ -1100,7 +1102,7 @@
         }
 
         public void visitLabelled(JCLabeledStatement tree) {
-            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
             scan(tree.body);
             resolveBreaks(tree, prevPendingExits);
@@ -1116,7 +1118,7 @@
         }
 
         private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
-            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
             scan(selector);
             for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
@@ -1140,7 +1142,7 @@
                 }
             }
 
-            ListBuffer<FlowPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
             for (JCTree resource : tree.resources) {
                 if (resource instanceof JCVariableDecl) {
@@ -1204,7 +1206,7 @@
             if (tree.finalizer != null) {
                 List<Type> savedThrown = thrown;
                 thrown = List.nil();
-                ListBuffer<FlowPendingExit> exits = pendingExits;
+                ListBuffer<PendingExit> exits = pendingExits;
                 pendingExits = prevPendingExits;
                 scan(tree.finalizer);
                 if (!tree.finallyCanCompleteNormally) {
@@ -1221,7 +1223,7 @@
                 }
             } else {
                 thrown = chk.union(thrown, chk.diff(thrownInTry, caughtInTry));
-                ListBuffer<FlowPendingExit> exits = pendingExits;
+                ListBuffer<PendingExit> exits = pendingExits;
                 pendingExits = prevPendingExits;
                 while (exits.nonEmpty()) pendingExits.append(exits.next());
             }
@@ -1267,16 +1269,16 @@
         public void visitBreak(JCBreak tree) {
             if (tree.isValueBreak())
                 scan(tree.value);
-            recordExit(new FlowPendingExit(tree, null));
+            recordExit(new PendingExit(tree));
         }
 
         public void visitContinue(JCContinue tree) {
-            recordExit(new FlowPendingExit(tree, null));
+            recordExit(new PendingExit(tree));
         }
 
         public void visitReturn(JCReturn tree) {
             scan(tree.expr);
-            recordExit(new FlowPendingExit(tree, null));
+            recordExit(new PendingExit(tree));
         }
 
         public void visitThrow(JCThrow tree) {
@@ -1343,18 +1345,18 @@
             }
             List<Type> prevCaught = caught;
             List<Type> prevThrown = thrown;
-            ListBuffer<FlowPendingExit> prevPending = pendingExits;
+            ListBuffer<PendingExit> prevPending = pendingExits;
             try {
                 pendingExits = new ListBuffer<>();
                 caught = tree.getDescriptorType(types).getThrownTypes();
                 thrown = List.nil();
                 scan(tree.body);
-                List<FlowPendingExit> exits = pendingExits.toList();
+                List<PendingExit> exits = pendingExits.toList();
                 pendingExits = new ListBuffer<>();
                 while (exits.nonEmpty()) {
-                    FlowPendingExit exit = exits.head;
+                    PendingExit exit = exits.head;
                     exits = exits.tail;
-                    if (exit.thrown == null) {
+                    if (!(exit instanceof ThrownPendingExit)) {
                         Assert.check(exit.tree.hasTag(RETURN));
                     } else {
                         // uncaught throws will be reported later
@@ -1488,7 +1490,7 @@
             }
             List<Type> prevCaught = caught;
             List<Type> prevThrown = thrown;
-            ListBuffer<FlowPendingExit> prevPending = pendingExits;
+            ListBuffer<PendingExit> prevPending = pendingExits;
             inLambda = true;
             try {
                 pendingExits = new ListBuffer<>();
@@ -1517,7 +1519,7 @@
      * effectively-final local variables/parameters.
      */
 
-    public class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
+    public class AssignAnalyzer extends BaseAnalyzer {
 
         /** The set of definitely assigned variables.
          */
@@ -1835,7 +1837,7 @@
                 JCClassDecl classDefPrev = classDef;
                 int firstadrPrev = firstadr;
                 int nextadrPrev = nextadr;
-                ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits;
+                ListBuffer<PendingExit> pendingExitsPrev = pendingExits;
 
                 pendingExits = new ListBuffer<>();
                 if (tree.name != names.empty) {
@@ -1970,14 +1972,15 @@
                             }
                         }
                     }
-                    List<AssignPendingExit> exits = pendingExits.toList();
+                    List<PendingExit> exits = pendingExits.toList();
                     pendingExits = new ListBuffer<>();
                     while (exits.nonEmpty()) {
-                        AssignPendingExit exit = exits.head;
+                        PendingExit exit = exits.head;
                         exits = exits.tail;
                         Assert.check(exit.tree.hasTag(RETURN), exit.tree);
                         if (isInitialConstructor) {
-                            inits.assign(exit.exit_inits);
+                            Assert.check(exit instanceof AssignPendingExit);
+                            inits.assign(((AssignPendingExit) exit).exit_inits);
                             for (int i = firstadr; i < nextadr; i++) {
                                 checkInit(exit.tree.pos(), vardecls[i].sym);
                             }
@@ -2027,7 +2030,7 @@
         }
 
         public void visitDoLoop(JCDoWhileLoop tree) {
-            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             FlowKind prevFlowKind = flowKind;
             flowKind = FlowKind.NORMAL;
             final Bits initsSkip = new Bits(true);
@@ -2059,7 +2062,7 @@
         }
 
         public void visitWhileLoop(JCWhileLoop tree) {
-            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             FlowKind prevFlowKind = flowKind;
             flowKind = FlowKind.NORMAL;
             final Bits initsSkip = new Bits(true);
@@ -2095,7 +2098,7 @@
         }
 
         public void visitForLoop(JCForLoop tree) {
-            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             FlowKind prevFlowKind = flowKind;
             flowKind = FlowKind.NORMAL;
             int nextadrPrev = nextadr;
@@ -2143,7 +2146,7 @@
         public void visitForeachLoop(JCEnhancedForLoop tree) {
             visitVarDef(tree.var);
 
-            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             FlowKind prevFlowKind = flowKind;
             flowKind = FlowKind.NORMAL;
             int nextadrPrev = nextadr;
@@ -2174,7 +2177,7 @@
         }
 
         public void visitLabelled(JCLabeledStatement tree) {
-            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
             scan(tree.body);
             resolveBreaks(tree, prevPendingExits);
@@ -2189,7 +2192,7 @@
         }
 
         private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
-            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
             int nextadrPrev = nextadr;
             scanExpr(selector);
@@ -2245,7 +2248,7 @@
         public void visitTry(JCTry tree) {
             ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>();
             final Bits uninitsTryPrev = new Bits(uninitsTry);
-            ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
+            ListBuffer<PendingExit> prevPendingExits = pendingExits;
             pendingExits = new ListBuffer<>();
             final Bits initsTry = new Bits(inits);
             uninitsTry.assign(uninits);
@@ -2302,7 +2305,7 @@
             if (tree.finalizer != null) {
                 inits.assign(initsTry);
                 uninits.assign(uninitsTry);
-                ListBuffer<AssignPendingExit> exits = pendingExits;
+                ListBuffer<PendingExit> exits = pendingExits;
                 pendingExits = prevPendingExits;
                 scan(tree.finalizer);
                 if (!tree.finallyCanCompleteNormally) {
@@ -2312,10 +2315,10 @@
                     // FIX: this doesn't preserve source order of exits in catch
                     // versus finally!
                     while (exits.nonEmpty()) {
-                        AssignPendingExit exit = exits.next();
-                        if (exit.exit_inits != null) {
-                            exit.exit_inits.orSet(inits);
-                            exit.exit_uninits.andSet(uninits);
+                        PendingExit exit = exits.next();
+                        if (exit instanceof AssignPendingExit) {
+                            ((AssignPendingExit) exit).exit_inits.orSet(inits);
+                            ((AssignPendingExit) exit).exit_uninits.andSet(uninits);
                         }
                         pendingExits.append(exit);
                     }
@@ -2324,7 +2327,7 @@
             } else {
                 inits.assign(initsEnd);
                 uninits.assign(uninitsEnd);
-                ListBuffer<AssignPendingExit> exits = pendingExits;
+                ListBuffer<PendingExit> exits = pendingExits;
                 pendingExits = prevPendingExits;
                 while (exits.nonEmpty()) pendingExits.append(exits.next());
             }
@@ -2390,8 +2393,34 @@
 
         @Override
         public void visitBreak(JCBreak tree) {
-            if (tree.isValueBreak())
+            if (tree.isValueBreak()) {
+                if (tree.target.hasTag(SWITCH_EXPRESSION)) {
+                    JCSwitchExpression expr = (JCSwitchExpression) tree.target;
+                    if (expr.type.hasTag(BOOLEAN)) {
+                        scanCond(tree.value);
+                        Bits initsAfterBreakWhenTrue = new Bits(initsWhenTrue);
+                        Bits initsAfterBreakWhenFalse = new Bits(initsWhenFalse);
+                        Bits uninitsAfterBreakWhenTrue = new Bits(uninitsWhenTrue);
+                        Bits uninitsAfterBreakWhenFalse = new Bits(uninitsWhenFalse);
+                        PendingExit exit = new PendingExit(tree) {
+                            @Override
+                            void resolveJump() {
+                                if (!inits.isReset()) {
+                                    split(true);
+                                }
+                                initsWhenTrue.andSet(initsAfterBreakWhenTrue);
+                                initsWhenFalse.andSet(initsAfterBreakWhenFalse);
+                                uninitsWhenTrue.andSet(uninitsAfterBreakWhenTrue);
+                                uninitsWhenFalse.andSet(uninitsAfterBreakWhenFalse);
+                            }
+                        };
+                        merge();
+                        recordExit(exit);
+                        return ;
+                    }
+                }
                 scan(tree.value);
+            }
             recordExit(new AssignPendingExit(tree, inits, uninits));
         }
 
@@ -2428,7 +2457,7 @@
             final Bits prevInits = new Bits(inits);
             int returnadrPrev = returnadr;
             int nextadrPrev = nextadr;
-            ListBuffer<AssignPendingExit> prevPending = pendingExits;
+            ListBuffer<PendingExit> prevPending = pendingExits;
             try {
                 returnadr = nextadr;
                 pendingExits = new ListBuffer<>();
@@ -2618,7 +2647,7 @@
      * As effectively final variables are marked as such during DA/DU, this pass must run after
      * AssignAnalyzer.
      */
-    class CaptureAnalyzer extends BaseAnalyzer<BaseAnalyzer.PendingExit> {
+    class CaptureAnalyzer extends BaseAnalyzer {
 
         JCTree currentTree; //local class or lambda
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Dec 03 12:35:27 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Dec 03 10:37:36 2018 +0100
@@ -63,6 +63,7 @@
 import com.sun.tools.javac.tree.JCTree.JCExpression;
 import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
 import static com.sun.tools.javac.tree.JCTree.JCOperatorExpression.OperandPos.LEFT;
+import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
 import static com.sun.tools.javac.tree.JCTree.Tag.*;
 
 /** This pass translates away some syntactic sugar: inner classes,
@@ -3362,14 +3363,29 @@
     }
 
     public void visitSwitch(JCSwitch tree) {
+        handleSwitch(tree, tree.selector, tree.cases);
+    }
+
+    @Override
+    public void visitSwitchExpression(JCSwitchExpression tree) {
+        if (tree.cases.stream().noneMatch(c -> c.pats.isEmpty())) {
+            JCThrow thr = make.Throw(makeNewClass(syms.incompatibleClassChangeErrorType,
+                                                  List.nil()));
+            JCCase c = make.Case(JCCase.STATEMENT, List.nil(), List.of(thr), null);
+            tree.cases = tree.cases.append(c);
+        }
+        handleSwitch(tree, tree.selector, tree.cases);
+    }
+
+    private void handleSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
         //expand multiple label cases:
-        ListBuffer<JCCase> cases = new ListBuffer<>();
-
-        for (JCCase c : tree.cases) {
+        ListBuffer<JCCase> convertedCases = new ListBuffer<>();
+
+        for (JCCase c : cases) {
             switch (c.pats.size()) {
                 case 0: //default
                 case 1: //single label
-                    cases.append(c);
+                    convertedCases.append(c);
                     break;
                 default: //multiple labels, expand:
                     //case C1, C2, C3: ...
@@ -3379,19 +3395,19 @@
                     //case C3: ...
                     List<JCExpression> patterns = c.pats;
                     while (patterns.tail.nonEmpty()) {
-                        cases.append(make_at(c.pos()).Case(JCCase.STATEMENT,
+                        convertedCases.append(make_at(c.pos()).Case(JCCase.STATEMENT,
                                                            List.of(patterns.head),
                                                            List.nil(),
                                                            null));
                         patterns = patterns.tail;
                     }
                     c.pats = patterns;
-                    cases.append(c);
+                    convertedCases.append(c);
                     break;
             }
         }
 
-        for (JCCase c : cases) {
+        for (JCCase c : convertedCases) {
             if (c.caseKind == JCCase.RULE && c.completesNormally) {
                 JCBreak b = make_at(c.pos()).Break(null);
                 b.target = tree;
@@ -3399,58 +3415,75 @@
             }
         }
 
-        tree.cases = cases.toList();
-
-        Type selsuper = types.supertype(tree.selector.type);
+        cases = convertedCases.toList();
+
+        Type selsuper = types.supertype(selector.type);
         boolean enumSwitch = selsuper != null &&
-            (tree.selector.type.tsym.flags() & ENUM) != 0;
+            (selector.type.tsym.flags() & ENUM) != 0;
         boolean stringSwitch = selsuper != null &&
-            types.isSameType(tree.selector.type, syms.stringType);
-        Type target = enumSwitch ? tree.selector.type :
+            types.isSameType(selector.type, syms.stringType);
+        Type target = enumSwitch ? selector.type :
             (stringSwitch? syms.stringType : syms.intType);
-        tree.selector = translate(tree.selector, target);
-        tree.cases = translateCases(tree.cases);
+        selector = translate(selector, target);
+        cases = translateCases(cases);
+        if (tree.hasTag(SWITCH)) {
+            ((JCSwitch) tree).selector = selector;
+            ((JCSwitch) tree).cases = cases;
+        } else if (tree.hasTag(SWITCH_EXPRESSION)) {
+            ((JCSwitchExpression) tree).selector = selector;
+            ((JCSwitchExpression) tree).cases = cases;
+        } else {
+            Assert.error();
+        }
         if (enumSwitch) {
-            result = visitEnumSwitch(tree);
+            result = visitEnumSwitch(tree, selector, cases);
         } else if (stringSwitch) {
-            result = visitStringSwitch(tree);
+            result = visitStringSwitch(tree, selector, cases);
         } else {
             result = tree;
         }
     }
 
-    public JCTree visitEnumSwitch(JCSwitch tree) {
-        TypeSymbol enumSym = tree.selector.type.tsym;
+    public JCTree visitEnumSwitch(JCTree tree, JCExpression selector, List<JCCase> cases) {
+        TypeSymbol enumSym = selector.type.tsym;
         EnumMapping map = mapForEnum(tree.pos(), enumSym);
         make_at(tree.pos());
         Symbol ordinalMethod = lookupMethod(tree.pos(),
                                             names.ordinal,
-                                            tree.selector.type,
+                                            selector.type,
                                             List.nil());
-        JCArrayAccess selector = make.Indexed(map.mapVar,
-                                        make.App(make.Select(tree.selector,
+        JCArrayAccess newSelector = make.Indexed(map.mapVar,
+                                        make.App(make.Select(selector,
                                                              ordinalMethod)));
-        ListBuffer<JCCase> cases = new ListBuffer<>();
-        for (JCCase c : tree.cases) {
+        ListBuffer<JCCase> newCases = new ListBuffer<>();
+        for (JCCase c : cases) {
             if (c.pats.nonEmpty()) {
                 VarSymbol label = (VarSymbol)TreeInfo.symbol(c.pats.head);
                 JCLiteral pat = map.forConstant(label);
-                cases.append(make.Case(JCCase.STATEMENT, List.of(pat), c.stats, null));
+                newCases.append(make.Case(JCCase.STATEMENT, List.of(pat), c.stats, null));
             } else {
-                cases.append(c);
+                newCases.append(c);
             }
         }
-        JCSwitch enumSwitch = make.Switch(selector, cases.toList());
+        JCTree enumSwitch;
+        if (tree.hasTag(SWITCH)) {
+            enumSwitch = make.Switch(newSelector, newCases.toList());
+        } else if (tree.hasTag(SWITCH_EXPRESSION)) {
+            enumSwitch = make.SwitchExpression(newSelector, newCases.toList());
+            enumSwitch.setType(tree.type);
+        } else {
+            Assert.error();
+            throw new AssertionError();
+        }
         patchTargets(enumSwitch, tree, enumSwitch);
         return enumSwitch;
     }
 
-    public JCTree visitStringSwitch(JCSwitch tree) {
-        List<JCCase> caseList = tree.getCases();
+    public JCTree visitStringSwitch(JCTree tree, JCExpression selector, List<JCCase> caseList) {
         int alternatives = caseList.size();
 
-        if (alternatives == 0) { // Strange but legal possibility
-            return make.at(tree.pos()).Exec(attr.makeNullCheck(tree.getExpression()));
+        if (alternatives == 0) { // Strange but legal possibility (only legal for switch statement)
+            return make.at(tree.pos()).Exec(attr.makeNullCheck(selector));
         } else {
             /*
              * The general approach used is to translate a single
@@ -3551,7 +3584,7 @@
                                                names.fromString("s" + tree.pos + target.syntheticNameChar()),
                                                syms.stringType,
                                                currentMethodSym);
-            stmtList.append(make.at(tree.pos()).VarDef(dollar_s, tree.getExpression()).setType(dollar_s.type));
+            stmtList.append(make.at(tree.pos()).VarDef(dollar_s, selector).setType(dollar_s.type));
 
             VarSymbol dollar_tmp = new VarSymbol(SYNTHETIC,
                                                  names.fromString("tmp" + tree.pos + target.syntheticNameChar()),
@@ -3601,12 +3634,7 @@
             // position map.
 
             ListBuffer<JCCase> lb = new ListBuffer<>();
-            JCSwitch switch2 = make.Switch(make.Ident(dollar_tmp), lb.toList());
             for(JCCase oneCase : caseList ) {
-                // Rewire up old unlabeled break statements to the
-                // replacement switch being created.
-                patchTargets(oneCase, tree, switch2);
-
                 boolean isDefault = (oneCase.pats.isEmpty());
                 JCExpression caseExpr;
                 if (isDefault)
@@ -3617,85 +3645,44 @@
                 }
 
                 lb.append(make.Case(JCCase.STATEMENT, caseExpr == null ? List.nil() : List.of(caseExpr),
-                                    oneCase.getStatements(), null));
+                                    oneCase.stats, null));
             }
 
-            switch2.cases = lb.toList();
-            stmtList.append(switch2);
-
-            return make.Block(0L, stmtList.toList());
+            if (tree.hasTag(SWITCH)) {
+                JCSwitch switch2 = make.Switch(make.Ident(dollar_tmp), lb.toList());
+                // Rewire up old unlabeled break statements to the
+                // replacement switch being created.
+                patchTargets(switch2, tree, switch2);
+
+                stmtList.append(switch2);
+
+                return make.Block(0L, stmtList.toList());
+            } else {
+                JCSwitchExpression switch2 = make.SwitchExpression(make.Ident(dollar_tmp), lb.toList());
+
+                // Rewire up old unlabeled break statements to the
+                // replacement switch being created.
+                patchTargets(switch2, tree, switch2);
+
+                switch2.setType(tree.type);
+
+                LetExpr res = make.LetExpr(stmtList.toList(), switch2);
+
+                res.needsCond = true;
+                res.setType(tree.type);
+
+                return res;
+            }
         }
     }
 
     @Override
-    public void visitSwitchExpression(JCSwitchExpression tree) {
-        //translates switch expression to statement switch:
-        //switch (selector) {
-        //    case C: break value;
-        //    ...
-        //}
-        //=>
-        //(letexpr T exprswitch$;
-        //         switch (selector) {
-        //             case C: { exprswitch$ = value; break; }
-        //         }
-        //         exprswitch$
-        //)
-        VarSymbol dollar_switchexpr = new VarSymbol(Flags.FINAL|Flags.SYNTHETIC,
-                           names.fromString("exprswitch" + tree.pos + target.syntheticNameChar()),
-                           tree.type,
-                           currentMethodSym);
-
-        ListBuffer<JCStatement> stmtList = new ListBuffer<>();
-
-        stmtList.append(make.at(tree.pos()).VarDef(dollar_switchexpr, null).setType(dollar_switchexpr.type));
-        JCSwitch switchStatement = make.Switch(tree.selector, null);
-        switchStatement.cases =
-                tree.cases.stream()
-                          .map(c -> convertCase(dollar_switchexpr, switchStatement, tree, c))
-                          .collect(List.collector());
-        if (tree.cases.stream().noneMatch(c -> c.pats.isEmpty())) {
-            JCThrow thr = make.Throw(makeNewClass(syms.incompatibleClassChangeErrorType,
-                                                  List.nil()));
-            JCCase c = make.Case(JCCase.STATEMENT, List.nil(), List.of(thr), null);
-            switchStatement.cases = switchStatement.cases.append(c);
+    public void visitBreak(JCBreak tree) {
+        if (tree.isValueBreak()) {
+            tree.value = translate(tree.value, tree.target.type);
         }
-
-        stmtList.append(translate(switchStatement));
-
-        result = make.LetExpr(stmtList.toList(), make.Ident(dollar_switchexpr))
-                     .setType(dollar_switchexpr.type);
+        result = tree;
     }
-        //where:
-        private JCCase convertCase(VarSymbol dollar_switchexpr, JCSwitch switchStatement,
-                                   JCSwitchExpression switchExpr, JCCase c) {
-            make.at(c.pos());
-            ListBuffer<JCStatement> statements = new ListBuffer<>();
-            statements.addAll(new TreeTranslator() {
-                @Override
-                public void visitLambda(JCLambda tree) {}
-                @Override
-                public void visitClassDef(JCClassDecl tree) {}
-                @Override
-                public void visitMethodDef(JCMethodDecl tree) {}
-                @Override
-                public void visitBreak(JCBreak tree) {
-                    if (tree.target == switchExpr) {
-                        tree.target = switchStatement;
-                        JCExpressionStatement assignment =
-                                make.Exec(make.Assign(make.Ident(dollar_switchexpr),
-                                                      translate(tree.value))
-                                              .setType(dollar_switchexpr.type));
-                        result = make.Block(0, List.of(assignment,
-                                                       tree));
-                        tree.value = null;
-                    } else {
-                        result = tree;
-                    }
-                }
-            }.translate(c.stats));
-            return make.Case(JCCase.STATEMENT, c.pats, statements.toList(), null);
-        }
 
     public void visitNewArray(JCNewArray tree) {
         tree.elemtype = translate(tree.elemtype);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java	Mon Dec 03 12:35:27 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/CRTable.java	Mon Dec 03 10:37:36 2018 +0100
@@ -33,6 +33,7 @@
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.tree.EndPosTable;
+import com.sun.tools.javac.tree.JCTree.JCSwitchExpression;
 
 /** This class contains the CharacterRangeTable for some method
  *  and the hashtable for mapping trees or lists of trees to their
@@ -311,6 +312,14 @@
             result = sr;
         }
 
+        @Override
+        public void visitSwitchExpression(JCSwitchExpression tree) {
+            SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
+            sr.mergeWith(csp(tree.selector));
+            sr.mergeWith(cspCases(tree.cases));
+            result = sr;
+        }
+
         public void visitCase(JCCase tree) {
             SourceRange sr = new SourceRange(startPos(tree), endPos(tree));
             sr.mergeWith(csp(tree.pats));
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Mon Dec 03 12:35:27 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Code.java	Mon Dec 03 10:37:36 2018 +0100
@@ -1220,7 +1220,7 @@
     }
 
     public boolean isStatementStart() {
-        return state.stacksize == letExprStackPos;
+        return !alive || state.stacksize == letExprStackPos;
     }
 
 /**************************************************************************
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon Dec 03 12:35:27 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Mon Dec 03 10:37:36 2018 +0100
@@ -25,6 +25,8 @@
 
 package com.sun.tools.javac.jvm;
 
+import java.util.function.BiConsumer;
+
 import com.sun.tools.javac.tree.TreeInfo.PosKind;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -161,6 +163,10 @@
      */
     EndPosTable endPosTable;
 
+    boolean inCondSwitchExpression;
+    Chain switchExpressionTrueChain;
+    Chain switchExpressionFalseChain;
+
     /** Generate code to load an integer constant.
      *  @param n     The integer to be loaded.
      */
@@ -719,6 +725,42 @@
                                       Code.mergeChains(falseJumps, second.falseJumps));
             if (markBranches) result.tree = tree.falsepart;
             return result;
+        } else if (inner_tree.hasTag(SWITCH_EXPRESSION)) {
+            boolean prevInCondSwitchExpression = inCondSwitchExpression;
+            Chain prevSwitchExpressionTrueChain = switchExpressionTrueChain;
+            Chain prevSwitchExpressionFalseChain = switchExpressionFalseChain;
+            try {
+                inCondSwitchExpression = true;
+                switchExpressionTrueChain = null;
+                switchExpressionFalseChain = null;
+                try {
+                    doHandleSwitchExpression((JCSwitchExpression) inner_tree);
+                } catch (CompletionFailure ex) {
+                    chk.completionError(_tree.pos(), ex);
+                    code.state.stacksize = 1;
+                }
+                CondItem result = items.makeCondItem(goto_,
+                                                     switchExpressionTrueChain,
+                                                     switchExpressionFalseChain);
+                if (markBranches) result.tree = _tree;
+                return result;
+            } finally {
+                inCondSwitchExpression = prevInCondSwitchExpression;
+                switchExpressionTrueChain = prevSwitchExpressionTrueChain;
+                switchExpressionFalseChain = prevSwitchExpressionFalseChain;
+            }
+        } else if (inner_tree.hasTag(LETEXPR) && ((LetExpr) inner_tree).needsCond) {
+            LetExpr tree = (LetExpr) inner_tree;
+            int limit = code.nextreg;
+            int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
+            try {
+                genStats(tree.defs, env);
+            } finally {
+                code.setLetExprStackPos(prevLetExprStart);
+            }
+            CondItem result = genCond(tree.expr, markBranches);
+            code.endScopes(limit);
+            return result;
         } else {
             CondItem result = genExpr(_tree, syms.booleanType).mkCond();
             if (markBranches) result.tree = _tree;
@@ -1119,25 +1161,50 @@
     }
 
     public void visitSwitch(JCSwitch tree) {
+        handleSwitch(tree, tree.selector, tree.cases);
+    }
+
+    @Override
+    public void visitSwitchExpression(JCSwitchExpression tree) {
+        code.resolvePending();
+        boolean prevInCondSwitchExpression = inCondSwitchExpression;
+        try {
+            inCondSwitchExpression = false;
+            doHandleSwitchExpression(tree);
+        } finally {
+            inCondSwitchExpression = prevInCondSwitchExpression;
+        }
+        result = items.makeStackItem(pt);
+    }
+
+    private void doHandleSwitchExpression(JCSwitchExpression tree) {
+        int prevLetExprStart = code.setLetExprStackPos(code.state.stacksize);
+        try {
+            handleSwitch(tree, tree.selector, tree.cases);
+        } finally {
+            code.setLetExprStackPos(prevLetExprStart);
+        }
+    }
+
+    private void handleSwitch(JCTree swtch, JCExpression selector, List<JCCase> cases) {
         int limit = code.nextreg;
-        Assert.check(!tree.selector.type.hasTag(CLASS));
+        Assert.check(!selector.type.hasTag(CLASS));
         int startpcCrt = genCrt ? code.curCP() : 0;
         Assert.check(code.isStatementStart());
-        Item sel = genExpr(tree.selector, syms.intType);
-        List<JCCase> cases = tree.cases;
+        Item sel = genExpr(selector, syms.intType);
         if (cases.isEmpty()) {
             // We are seeing:  switch <sel> {}
             sel.load().drop();
             if (genCrt)
-                code.crt.put(TreeInfo.skipParens(tree.selector),
+                code.crt.put(TreeInfo.skipParens(selector),
                              CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
         } else {
             // We are seeing a nonempty switch.
             sel.load();
             if (genCrt)
-                code.crt.put(TreeInfo.skipParens(tree.selector),
+                code.crt.put(TreeInfo.skipParens(selector),
                              CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
-            Env<GenContext> switchEnv = env.dup(tree, new GenContext());
+            Env<GenContext> switchEnv = env.dup(swtch, new GenContext());
             switchEnv.info.isSwitch = true;
 
             // Compute number of labels and minimum and maximum label values.
@@ -1593,10 +1660,35 @@
 
     public void visitBreak(JCBreak tree) {
         int tmpPos = code.pendingStatPos;
+        Assert.check(code.isStatementStart());
         Env<GenContext> targetEnv = unwind(tree.target, env);
         code.pendingStatPos = tmpPos;
-        Assert.check(code.isStatementStart());
-        targetEnv.info.addExit(code.branch(goto_));
+        if (tree.isValueBreak()) {
+            if (inCondSwitchExpression) {
+                CondItem value = genCond(tree.value, CRT_FLOW_TARGET);
+                Chain falseJumps = value.jumpFalse();
+                code.resolve(value.trueJumps);
+                Chain trueJumps = code.branch(goto_);
+                if (switchExpressionTrueChain == null) {
+                    switchExpressionTrueChain = trueJumps;
+                } else {
+                    switchExpressionTrueChain =
+                            Code.mergeChains(switchExpressionTrueChain, trueJumps);
+                }
+                if (switchExpressionFalseChain == null) {
+                    switchExpressionFalseChain = falseJumps;
+                } else {
+                    switchExpressionFalseChain =
+                            Code.mergeChains(switchExpressionFalseChain, falseJumps);
+                }
+            } else {
+                genExpr(tree.value, pt).load();
+                code.state.forceStackTop(tree.target.type);
+                targetEnv.info.addExit(code.branch(goto_));
+            }
+        } else {
+            targetEnv.info.addExit(code.branch(goto_));
+        }
         endFinalizerGaps(env, targetEnv);
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Dec 03 12:35:27 2018 +0530
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Dec 03 10:37:36 2018 +0100
@@ -3016,6 +3016,8 @@
     public static class LetExpr extends JCExpression {
         public List<JCStatement> defs;
         public JCExpression expr;
+        /**true if a expr should be run through Gen.genCond:*/
+        public boolean needsCond;
         protected LetExpr(List<JCStatement> defs, JCExpression expr) {
             this.defs = defs;
             this.expr = expr;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/CRT.java	Mon Dec 03 10:37:36 2018 +0100
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8214031
+ * @summary Test the CharacterRangeTable generated for switch expressions
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.Assert toolbox.ToolBox toolbox.JavacTask
+ * @run main CRT
+ */
+
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Collectors;
+
+import toolbox.JavacTask;
+import toolbox.JavapTask;
+import toolbox.Task.OutputKind;
+import toolbox.ToolBox;
+
+public class CRT {
+    public static void main(String... args) throws Exception {
+        new CRT().run();
+    }
+
+    private ToolBox tb = new ToolBox();
+
+    private void run() throws Exception {
+        doTest("    private String convert(int i) {\n" +
+               "        String res;" +
+               "        switch (i) {\n" +
+               "            case 0: res = \"a\"; break;\n" +
+               "            default: res = \"\"; break;\n" +
+               "        };\n" +
+               "        return res;\n" +
+               "    }\n",
+               "CharacterRangeTable:\n" +
+               "             0,  0,    c24,    c25,    8        //  0,  0,    3:36,    3:37, flow-controller\n" +
+               "            20, 22,   1015,   101f,    1        // 20, 22,    4:21,    4:31, statement\n" +
+               "            23, 25,   1020,   1026,    1        // 23, 25,    4:32,    4:38, statement\n" +
+               "            20, 25,   1015,   1026,   10        // 20, 25,    4:21,    4:38, flow-target\n" +
+               "            26, 28,   1416,   141f,    1        // 26, 28,    5:22,    5:31, statement\n" +
+               "            29, 31,   1420,   1426,    1        // 29, 31,    5:32,    5:38, statement\n" +
+               "            26, 31,   1416,   1426,   10        // 26, 31,    5:22,    5:38, flow-target\n" +
+               "             0, 31,    c1c,   180a,    1        //  0, 31,    3:28,    6:10, statement\n" +
+               "            32, 33,   1c09,   1c14,    1        // 32, 33,    7:09,    7:20, statement\n" +
+               "             0, 33,    823,   2006,    2        //  0, 33,    2:35,    8:06, block\n");
+        doTest("    private String convert(int i) {\n" +
+               "        return switch (i) {\n" +
+               "            case 0 -> \"a\";\n" +
+               "            default -> \"\";\n" +
+               "        };\n" +
+               "    }\n",
+               "CharacterRangeTable:\n" +
+               "             0,  0,    c18,    c19,    8        //  0,  0,    3:24,    3:25, flow-controller\n" +
+               "            20, 24,   1017,   101b,   11        // 20, 24,    4:23,    4:27, statement, flow-target\n" +
+               "            25, 29,   1418,   141b,   11        // 25, 29,    5:24,    5:27, statement, flow-target\n" +
+               "             0, 30,    c09,   180b,    1        //  0, 30,    3:09,    6:11, statement\n" +
+               "             0, 30,    823,   1c06,    2        //  0, 30,    2:35,    7:06, block");
+        doTest("    private boolean convert(int i) {\n" +
+               "        return switch (i) {\n" +
+               "            case 0 -> true;\n" +
+               "            default -> false;\n" +
+               "        } && i == 0;\n" +
+               "    }\n",
+               "CharacterRangeTable:\n" +
+               "             0,  0,    c18,    c19,    8        //  0,  0,    3:24,    3:25, flow-controller\n" +
+               "            20, 22,   1017,   101c,   11        // 20, 22,    4:23,    4:28, statement, flow-target\n" +
+               "            23, 25,   1418,   141e,   11        // 23, 25,    5:24,    5:30, statement, flow-target\n" +
+               "             0, 25,    c10,   180a,    8        //  0, 25,    3:16,    6:10, flow-controller\n" +
+               "            26, 26,   180e,   1814,   10        // 26, 26,    6:14,    6:20, flow-target\n" +
+               "             0, 35,    c09,   1815,    1        //  0, 35,    3:09,    6:21, statement\n" +
+               "             0, 35,    824,   1c06,    2        //  0, 35,    2:36,    7:06, block\n");
+        doTest("    private boolean convert(int i) {\n" +
+               "        return i >= 0 ? i == 0\n" +
+               "                        ? true\n" +
+               "                        : false\n" +
+               "                      : i == -1\n" +
+               "                        ? false\n" +
+               "                        : true;\n" +
+               "    }\n",
+               "CharacterRangeTable:\n" +
+               "             0,  0,    c10,    c16,    8        //  0,  0,    3:16,    3:22, flow-controller\n" +
+               "             1,  3,    c10,    c16,  100        //  1,  3,    3:16,    3:22, branch-false\n" +
+               "             4,  4,    c19,    c1f,    8        //  4,  4,    3:25,    3:31, flow-controller\n" +
+               "             5,  7,    c19,    c1f,  100        //  5,  7,    3:25,    3:31, branch-false\n" +
+               "             8,  8,   101b,   101f,   10        //  8,  8,    4:27,    4:31, flow-target\n" +
+               "            12, 12,   141b,   1420,   10        // 12, 12,    5:27,    5:32, flow-target\n" +
+               "             4, 12,    c19,   1420,   10        //  4, 12,    3:25,    5:32, flow-target\n" +
+               "            16, 17,   1819,   1820,    8        // 16, 17,    6:25,    6:32, flow-controller\n" +
+               "            18, 20,   1819,   1820,  100        // 18, 20,    6:25,    6:32, branch-false\n" +
+               "            21, 21,   1c1b,   1c20,   10        // 21, 21,    7:27,    7:32, flow-target\n" +
+               "            25, 25,   201b,   201f,   10        // 25, 25,    8:27,    8:31, flow-target\n" +
+               "            16, 25,   1819,   201f,   10        // 16, 25,    6:25,    8:31, flow-target\n" +
+               "             0, 26,    c09,   2020,    1        //  0, 26,    3:09,    8:32, statement\n" +
+               "             0, 26,    824,   2406,    2        //  0, 26,    2:36,    9:06, block\n");
+        doTest("    private boolean convert(int i) {\n" +
+               "        return i >= 0 ? switch (i) {\n" +
+               "            case 0 -> true;\n" +
+               "            default -> false;\n" +
+               "        } : switch (i) {\n" +
+               "            case -1 -> false;\n" +
+               "            default -> true;\n" +
+               "        };\n" +
+               "    }\n",
+               "CharacterRangeTable:\n" +
+               "             0,  0,    c10,    c16,    8        //  0,  0,    3:16,    3:22, flow-controller\n" +
+               "             1,  3,    c10,    c16,  100        //  1,  3,    3:16,    3:22, branch-false\n" +
+               "             4,  4,    c21,    c22,    8        //  4,  4,    3:33,    3:34, flow-controller\n" +
+               "            24, 27,   1017,   101c,   11        // 24, 27,    4:23,    4:28, statement, flow-target\n" +
+               "            28, 31,   1418,   141e,   11        // 28, 31,    5:24,    5:30, statement, flow-target\n" +
+               "             4, 31,    c19,   180a,   10        //  4, 31,    3:25,    6:10, flow-target\n" +
+               "            35, 35,   1815,   1816,    8        // 35, 35,    6:21,    6:22, flow-controller\n" +
+               "            56, 59,   1c18,   1c1e,   11        // 56, 59,    7:24,    7:30, statement, flow-target\n" +
+               "            60, 63,   2018,   201d,   11        // 60, 63,    8:24,    8:29, statement, flow-target\n" +
+               "            35, 63,   180d,   240a,   10        // 35, 63,    6:13,    9:10, flow-target\n" +
+               "             0, 64,    c09,   240b,    1        //  0, 64,    3:09,    9:11, statement\n" +
+               "             0, 64,    824,   2806,    2        //  0, 64,    2:36,   10:06, block\n");
+    }
+
+    private void doTest(String code, String expected) throws Exception {
+        Path base = Paths.get(".");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+        tb.cleanDirectory(classes);
+        new JavacTask(tb)
+                .options("-Xjcov",
+                         "--enable-preview",
+                         "-source", "12")
+                .outdir(classes)
+                .sources("public class Test {\n" +
+                         code +
+                         "}\n")
+                .run()
+                .writeAll();
+        String out = new JavapTask(tb)
+                .options("-private",
+                         "-verbose",
+                         "-s")
+                .classpath(classes.toString())
+                .classes("Test")
+                .run()
+                .writeAll()
+                .getOutputLines(OutputKind.DIRECT)
+                .stream()
+                .collect(Collectors.joining("\n"));
+        String crt = cutCRT(out);
+        if (!expected.trim().equals(crt.trim())) {
+            throw new AssertionError("Expected CharacterRangeTable not found, found: " + crt);
+        }
+    }
+
+    private static String cutCRT(String from) {
+        int start = from.indexOf("CharacterRangeTable:", from.indexOf("convert(int);"));
+        int end = from.indexOf("StackMapTable:");
+        return from.substring(start, end);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/DefiniteAssignment1.java	Mon Dec 03 10:37:36 2018 +0100
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8214031
+ * @summary Verify that definite assignment when true works (legal code)
+ * @compile --enable-preview --source 12 DefiniteAssignment1.java
+ * @run main/othervm --enable-preview DefiniteAssignment1
+ */
+public class DefiniteAssignment1 {
+    public static void main(String[] args) {
+        int a = 0;
+        boolean b = true;
+
+        {
+        int x;
+
+        boolean t1 = (b && switch(a) {
+            case 0: break (x = 1) == 1 || true;
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t1) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        boolean t1 = (b && switch(a) {
+            case 0: break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t1) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        boolean t1a = (b && switch(a) {
+            case 0: break (x = 1) == 1;
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t1a) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        boolean t1b = (switch(a) {
+            case 0: break (x = 1) == 1;
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t1b) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        boolean t2 = !(b && switch(a) {
+            case 0: break (x = 1) == 1 || true;
+            default: break false;
+        }) || x == 1;
+
+        if (!t2) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        boolean t2 = !(b && switch(a) {
+            case 0: break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) || x == 1;
+
+        if (!t2) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        boolean t3 = !(switch(a) {
+            case 0: break (x = 1) == 1 || true;
+            default: break false;
+        }) || x == 2;
+
+        if (t3) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        boolean t3 = !(switch(a) {
+            case 0: break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) || x == 2;
+
+        if (t3) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        boolean t4 = (b && switch(a) {
+            case 0: break (x = 1) == 1 || true;
+            default: throw new IllegalStateException();
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t4) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+
+        {
+        int x;
+
+        boolean t4 = (b && switch(a) {
+            case 0: break (x = 1) == 1 || isTrue();
+            default: throw new IllegalStateException();
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t4) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        String s = "a";
+
+        boolean t5 = (switch(s) {
+            case "a": break (x = 1) == 1 || true;
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t5) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        String s = "a";
+
+        boolean t5 = (switch(s) {
+            case "a": break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t5) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.B;
+
+        boolean t6 = (switch(e) {
+            case B: break (x = 1) == 1 || true;
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t6) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.B;
+
+        boolean t6 = (switch(e) {
+            case B: break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t6) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        int t7 = new DefiniteAssignment1().id(switch(0) {
+            default -> true;
+        } && (x = 1) == 1 && x == 1 ? 2 : -1);
+
+        if (t7 != 2) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+
+        int t7 = new DefiniteAssignment1().id(switch(0) {
+            default -> isTrue();
+        } && (x = 1) == 1 && x == 1 ? 2 : -1);
+
+        if (t7 != 2) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.B;
+
+        boolean t8 = (switch(e) {
+            case A: x = 1; break true;
+            case B: break (x = 1) == 1 || true;
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t8) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.B;
+
+        boolean t8 = (switch(e) {
+            case A: x = 1; break isTrue();
+            case B: break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t8) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.A;
+
+        boolean t9 = (switch(e) {
+            case A: x = 1; break true;
+            case B: break (x = 1) == 1 || true;
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t9) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.A;
+
+        boolean t9 = (switch(e) {
+            case A: x = 1; break isTrue();
+            case B: break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!t9) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.C;
+
+        boolean tA = (switch(e) {
+            case A: x = 1; break true;
+            case B: break (x = 1) == 1 || true;
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (tA) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.C;
+
+        boolean tA = (switch(e) {
+            case A: x = 1; break isTrue();
+            case B: break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (tA) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        final int x;
+        E e = E.C;
+
+        boolean tA = (switch(e) {
+            case A: x = 1; break true;
+            case B: break (x = 2) == 2 || true;
+            default: break false;
+        }) || (x = 3) == 3; //x is definitelly unassigned here
+
+        if (x != 3) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.A;
+
+        boolean tA = (switch(e) {
+            case A: break isTrue() && (x = 1) == 1;
+            case B: break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!tA) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.A;
+
+        boolean tA = (switch(e) {
+            case A: break isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
+            case B: break (x = 1) == 1 || true;
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!tA) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+
+        {
+        int x;
+        E e = E.A;
+
+        boolean tA = (switch(e) {
+            case A: break isTrue() && e != E.C ? (x = 1) == 1 && e != E.B : false;
+            case B: break (x = 1) == 1 || isTrue();
+            default: break false;
+        }) && x == 1; //x is definitelly assigned here
+
+        if (!tA) {
+            throw new IllegalStateException("Unexpected result.");
+        }
+        }
+    }
+
+    private int id(int v) {
+        return v;
+    }
+
+    private static boolean isTrue() {
+        return true;
+    }
+
+    enum E {
+        A, B, C;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/DefiniteAssignment2.java	Mon Dec 03 10:37:36 2018 +0100
@@ -0,0 +1,87 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 8214031
+ * @summary Verify that definite assignment when true works (illegal code)
+ * @compile/fail/ref=DefiniteAssignment2.out --enable-preview --source 12 -XDrawDiagnostics DefiniteAssignment2.java
+ */
+public class DefiniteAssignment2 {
+
+    public static void main(String[] args) {
+        int a = 0;
+        boolean b = true;
+        boolean t;
+
+        {
+            int x;
+
+            t = (b && switch(a) {
+                case 0: break (x = 1) == 1 || true;
+                default: break false;
+            }) || x == 1;
+        }
+
+        {
+            int x;
+
+            t = (switch(a) {
+                case 0: break (x = 1) == 1;
+                default: break false;
+            }) || x == 1;
+        }
+
+        {
+            int x;
+
+            t = (switch(a) {
+                case 0: x = 1; break true;
+                case 1: break (x = 1) == 1;
+                default: break false;
+            }) || x == 1;
+        }
+
+        {
+            int x;
+
+            t = (switch(a) {
+                case 0: break true;
+                case 1: break (x = 1) == 1;
+                default: break false;
+            }) && x == 1;
+        }
+
+        {
+            int x;
+
+            t = (switch(a) {
+                case 0: break false;
+                case 1: break isTrue() || (x = 1) == 1;
+                default: break false;
+            }) && x == 1;
+        }
+
+        {
+            int x;
+
+            t = (switch(a) {
+                case 0: break false;
+                case 1: break isTrue() ? true : (x = 1) == 1;
+                default: break false;
+            }) && x == 1;
+        }
+
+        {
+            final int x;
+
+            t = (switch(a) {
+                case 0: break false;
+                case 1: break isTrue() ? true : (x = 1) == 1;
+                default: break false;
+            }) && (x = 1) == 1;
+        }
+    }
+
+    private static boolean isTrue() {
+        return true;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/DefiniteAssignment2.out	Mon Dec 03 10:37:36 2018 +0100
@@ -0,0 +1,10 @@
+DefiniteAssignment2.java:20:19: compiler.err.var.might.not.have.been.initialized: x
+DefiniteAssignment2.java:29:19: compiler.err.var.might.not.have.been.initialized: x
+DefiniteAssignment2.java:39:19: compiler.err.var.might.not.have.been.initialized: x
+DefiniteAssignment2.java:49:19: compiler.err.var.might.not.have.been.initialized: x
+DefiniteAssignment2.java:59:19: compiler.err.var.might.not.have.been.initialized: x
+DefiniteAssignment2.java:69:19: compiler.err.var.might.not.have.been.initialized: x
+DefiniteAssignment2.java:79:20: compiler.err.var.might.already.be.assigned: x
+- compiler.note.preview.filename: DefiniteAssignment2.java
+- compiler.note.preview.recompile
+7 errors
--- a/test/langtools/tools/javac/switchexpr/ExpressionSwitch-old.out	Mon Dec 03 12:35:27 2018 +0530
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitch-old.out	Mon Dec 03 10:37:36 2018 +0100
@@ -1,3 +1,4 @@
-ExpressionSwitch.java:30:16: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.switch.expressions)
-ExpressionSwitch.java:31:20: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.switch.rules)
-2 errors
+ExpressionSwitch.java:38:16: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.switch.expressions)
+ExpressionSwitch.java:39:20: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.switch.rules)
+ExpressionSwitch.java:89:21: compiler.err.preview.feature.disabled.plural: (compiler.misc.feature.multiple.case.labels)
+3 errors
--- a/test/langtools/tools/javac/switchexpr/ExpressionSwitch.java	Mon Dec 03 12:35:27 2018 +0530
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitch.java	Mon Dec 03 10:37:36 2018 +0100
@@ -23,6 +23,14 @@
         assertEquals(scopesIsolated(T.B), "B");
         assertEquals(lambdas1(T.B).get(), "B");
         assertEquals(lambdas2(T.B).get(), "B");
+        assertEquals(convert1("A"), 0);
+        assertEquals(convert1("B"), 0);
+        assertEquals(convert1("C"), 1);
+        assertEquals(convert1(""), -1);
+        assertEquals(convert2("A"), 0);
+        assertEquals(convert2("B"), 0);
+        assertEquals(convert2("C"), 1);
+        assertEquals(convert2(""), -1);
         localClass(T.A);
     }
 
@@ -76,6 +84,22 @@
         };
     }
 
+    private int convert1(String s) {
+        return switch (s) {
+            case "A", "B" -> 0;
+            case "C" -> { break 1; }
+            default -> -1;
+        };
+    }
+
+    private int convert2(String s) {
+        return switch (s) {
+            case "A", "B": break 0;
+            case "C": break 1;
+            default: break -1;
+        };
+    }
+
     private void localClass(T t) {
         String good = "good";
         class L {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchBugsInGen.java	Mon Dec 03 10:37:36 2018 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8214031
+ * @summary Verify various corner cases with nested switch expressions.
+ * @compile --enable-preview -source 12 ExpressionSwitchBugsInGen.java
+ * @run main/othervm --enable-preview ExpressionSwitchBugsInGen
+ */
+
+public class ExpressionSwitchBugsInGen {
+    public static void main(String... args) {
+        new ExpressionSwitchBugsInGen().test(0, 0, 0, false);
+        new ExpressionSwitchBugsInGen().test(0, 0, 1, true);
+        new ExpressionSwitchBugsInGen().test(0, 1, 1, false);
+        new ExpressionSwitchBugsInGen().test(1, 1, -1, true);
+        new ExpressionSwitchBugsInGen().test(1, 12, -1, false);
+        new ExpressionSwitchBugsInGen().testCommonSuperType(0, "a", new StringBuilder(), "a");
+        new ExpressionSwitchBugsInGen().testCommonSuperType(1, "", new StringBuilder("a"), "a");
+        new ExpressionSwitchBugsInGen().testSwitchExpressionInConditional(0, null, -1);
+        new ExpressionSwitchBugsInGen().testSwitchExpressionInConditional(1, "", 0);
+        new ExpressionSwitchBugsInGen().testSwitchExpressionInConditional(1, 1, 1);
+        new ExpressionSwitchBugsInGen().testIntBoxing(0, 10, 10);
+        new ExpressionSwitchBugsInGen().testIntBoxing(1, 10, -1);
+    }
+
+    private void test(int a, int b, int c, boolean expected) {
+        if ( !(switch (a) {
+                case 0 -> b == (switch (c) { case 0 -> 0; default -> 1; });
+                default -> b == 12;
+            })) {
+            if (!expected) {
+                throw new IllegalStateException();
+            }
+        } else {
+            if (expected) {
+                throw new IllegalStateException();
+            }
+        }
+    }
+
+    private void testCommonSuperType(int a, String s1, StringBuilder s2, String expected) {
+        String r = (switch (a) {
+            case 0 -> s1;
+            default -> s2;
+        }).toString();
+        if (!expected.equals(r)) {
+            throw new IllegalStateException();
+        }
+    }
+
+    private void testSwitchExpressionInConditional(int a, Object o, int expected) {
+        int v = a == 0 ? -1
+                       : switch (o instanceof String ? 0 : 1) {
+                             case 0 -> 0;
+                             default -> 1;
+                       };
+        if (v != expected) {
+            throw new IllegalStateException();
+        }
+    }
+
+    private void testIntBoxing(int a, Integer res, int expected) {
+        int r = switch (a) {
+            case 0 -> res;
+            default -> -1;
+        };
+        if (r != expected) {
+            throw new IllegalStateException();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/switchexpr/ExpressionSwitchEmbedding.java	Mon Dec 03 10:37:36 2018 +0100
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8214031
+ * @summary Verify switch expressions embedded in various statements work properly.
+ * @compile --enable-preview -source 12 ExpressionSwitchEmbedding.java
+ * @run main/othervm --enable-preview ExpressionSwitchEmbedding
+ */
+
+public class ExpressionSwitchEmbedding {
+    public static void main(String... args) {
+        new ExpressionSwitchEmbedding().run();
+    }
+
+    private void run() {
+        {
+            int i = 6;
+            int o = 0;
+            while (switch (i) {
+                case 1: i = 0; break true;
+                case 2: i = 1; break true;
+                case 3, 4: i--;
+                    if (i == 2 || i == 4) {
+                        break switch (i) {
+                            case 2 -> true;
+                            case 4 -> false;
+                            default -> throw new IllegalStateException();
+                        };
+                    } else {
+                        break true;
+                    }
+                default: i--; break switch (i) {
+                    case -1 -> false;
+                    case 3 -> true;
+                    default -> true;
+                };
+            }) {
+                o++;
+            }
+            if (o != 6 && i >= 0) {
+                throw new IllegalStateException();
+            }
+        }
+        {
+            int i = 6;
+            int o = 0;
+            if (switch (i) {
+                case 1: i = 0; break true;
+                case 2: i = 1; break true;
+                case 3, 4: i--;
+                    if (i == 2 || i == 4) {
+                        break (switch (i) {
+                            case 2 -> 3;
+                            case 4 -> 5;
+                            default -> throw new IllegalStateException();
+                        }) == i + 1;
+                    } else {
+                        break true;
+                    }
+                default: i--; break switch (i) {
+                    case -1 -> false;
+                    case 3 -> true;
+                    default -> true;
+                };
+            }) {
+                o++;
+            }
+            if (o != 1 && i != 5) {
+                throw new IllegalStateException();
+            }
+        }
+        {
+            int o = 0;
+            for (int i = 6; (switch (i) {
+                case 1: i = 0; break true;
+                case 2: i = 1; break true;
+                case 3, 4: i--;
+                    if (i == 2 || i == 4) {
+                        break switch (i) {
+                            case 2 -> true;
+                            case 4 -> false;
+                            default -> throw new IllegalStateException();
+                        };
+                    } else {
+                        break true;
+                    }
+                default: i--; break switch (i) {
+                    case -1 -> false;
+                    case 3 -> true;
+                    default -> true;
+                };
+            }); ) {
+                o++;
+            }
+            if (o != 6) {
+                throw new IllegalStateException();
+            }
+        }
+        {
+            int i = 6;
+            int o = 0;
+            do {
+                o++;
+            } while (switch (i) {
+                case 1: i = 0; break true;
+                case 2: i = 1; break true;
+                case 3, 4: i--;
+                    if (i == 2 || i == 4) {
+                        break switch (i) {
+                            case 2 -> true;
+                            case 4 -> false;
+                            default -> throw new IllegalStateException();
+                        };
+                    } else {
+                        break true;
+                    }
+                default: i--; break switch (i) {
+                    case -1 -> false;
+                    case 3 -> true;
+                    default -> true;
+                };
+            });
+            if (o != 6 && i >= 0) {
+                throw new IllegalStateException();
+            }
+        }
+    }
+
+}