1 /*
  2  * Copyright (c) 2024, 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 import java.lang.runtime.CodeReflection;
 25 
 26 /*
 27  * @test
 28  * @summary Smoke test for code reflection with try statements.
 29  * @build TryTest
 30  * @build CodeReflectionTester
 31  * @run main CodeReflectionTester TryTest
 32  */
 33 
 34 public class TryTest {
 35 
 36     @CodeReflection
 37     @IR("""
 38             func @"test1" (%0 : TryTest)void -> {
 39                 %1 : int = constant @"0";
 40                 %2 : Var<int> = var %1 @"i";
 41                 java.try
 42                     ()void -> {
 43                         %3 : int = constant @"1";
 44                         var.store %2 %3;
 45                         yield;
 46                     }
 47                     ^catch(%4 : java.lang.Exception)void -> {
 48                         %5 : Var<java.lang.Exception> = var %4 @"e";
 49                         %6 : int = constant @"2";
 50                         var.store %2 %6;
 51                         yield;
 52                     }
 53                     ^finally()void -> {
 54                         %7 : int = constant @"3";
 55                         var.store %2 %7;
 56                         yield;
 57                     };
 58                 return;
 59             };
 60             """)
 61     void test1() {
 62         int i = 0;
 63         try {
 64             i = 1;
 65         } catch (Exception e) {
 66             i = 2;
 67         } finally {
 68             i = 3;
 69         }
 70     }
 71 
 72     @CodeReflection
 73     @IR("""
 74             func @"test2" (%0 : TryTest)void -> {
 75                 %1 : int = constant @"0";
 76                 %2 : Var<int> = var %1 @"i";
 77                 java.try
 78                     ()void -> {
 79                         %3 : int = constant @"1";
 80                         var.store %2 %3;
 81                         yield;
 82                     }
 83                     ^finally()void -> {
 84                         %4 : int = constant @"3";
 85                         var.store %2 %4;
 86                         yield;
 87                     };
 88                 return;
 89             };
 90             """)
 91     void test2() {
 92         int i = 0;
 93         try {
 94             i = 1;
 95         } finally {
 96             i = 3;
 97         }
 98     }
 99 
100     @CodeReflection
101     @IR("""
102             func @"test3" (%0 : TryTest)void -> {
103                 %1 : int = constant @"0";
104                 %2 : Var<int> = var %1 @"i";
105                 java.try
106                     ()void -> {
107                         %3 : int = constant @"1";
108                         var.store %2 %3;
109                         yield;
110                     }
111                     ^catch(%4 : java.lang.Exception)void -> {
112                         %5 : Var<java.lang.Exception> = var %4 @"e";
113                         %6 : java.lang.Exception = var.load %5;
114                         invoke %6 @"java.lang.Exception::printStackTrace()void";
115                         yield;
116                     };
117                 return;
118             };
119             """)
120     void test3() {
121         int i = 0;
122         try {
123             i = 1;
124         } catch (Exception e) {
125             e.printStackTrace();
126         }
127     }
128 
129 
130     static class A implements AutoCloseable {
131         final B b;
132 
133         public A() {
134             this.b = null;
135         }
136 
137         @Override
138         public void close() throws Exception {
139 
140         }
141     }
142 
143     static class B implements AutoCloseable {
144         C c;
145 
146         @Override
147         public void close() throws Exception {
148 
149         }
150     }
151 
152     static class C implements AutoCloseable {
153         @Override
154         public void close() throws Exception {
155 
156         }
157     }
158 
159     A a() {
160         return null;
161     }
162 
163     @CodeReflection
164     @IR("""
165             func @"test4" (%0 : TryTest)void -> {
166                 java.try
167                     ^resources()Tuple<Var<TryTest$A>, TryTest$B, Var<TryTest$C>> -> {
168                         %1 : TryTest$A = invoke %0 @"TryTest::a()TryTest$A";
169                         %2 : Var<TryTest$A> = var %1 @"a";
170                         %3 : TryTest$A = var.load %2;
171                         %4 : TryTest$B = field.load %3 @"TryTest$A::b()TryTest$B";
172                         %5 : TryTest$A = var.load %2;
173                         %6 : TryTest$B = field.load %5 @"TryTest$A::b()TryTest$B";
174                         %7 : TryTest$C = field.load %6 @"TryTest$B::c()TryTest$C";
175                         %8 : Var<TryTest$C> = var %7 @"c";
176                         %9 : Tuple<Var<TryTest$A>, TryTest$B, Var<TryTest$C>> = tuple %2 %4 %8;
177                         yield %9;
178                     }
179                     (%10 : Var<TryTest$A>, %11 : Var<TryTest$C>)void -> {
180                         %12 : TryTest$A = var.load %10;
181                         %13 : Var<TryTest$A> = var %12 @"_a";
182                         %14 : TryTest$C = var.load %11;
183                         %15 : Var<TryTest$C> = var %14 @"_c";
184                         yield;
185                     }
186                     ^catch(%16 : java.lang.Throwable)void -> {
187                         %17 : Var<java.lang.Throwable> = var %16 @"t";
188                         %18 : java.lang.Throwable = var.load %17;
189                         invoke %18 @"java.lang.Throwable::printStackTrace()void";
190                         yield;
191                     }
192                     ^finally()void -> {
193                         %19 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
194                         %20 : java.lang.String = constant @"F";
195                         invoke %19 %20 @"java.io.PrintStream::println(java.lang.String)void";
196                         yield;
197                     };
198                 return;
199             };
200             """)
201     void test4() throws Exception {
202         try (A a = a(); a.b; C c = a.b.c) {
203             A _a = a;
204             C _c = c;
205         } catch (Throwable t) {
206             t.printStackTrace();
207         } finally {
208             System.out.println("F");
209         }
210     }
211 
212     @CodeReflection
213     @IR("""
214             func @"test5" (%0 : TryTest)void -> {
215                 %1 : int = constant @"0";
216                 %2 : Var<int> = var %1 @"i";
217                 java.try
218                     ()void -> {
219                         %3 : int = constant @"1";
220                         var.store %2 %3;
221                         yield;
222                     }
223                     ^catch(%4 : java.lang.NullPointerException)void -> {
224                         %5 : Var<java.lang.NullPointerException> = var %4 @"e";
225                         %6 : int = constant @"2";
226                         var.store %2 %6;
227                         yield;
228                     }
229                     ^catch(%7 : java.lang.OutOfMemoryError)void -> {
230                         %8 : Var<java.lang.OutOfMemoryError> = var %7 @"e";
231                         %9 : int = constant @"3";
232                         var.store %2 %9;
233                         yield;
234                     };
235                 return;
236             };
237             """)
238     void test5() {
239         int i = 0;
240         try {
241             i = 1;
242         } catch (NullPointerException e) {
243             i = 2;
244         } catch (OutOfMemoryError e) {
245             i = 3;
246         }
247     }
248 
249     @CodeReflection
250     @IR("""
251             func @"test6" (%0 : TryTest)void -> {
252                 %1 : int = constant @"0";
253                 %2 : Var<int> = var %1 @"i";
254                 java.try
255                     ()void -> {
256                         return;
257                     }
258                     ^catch(%3 : java.lang.Exception)void -> {
259                         %4 : Var<java.lang.Exception> = var %3 @"e";
260                         %5 : java.lang.Exception = var.load %4;
261                         throw %5;
262                     }
263                     ^finally()void -> {
264                         return;
265                     };
266                 return;
267             };
268             """)
269     void test6() {
270         int i = 0;
271         try {
272             return;
273         } catch (Exception e) {
274             throw e;
275         } finally {
276             return;
277         }
278      }
279 
280 }