1 /*
   2  * Copyright (c) 2019, 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 8220018
  27  * @summary Verify that try-catch-finally inside a switch expression works properly.
  28  * @compile TryCatchFinally.java
  29  * @run main TryCatchFinally
  30  */
  31 public class TryCatchFinally {//TODO: yield <double>
  32     public static void main(String[] args) {
  33         for (int p1 = 0; p1 < 2; p1++) {
  34             for (int p2 = 0; p2 < 2; p2++) {
  35                 for (int p3 = 0; p3 < 2; p3++) {
  36                     for (int p4 = 0; p4 < 2; p4++) {
  37                         for (int p5 = 0; p5 < 2; p5++) {
  38                             for (int p6 = 0; p6 < 3; p6++) {
  39                                 int actual = runSwitchesOrdinary(p1, p2, p3, p4, p5, p6);
  40                                 int expected = computeExpectedOrdinary(p1, p2, p3, p4, p5, p6);
  41                                 if (actual != expected) {
  42                                     throw new IllegalStateException("actual=" + actual + "; " +
  43                                                                     "expected=" + expected + ", parameters: " + p1 + ", " + p2 + ", " + p3 + ", " + p4 + ", " + p5 + ", " + p6 + ", ");
  44                                 }
  45                             }
  46                         }
  47                     }
  48                 }
  49             }
  50         }
  51         {
  52             boolean correct = false;
  53             int v;
  54             if (switch (0) {
  55                 case 0:
  56                     try {
  57                         if (true) {
  58                             throw new MarkerException();
  59                         }
  60                         yield false;
  61                     } catch (MarkerException ex) {
  62                         yield false;
  63                     } finally {
  64                         v = 0;
  65                         yield true;
  66                     }
  67                 default: yield false;
  68             } && v == 0) {
  69                 correct = true;
  70             }
  71             if (!correct) {
  72                 throw new IllegalStateException();
  73             }
  74         }
  75         {
  76             boolean correct = false;
  77             if (switch (0) {
  78                 case 0:
  79                     try {
  80                         if (true) {
  81                             throw new MarkerException();
  82                         }
  83                         yield new TryCatchFinally().fls();
  84                     } catch (MarkerException ex) {
  85                         yield new TryCatchFinally().fls();
  86                     } finally {
  87                         yield true;
  88                     }
  89                 default: yield new TryCatchFinally().fls();
  90             }) {
  91                 correct = true;
  92             }
  93             if (!correct) {
  94                 throw new IllegalStateException();
  95             }
  96         }
  97         {
  98             E e = E.A;
  99             boolean correct = false;
 100             int v;
 101             if (switch (0) {
 102                 case 0:
 103                     try {
 104                         if (true) {
 105                             throw new MarkerException();
 106                         }
 107                         yield false;
 108                     } catch (MarkerException ex) {
 109                         v = 0;
 110                         yield true;
 111                     } finally {
 112                         try {
 113                             if (true)
 114                                 throw new MarkerException();
 115                         } catch (MarkerException ex) {
 116                             e = e.next();
 117                         }
 118                     }
 119                 default: yield false;
 120             } && v == 0) {
 121                 correct = true;
 122             }
 123             if (!correct) {
 124                 throw new IllegalStateException();
 125             }
 126         }
 127         {
 128             E e = E.A;
 129             boolean correct = false;
 130             int v;
 131             if (switch (0) {
 132                 case 0:
 133                     try {
 134                         if (true) {
 135                             throw new MarkerException();
 136                         }
 137                         yield false;
 138                     } catch (MarkerException ex) {
 139                         yield false;
 140                     } finally {
 141                         try {
 142                             if (true)
 143                                 throw new MarkerException();
 144                         } catch (MarkerException ex) {
 145                             e = e.next();
 146                         } finally {
 147                             v = 0;
 148                             yield true;
 149                         }
 150                     }
 151                 default: yield false;
 152             } && v == 0) {
 153                 correct = true;
 154             }
 155             if (!correct) {
 156                 throw new IllegalStateException();
 157             }
 158         }
 159         {
 160             boolean correct = false;
 161             if (!switch (0) {
 162                 default -> {
 163                     try {
 164                         yield switch(0) { default -> true; };
 165                     }
 166                     finally {
 167                         yield false;
 168                     }
 169                 }
 170             }) {
 171                 correct = true;
 172             }
 173             if (!correct) {
 174                 throw new IllegalStateException();
 175             }
 176         }
 177     }
 178 
 179     private static int runSwitchesOrdinary(int p1, int p2, int p3, int p4, int p5, int p6) {
 180         return 1 + switch (p1) {
 181             case 0:
 182                 try {
 183                     if (p2 == 0) {
 184                         new TryCatchFinally().throwException();
 185                     }
 186                     try {
 187                         yield 10 + switch (p3) {
 188                             case 0 -> {
 189                                 try {
 190                                     if (p4  == 0) {
 191                                         new TryCatchFinally().throwException();
 192                                     }
 193                                     yield 100;
 194                                 } catch (Throwable ex) {
 195                                     yield 200;
 196                                 } finally {
 197                                     if (p6 == 0) {
 198                                         yield 300;
 199                                     } else if (p6 == 1) {
 200                                         throw new MarkerException();
 201                                     }
 202                                 }
 203                             }
 204                             default -> 400;
 205                         };
 206                     } catch (MarkerException me) {
 207                         yield 510;
 208                     }
 209                 } catch(Throwable ex) {
 210                     try {
 211                         yield 20 + switch (p3) {
 212                             case 0 -> {
 213                                 try {
 214                                     if (p4  == 0) {
 215                                         new TryCatchFinally().throwException();
 216                                     }
 217                                     yield 100;
 218                                 } catch (Throwable ex2) {
 219                                     yield 200;
 220                                 } finally {
 221                                     if (p6 == 0) {
 222                                         yield 300;
 223                                     } else if (p6 == 1) {
 224                                         throw new MarkerException();
 225                                     }
 226                                 }
 227                             }
 228                             default -> 400;
 229                         };
 230                     } catch (MarkerException me) {
 231                         yield 520;
 232                     }
 233                 } finally {
 234                     if (p5 == 0) {
 235                         try {
 236                             yield 30 + switch (p3) {
 237                                 case 0 -> {
 238                                     try {
 239                                         if (p4  == 0) {
 240                                             new TryCatchFinally().throwException();
 241                                         }
 242                                         yield 100;
 243                                     } catch (Throwable ex) {
 244                                         yield 200;
 245                                     } finally {
 246                                         if (p6 == 0) {
 247                                             yield 300;
 248                                         } else if (p6 == 1) {
 249                                             throw new MarkerException();
 250                                         }
 251                                     }
 252                                 }
 253                                 default -> 400;
 254                             };
 255                         } catch (MarkerException me) {
 256                             yield 530;
 257                         }
 258                     }
 259                 }
 260             default: yield 40;
 261         };
 262     }
 263 
 264     private static int computeExpectedOrdinary(int p1, int p2, int p3, int p4, int p5, int p6) {
 265         int expected = 0;
 266 
 267         if (p1 == 0) {
 268             if (p5 == 0) {
 269                 expected = 30;
 270             } else if (p2 == 0) {
 271                 expected = 20;
 272             } else {
 273                 expected = 10;
 274             }
 275             if (p3 == 0) {
 276                 if (p6 == 0) {
 277                     expected += 300;
 278                 } else if (p6 == 1) {
 279                     expected += 500;
 280                 } else if (p4 == 0) {
 281                     expected += 200;
 282                 } else {
 283                     expected += 100;
 284                 }
 285             } else {
 286                 expected += 400;
 287             }
 288         } else {
 289             expected = 40;
 290         }
 291 
 292         expected += 1;
 293 
 294         return expected;
 295     }
 296 
 297     private boolean fls() {
 298         return false;
 299     }
 300     private void throwException() {
 301         throw new RuntimeException();
 302     }
 303 
 304     static class MarkerException extends Throwable {}
 305 
 306     enum E {
 307         A, B, C;
 308         public E next() {
 309             return values()[(ordinal() + 1) % values().length];
 310         }
 311     }
 312 }