| // TARGET_BACKEND: NATIVE | |
| // FILECHECK_STAGE: CStubs | |
| // FREE_COMPILER_ARGS: -Xbinary=genericSafeCasts=true -Xdisable-phases=CastsOptimization | |
| // IGNORE_NATIVE: optimizationMode=OPT && cacheMode=STATIC_ONLY_DIST | |
| // IGNORE_NATIVE: optimizationMode=OPT && cacheMode=STATIC_EVERYWHERE | |
| // KT-86949: ComputeTypesPass must not narrow a control flow merge point's type to a | |
| // final class across loop iterations as if a node reached on one iteration is reached | |
| // on every one. CastsOptimization is disabled so that ComputeTypesPass is | |
| // tested in isolation (it mishandles the same case, see KT-86948). | |
| class A | |
| fun bar() = true | |
| // CHECK-LABEL: define {{i1|zeroext i1}} @"kfun:#foo(){}kotlin.Boolean" | |
| fun foo(): Boolean { | |
| val a = A() | |
| var x: Any = a | |
| var count = 0 | |
| var last = false | |
| do { | |
| count++ | |
| // CHECK-DEBUG: {{call|call zeroext}} i1 @IsSubtype | |
| // CHECK-OPT: {{call|call zeroext}} i1 @IsSubclassFast | |
| // CHECK-DEBUG-NOT: call ptr @"kfun:kotlin.native.internal#downcast | |
| // On the second iteration `x` is an Any(), so the `if` expression is not always an `A`; | |
| // its type must not be rewritten to `A`, which would coerce the `Any()` to `A` with an unsafe downcast. | |
| last = (if (bar()) x else a) is A | |
| x = Any() | |
| } while (count < 2) | |
| return last | |
| // CHECK-LABEL: epilogue: | |
| } | |
| // CHECK-LABEL: define ptr @"kfun:#box(){}kotlin.String" | |
| fun box(): String { | |
| return if (foo()) "fail" else "OK" | |
| } |