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