1 /*
   2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 8214114
  27  * @summary Verify try-catch inside a switch expression works properly.
  28  * @compile --enable-preview -source 12 TryCatch.java
  29  * @run main/othervm --enable-preview TryCatch
  30  */
  31 public class TryCatch {
  32     public static void main(String[] args) {
  33         {
  34             int val = 3;
  35             for (int p : new int[] {0, 1, 2}) {
  36                 int res = 1 + new TryCatch().id(switch(p) {
  37                     case 0 -> switch (p + 1) {
  38                         case 1:
  39                             try {
  40                                 new TryCatch().throwException();
  41                                 break -1;
  42                             } catch(Throwable ex) {
  43                                 break val;
  44                             }
  45                         default: break -1;
  46                     };
  47                     case 1 -> {
  48                         try {
  49                             break new TryCatch().id(switch (p + 1) {
  50                                 case 2:
  51                                     try {
  52                                         new TryCatch().throwException();
  53                                         break -1;
  54                                     } catch(Throwable ex) {
  55                                         throw ex;
  56                                     }
  57                                 default: break -1;
  58                             });
  59                         } catch(Throwable ex) {
  60                             break val;
  61                         }
  62                     }
  63                     default -> {
  64                         try {
  65                             new TryCatch().throwException();
  66                             break -1;
  67                         } catch(Throwable ex) {
  68                             break val;
  69                         }
  70                     }
  71                 } - 1);
  72                 if (res != 3) {
  73                     throw new AssertionError("Unexpected result: " + res);
  74                 }
  75             }
  76         }
  77         {
  78             int val = 3;
  79             for (int p : new int[] {0, 1, 2}) {
  80                 int x;
  81                 int res = new TryCatch().id(val == 3 && switch(p) {
  82                     case 0 -> switch (p + 1) {
  83                         case 1:
  84                             try {
  85                                 new TryCatch().throwException();
  86                                 break false;
  87                             } catch(Throwable ex) {
  88                                 break true;
  89                             }
  90                         default: break false;
  91                     };
  92                     case 1 -> {
  93                         try {
  94                             break new TryCatch().id(switch (p + 1) {
  95                                 case 2:
  96                                     try {
  97                                         new TryCatch().throwException();
  98                                         break false;
  99                                     } catch(Throwable ex) {
 100                                         throw ex;
 101                                     }
 102                                 default: break false;
 103                             });
 104                         } catch(Throwable ex) {
 105                             break true;
 106                         }
 107                     }
 108                     default -> {
 109                         try {
 110                             new TryCatch().throwException();
 111                             break false;
 112                         } catch(Throwable ex) {
 113                             break true;
 114                         }
 115                     }
 116                 } && (x = 1) == 1 && x == 1 ? val : -1);
 117                 if (res != 3) {
 118                     throw new AssertionError("Unexpected result: " + res);
 119                 }
 120             }
 121         }
 122         {
 123             int val = 3;
 124             for (E e : new E[] {E.A, E.B, E.C}) {
 125                 int res = 1 + new TryCatch().id(switch(e) {
 126                     case A -> switch (e.next()) {
 127                         case B:
 128                             try {
 129                                 new TryCatch().throwException();
 130                                 break -1;
 131                             } catch(Throwable ex) {
 132                                 break val;
 133                             }
 134                         default: break -1;
 135                     };
 136                     case B -> {
 137                         try {
 138                             break new TryCatch().id(switch (e.next()) {
 139                                 case C:
 140                                     try {
 141                                         new TryCatch().throwException();
 142                                         break -1;
 143                                     } catch(Throwable ex) {
 144                                         throw ex;
 145                                     }
 146                                 default: break -1;
 147                             });
 148                         } catch(Throwable ex) {
 149                             break val;
 150                         }
 151                     }
 152                     default -> {
 153                         try {
 154                             new TryCatch().throwException();
 155                             break -1;
 156                         } catch(Throwable ex) {
 157                             break val;
 158                         }
 159                     }
 160                 } - 1);
 161                 if (res != 3) {
 162                     throw new AssertionError("Unexpected result: " + res);
 163                 }
 164             }
 165         }
 166         {
 167             int val = 3;
 168             for (E e : new E[] {E.A, E.B, E.C}) {
 169                 int x;
 170                 int res = new TryCatch().id(val == 3 && switch(e) {
 171                     case A -> switch (e.next()) {
 172                         case B:
 173                             try {
 174                                 new TryCatch().throwException();
 175                                 break false;
 176                             } catch(Throwable ex) {
 177                                 break true;
 178                             }
 179                         default: break false;
 180                     };
 181                     case B -> {
 182                         try {
 183                             break new TryCatch().id(switch (e.next()) {
 184                                 case C:
 185                                     try {
 186                                         new TryCatch().throwException();
 187                                         break false;
 188                                     } catch(Throwable ex) {
 189                                         throw ex;
 190                                     }
 191                                 default: break false;
 192                             });
 193                         } catch(Throwable ex) {
 194                             break true;
 195                         }
 196                     }
 197                     default -> {
 198                         try {
 199                             new TryCatch().throwException();
 200                             break false;
 201                         } catch(Throwable ex) {
 202                             break true;
 203                         }
 204                     }
 205                 } && (x = 1) == 1 && x == 1 ? val : -1);
 206                 if (res != 3) {
 207                     throw new AssertionError("Unexpected result: " + res);
 208                 }
 209             }
 210         }
 211         {
 212             int val = 3;
 213             for (String s : new String[] {"", "a", "b"}) {
 214                 int res = 1 + new TryCatch().id(switch(s) {
 215                     case "" -> switch (s + "c") {
 216                         case "c":
 217                             try {
 218                                 new TryCatch().throwException();
 219                                 break -1;
 220                             } catch(Throwable ex) {
 221                                 break val;
 222                             }
 223                         default: break -1;
 224                     };
 225                     case "a" -> {
 226                         try {
 227                             break new TryCatch().id(switch (s + "c") {
 228                                 case "ac":
 229                                     try {
 230                                         new TryCatch().throwException();
 231                                         break -1;
 232                                     } catch(Throwable ex) {
 233                                         throw ex;
 234                                     }
 235                                 default: break -1;
 236                             });
 237                         } catch(Throwable ex) {
 238                             break val;
 239                         }
 240                     }
 241                     default -> {
 242                         try {
 243                             new TryCatch().throwException();
 244                             break -1;
 245                         } catch(Throwable ex) {
 246                             break val;
 247                         }
 248                     }
 249                 } - 1);
 250                 if (res != 3) {
 251                     throw new AssertionError("Unexpected result: " + res);
 252                 }
 253             }
 254         }
 255         {
 256             int val = 3;
 257             for (String s : new String[] {"", "a", "b"}) {
 258                 int x;
 259                 int res = new TryCatch().id(val == 3 && switch(s) {
 260                     case "" -> switch (s + "c") {
 261                         case "c":
 262                             try {
 263                                 new TryCatch().throwException();
 264                                 break false;
 265                             } catch(Throwable ex) {
 266                                 break true;
 267                             }
 268                         default: break false;
 269                     };
 270                     case "a" -> {
 271                         try {
 272                             break new TryCatch().id(switch (s + "c") {
 273                                 case "ac":
 274                                     try {
 275                                         new TryCatch().throwException();
 276                                         break false;
 277                                     } catch(Throwable ex) {
 278                                         throw ex;
 279                                     }
 280                                 default: break false;
 281                             });
 282                         } catch(Throwable ex) {
 283                             break true;
 284                         }
 285                     }
 286                     default -> {
 287                         try {
 288                             new TryCatch().throwException();
 289                             break false;
 290                         } catch(Throwable ex) {
 291                             break true;
 292                         }
 293                     }
 294                 } && (x = 1) == 1 && x == 1 ? val : -1);
 295                 if (res != 3) {
 296                     throw new AssertionError("Unexpected result: " + res);
 297                 }
 298             }
 299         }
 300 
 301         {
 302             int res = new FieldHolder().intTest;
 303 
 304             if (res != 3) {
 305                 throw new AssertionError("Unexpected result: " + res);
 306             }
 307         }
 308         {
 309             int res = FieldHolder.intStaticTest;
 310 
 311             if (res != 3) {
 312                 throw new AssertionError("Unexpected result: " + res);
 313             }
 314         }
 315         {
 316             boolean res = new FieldHolder().booleanTest;
 317 
 318             if (!res) {
 319                 throw new AssertionError("Unexpected result: " + res);
 320             }
 321         }
 322         {
 323             boolean res = FieldHolder.booleanStaticTest;
 324 
 325             if (!res) {
 326                 throw new AssertionError("Unexpected result: " + res);
 327             }
 328         }
 329     }
 330 
 331     static class FieldHolder {
 332         private final int intTest = switch (0) {
 333             case -1: break -1;
 334             default:
 335                 try {
 336                     break new TryCatch().id(switch (2) {
 337                         case 2:
 338                             try {
 339                                 new TryCatch().throwException();
 340                                 break -1;
 341                             } catch(Throwable ex) {
 342                                 throw ex;
 343                             }
 344                         default: break -1;
 345                     });
 346                 } catch(Throwable ex) {
 347                     break 3;
 348                 }
 349         };
 350         private static final int intStaticTest = switch (0) {
 351             case -1: break -1;
 352             default:
 353                 try {
 354                     break new TryCatch().id(switch (2) {
 355                         case 2:
 356                             try {
 357                                 new TryCatch().throwException();
 358                                 break -1;
 359                             } catch(Throwable ex) {
 360                                 throw ex;
 361                             }
 362                         default: break -1;
 363                     });
 364                 } catch(Throwable ex) {
 365                     break 3;
 366                 }
 367         };
 368         private final boolean booleanTest = switch (0) {
 369             case -1: break false;
 370             default:
 371                 try {
 372                     break new TryCatch().id(switch (2) {
 373                         case 2:
 374                             try {
 375                                 new TryCatch().throwException();
 376                                 break false;
 377                             } catch(Throwable ex) {
 378                                 throw ex;
 379                             }
 380                         default: break false;
 381                     });
 382                 } catch(Throwable ex) {
 383                     break true;
 384                 }
 385         };
 386         private static final boolean booleanStaticTest = switch (0) {
 387             case -1: break false;
 388             default:
 389                 try {
 390                     break new TryCatch().id(switch (2) {
 391                         case 2:
 392                             try {
 393                                 new TryCatch().throwException();
 394                                 break false;
 395                             } catch(Throwable ex) {
 396                                 throw ex;
 397                             }
 398                         default: break false;
 399                     });
 400                 } catch(Throwable ex) {
 401                     break true;
 402                 }
 403         };
 404     }
 405 
 406     private int id(int i) {
 407         return i;
 408     }
 409 
 410     private boolean id(boolean b) {
 411         return b;
 412     }
 413 
 414     private void throwException() {
 415         throw new RuntimeException();
 416     }
 417     enum E {
 418         A, B, C;
 419         public E next() {
 420             return values()[(ordinal() + 1) % values().length];
 421         }
 422     }
 423 }