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 import java.util.function.Supplier;
 26 
 27 
 28 /*
 29  * @test
 30  * @summary Smoke test for code reflection with null constants.
 31  * @enablePreview
 32  * @build NullTest
 33  * @build CodeReflectionTester
 34  * @run main CodeReflectionTester NullTest
 35  */
 36 
 37 public class NullTest {
 38 
 39     @CodeReflection
 40     @IR("""
 41             func @"test1" (%0 : NullTest)void -> {
 42                 %1 : java.lang.String = constant @null;
 43                 %2 : Var<java.lang.String> = var %1 @"s";
 44                 return;
 45             };
 46             """)
 47     void test1() {
 48         String s = null;
 49     }
 50 
 51     @CodeReflection
 52     @IR("""
 53             func @"test2" (%0 : NullTest)void -> {
 54                 %1 : java.lang.Object = constant @null;
 55                 %2 : java.lang.String = cast %1 @"java.lang.String";
 56                 %3 : Var<java.lang.String> = var %2 @"s";
 57                 return;
 58             };
 59             """)
 60     void test2() {
 61         String s = (String)null;
 62     }
 63 
 64     @CodeReflection
 65     @IR("""
 66             func @"test3" (%0 : NullTest, %1 : boolean)java.lang.String -> {
 67                 %2 : Var<boolean> = var %1 @"cond";
 68                 %3 : java.lang.String = java.cexpression
 69                     ^cond()boolean -> {
 70                         %4 : boolean = var.load %2;
 71                         yield %4;
 72                     }
 73                     ^truepart()java.lang.String -> {
 74                         %5 : java.lang.String = constant @null;
 75                         yield %5;
 76                     }
 77                     ^falsepart()java.lang.String -> {
 78                         %6 : java.lang.String = constant @"";
 79                         yield %6;
 80                     };
 81                 return %3;
 82             };
 83             """)
 84     String test3(boolean cond) {
 85         return cond ? null : "";
 86     }
 87 
 88     @CodeReflection
 89     @IR("""
 90             func @"test4" (%0 : NullTest, %1 : boolean)java.lang.String -> {
 91                 %2 : Var<boolean> = var %1 @"cond";
 92                 %3 : java.lang.String = java.cexpression
 93                     ^cond()boolean -> {
 94                         %4 : boolean = var.load %2;
 95                         yield %4;
 96                     }
 97                     ^truepart()java.lang.String -> {
 98                         %5 : java.lang.String = constant @"";
 99                         yield %5;
100                     }
101                     ^falsepart()java.lang.String -> {
102                         %6 : java.lang.String = constant @null;
103                         yield %6;
104                     };
105                 return %3;
106             };
107             """)
108     String test4(boolean cond) {
109         return cond ? "" : null;
110     }
111 
112     @CodeReflection
113     @IR("""
114             func @"test5" (%0 : NullTest, %1 : boolean)java.lang.String -> {
115                 %2 : Var<boolean> = var %1 @"cond";
116                 %3 : java.lang.String = java.cexpression
117                     ^cond()boolean -> {
118                         %4 : boolean = var.load %2;
119                         yield %4;
120                     }
121                     ^truepart()java.lang.String -> {
122                         %5 : java.lang.String = constant @null;
123                         yield %5;
124                     }
125                     ^falsepart()java.lang.String -> {
126                         %6 : java.lang.String = constant @null;
127                         yield %6;
128                     };
129                 return %3;
130             };
131             """)
132     String test5(boolean cond) {
133         return cond ? null : null;
134     }
135 
136     @CodeReflection
137     @IR("""
138             func @"test6" (%0 : NullTest, %1 : boolean)java.lang.String -> {
139                 %2 : Var<boolean> = var %1 @"cond";
140                 %3 : java.lang.Object = java.cexpression
141                     ^cond()boolean -> {
142                         %4 : boolean = var.load %2;
143                         yield %4;
144                     }
145                     ^truepart()java.lang.Object -> {
146                         %5 : java.lang.Object = constant @null;
147                         yield %5;
148                     }
149                     ^falsepart()java.lang.Object -> {
150                         %6 : java.lang.Object = constant @null;
151                         yield %6;
152                     };
153                 %7 : java.lang.String = cast %3 @"java.lang.String";
154                 return %7;
155             };
156             """)
157     String test6(boolean cond) {
158         return (String)(cond ? null : null);
159     }
160 
161     @CodeReflection
162     @IR("""
163             func @"test7" (%0 : NullTest, %1 : int)java.lang.String -> {
164                 %2 : Var<int> = var %1 @"cond";
165                 %3 : int = var.load %2;
166                 %4 : java.lang.String = java.switch.expression %3
167                     ^constantCaseLabel(%5 : int)boolean -> {
168                         %6 : int = constant @"1";
169                         %7 : boolean = eq %5 %6;
170                         yield %7;
171                     }
172                     ()java.lang.String -> {
173                         %8 : java.lang.String = constant @"";
174                         yield %8;
175                     }
176                     ^defaultCaseLabel()void -> {
177                         yield;
178                     }
179                     ()java.lang.String -> {
180                         %9 : java.lang.String = constant @null;
181                         yield %9;
182                     };
183                 return %4;
184             };
185             """)
186     String test7(int cond) {
187         return switch(cond) {
188             case 1  -> "";
189             default -> null;
190         };
191     }
192 
193     @CodeReflection
194     @IR("""
195             func @"test8" (%0 : NullTest, %1 : int)java.lang.String -> {
196                 %2 : Var<int> = var %1 @"cond";
197                 %3 : int = var.load %2;
198                 %4 : java.lang.String = java.switch.expression %3
199                     ^constantCaseLabel(%5 : int)boolean -> {
200                         %6 : int = constant @"1";
201                         %7 : boolean = eq %5 %6;
202                         yield %7;
203                     }
204                     ()java.lang.String -> {
205                         %8 : java.lang.String = constant @null;
206                         yield %8;
207                     }
208                     ^defaultCaseLabel()void -> {
209                         yield;
210                     }
211                     ()java.lang.String -> {
212                         %9 : java.lang.String = constant @"";
213                         yield %9;
214                     };
215                 return %4;
216             };
217             """)
218     String test8(int cond) {
219         return switch(cond) {
220             case 1  -> null;
221             default -> "";
222         };
223     }
224 
225     @CodeReflection
226     @IR("""
227             func @"test9" (%0 : NullTest, %1 : int)java.lang.String -> {
228                 %2 : Var<int> = var %1 @"cond";
229                 %3 : int = var.load %2;
230                 %4 : java.lang.String = java.switch.expression %3
231                     ^constantCaseLabel(%5 : int)boolean -> {
232                         %6 : int = constant @"1";
233                         %7 : boolean = eq %5 %6;
234                         yield %7;
235                     }
236                     ()java.lang.String -> {
237                         %8 : java.lang.String = constant @null;
238                         yield %8;
239                     }
240                     ^defaultCaseLabel()void -> {
241                         yield;
242                     }
243                     ()java.lang.String -> {
244                         %9 : java.lang.String = constant @null;
245                         yield %9;
246                     };
247                 return %4;
248             };
249             """)
250     String test9(int cond) {
251         return switch(cond) {
252             case 1  -> null;
253             default -> null;
254         };
255     }
256 
257     @CodeReflection
258     @IR("""
259             func @"test10" (%0 : NullTest, %1 : int)java.lang.String -> {
260                 %2 : Var<int> = var %1 @"cond";
261                 %3 : int = var.load %2;
262                 %4 : java.lang.Object = java.switch.expression %3
263                     ^constantCaseLabel(%5 : int)boolean -> {
264                         %6 : int = constant @"1";
265                         %7 : boolean = eq %5 %6;
266                         yield %7;
267                     }
268                     ()java.lang.Object -> {
269                         %8 : java.lang.Object = constant @null;
270                         yield %8;
271                     }
272                     ^defaultCaseLabel()void -> {
273                         yield;
274                     }
275                     ()java.lang.Object -> {
276                         %9 : java.lang.Object = constant @null;
277                         yield %9;
278                     };
279                 %10 : java.lang.String = cast %4 @"java.lang.String";
280                 return %10;
281             };
282             """)
283     String test10(int cond) {
284         return (String)switch(cond) {
285             case 1  -> null;
286             default -> null;
287         };
288     }
289 
290     @CodeReflection
291     @IR("""
292             func @"test11" (%0 : NullTest, %1 : int)java.lang.String -> {
293                 %2 : Var<int> = var %1 @"cond";
294                 %3 : int = var.load %2;
295                 %4 : java.lang.String = java.switch.expression %3
296                     ^constantCaseLabel(%5 : int)boolean -> {
297                         %6 : int = constant @"1";
298                         %7 : boolean = eq %5 %6;
299                         yield %7;
300                     }
301                     ()java.lang.String -> {
302                         %8 : java.lang.String = constant @"";
303                         java.yield %8;
304                     }
305                     ^defaultCaseLabel()void -> {
306                         yield;
307                     }
308                     ()java.lang.String -> {
309                         %9 : java.lang.String = constant @null;
310                         java.yield %9;
311                     };
312                 return %4;
313             };
314             """)
315     String test11(int cond) {
316         return switch(cond) {
317             case 1  -> { yield ""; }
318             default -> { yield null; }
319         };
320     }
321 
322     @CodeReflection
323     @IR("""
324             func @"test12" (%0 : NullTest, %1 : int)java.lang.String -> {
325                 %2 : Var<int> = var %1 @"cond";
326                 %3 : int = var.load %2;
327                 %4 : java.lang.String = java.switch.expression %3
328                     ^constantCaseLabel(%5 : int)boolean -> {
329                         %6 : int = constant @"1";
330                         %7 : boolean = eq %5 %6;
331                         yield %7;
332                     }
333                     ()java.lang.String -> {
334                         %8 : java.lang.String = constant @null;
335                         java.yield %8;
336                     }
337                     ^defaultCaseLabel()void -> {
338                         yield;
339                     }
340                     ()java.lang.String -> {
341                         %9 : java.lang.String = constant @"";
342                         java.yield %9;
343                     };
344                 return %4;
345             };
346             """)
347     String test12(int cond) {
348         return switch(cond) {
349             case 1  -> { yield null; }
350             default -> { yield ""; }
351         };
352     }
353 
354     @CodeReflection
355     @IR("""
356             func @"test13" (%0 : NullTest, %1 : int)java.lang.String -> {
357                 %2 : Var<int> = var %1 @"cond";
358                 %3 : int = var.load %2;
359                 %4 : java.lang.String = java.switch.expression %3
360                     ^constantCaseLabel(%5 : int)boolean -> {
361                         %6 : int = constant @"1";
362                         %7 : boolean = eq %5 %6;
363                         yield %7;
364                     }
365                     ()java.lang.String -> {
366                         %8 : java.lang.String = constant @null;
367                         java.yield %8;
368                     }
369                     ^defaultCaseLabel()void -> {
370                         yield;
371                     }
372                     ()java.lang.String -> {
373                         %9 : java.lang.String = constant @null;
374                         java.yield %9;
375                     };
376                 return %4;
377             };
378             """)
379     String test13(int cond) {
380         return switch(cond) {
381             case 1  -> { yield null; }
382             default -> { yield null; }
383         };
384     }
385 
386     @CodeReflection
387     @IR("""
388             func @"test14" (%0 : NullTest, %1 : int)java.lang.String -> {
389                 %2 : Var<int> = var %1 @"cond";
390                 %3 : int = var.load %2;
391                 %4 : java.lang.Object = java.switch.expression %3
392                     ^constantCaseLabel(%5 : int)boolean -> {
393                         %6 : int = constant @"1";
394                         %7 : boolean = eq %5 %6;
395                         yield %7;
396                     }
397                     ()java.lang.Object -> {
398                         %8 : java.lang.Object = constant @null;
399                         java.yield %8;
400                     }
401                     ^defaultCaseLabel()void -> {
402                         yield;
403                     }
404                     ()java.lang.Object -> {
405                         %9 : java.lang.Object = constant @null;
406                         java.yield %9;
407                     };
408                 %10 : java.lang.String = cast %4 @"java.lang.String";
409                 return %10;
410             };
411             """)
412     String test14(int cond) {
413         return (String)switch(cond) {
414             case 1  -> { yield null; }
415             default -> { yield null; }
416         };
417     }
418 
419     @CodeReflection
420     @IR("""
421             func @"test15" (%0 : NullTest)java.util.function.Supplier<java.lang.String> -> {
422                 %1 : java.util.function.Supplier<java.lang.String> = lambda ()java.lang.String -> {
423                     %2 : java.lang.String = constant @null;
424                     return %2;
425                 };
426                 return %1;
427             };
428             """)
429     Supplier<String> test15() {
430         return () -> null;
431     }
432 
433     static void m(String s, String... ss) { }
434 
435     @CodeReflection
436     @IR("""
437             func @"test16" (%0 : NullTest)void -> {
438                 %1 : java.lang.String = constant @null;
439                 invoke %1 @"NullTest::m(java.lang.String, java.lang.String[])void";
440                 return;
441             };
442             """)
443     void test16() {
444         m(null);
445     }
446 
447     @CodeReflection
448     @IR("""
449             func @"test17" (%0 : NullTest)void -> {
450                 %1 : java.lang.String = constant @null;
451                 %2 : java.lang.String[] = constant @null;
452                 invoke %1 %2 @"NullTest::m(java.lang.String, java.lang.String[])void";
453                 return;
454             };
455             """)
456     void test17() {
457         m(null, null);
458     }
459 
460     @CodeReflection
461     @IR("""
462             func @"test18" (%0 : NullTest)void -> {
463                 %1 : java.lang.String = constant @null;
464                 %2 : java.lang.String = constant @null;
465                 %3 : java.lang.String = constant @null;
466                 invoke %1 %2 %3 @"NullTest::m(java.lang.String, java.lang.String[])void";
467                 return;
468             };
469             """)
470     void test18() {
471         m(null, null, null);
472     }
473 
474     static class Box {
475         Box(String s, String... ss) { }
476     }
477 
478     @CodeReflection
479     @IR("""
480             func @"test19" (%0 : NullTest)void -> {
481                 %1 : java.lang.String = constant @null;
482                 %2 : NullTest$Box = new %1 @"func<NullTest$Box, java.lang.String, java.lang.String[]>";
483                 return;
484             };
485             """)
486     void test19() {
487         new Box(null);
488     }
489 
490     @CodeReflection
491     @IR("""
492             func @"test20" (%0 : NullTest)void -> {
493                 %1 : java.lang.String = constant @null;
494                 %2 : java.lang.String[] = constant @null;
495                 %3 : NullTest$Box = new %1 %2 @"func<NullTest$Box, java.lang.String, java.lang.String[]>";
496                 return;
497             };
498             """)
499     void test20() {
500         new Box(null, null);
501     }
502 
503     @CodeReflection
504     @IR("""
505             func @"test21" (%0 : NullTest)void -> {
506                 %1 : java.lang.String = constant @null;
507                 %2 : java.lang.String = constant @null;
508                 %3 : java.lang.String = constant @null;
509                 %4 : NullTest$Box = new %1 %2 %3 @"func<NullTest$Box, java.lang.String, java.lang.String[]>";
510                 return;
511             };
512             """)
513     void test21() {
514         new Box(null, null, null);
515     }
516 }