| // TARGET_BACKEND: NATIVE | |
| // FILECHECK_STAGE: CStubs | |
| // FREE_COMPILER_ARGS: -Xbinary=genericSafeCasts=true | |
| // IGNORE_NATIVE: optimizationMode=OPT && cacheMode=STATIC_ONLY_DIST | |
| // IGNORE_NATIVE: optimizationMode=OPT && cacheMode=STATIC_EVERYWHERE | |
| // KT-85403: reading a top-level val (a trivial getter) inside an `if (x is T)` branch dropped | |
| // the branch's path predicate in CastsOptimization, so the control flow merge after the `if` | |
| // wrongly concluded `x !is T`, folding subsequent `x is T` checks to false. | |
| val b = 42 | |
| open class A | |
| class A1 : A() | |
| // CHECK-LABEL: define i32 @"kfun:#foo(A){}kotlin.Int" | |
| fun foo(a: A): Int { | |
| // CHECK-DEBUG: @IsSubtype{{.*}}@"kclass:A1" | |
| // CHECK-OPT: {{call|call zeroext}} i1 @IsSubclassFast | |
| if (a is A1) { | |
| val c = b | |
| } | |
| // The check below must be kept, not folded to false. | |
| // CHECK-DEBUG: @IsSubtype{{.*}}@"kclass:A1" | |
| // CHECK-OPT: {{call|call zeroext}} i1 @IsSubclassFast | |
| return if (a is A1) 1 else 0 | |
| // CHECK-LABEL: epilogue: | |
| } | |
| sealed class B | |
| class B1 : B() | |
| // The original reproducer's shape: before the fix, the `is B1` check of the exhaustive `when` | |
| // was folded to false, and the `when` threw NoWhenBranchMatchedException. | |
| fun bar(x: B): Int { | |
| if (x is B1) { | |
| val c = b | |
| } | |
| return when (x) { | |
| is B1 -> 1 | |
| } | |
| } | |
| // CHECK-LABEL: define ptr @"kfun:#box(){}kotlin.String" | |
| fun box(): String { | |
| if (foo(A1()) != 1) return "fail 1" | |
| if (foo(A()) != 0) return "fail 2" | |
| if (bar(B1()) != 1) return "fail 3" | |
| return "OK" | |
| } |