Don't emit redundant retain-release sequence for Obj-C alloc result

when calling Kotlin constructor generated for Objective-C initializer.

retain-release here is suboptimal and also may provoke specific bugs
to reproduce.
This commit is contained in:
Svyatoslav Scherbina
2019-08-06 16:42:40 +03:00
committed by SvyatoslavScherbina
parent 7efab59bc1
commit 9e149b6d91
6 changed files with 104 additions and 28 deletions
@@ -26,6 +26,8 @@ fun run() {
testMultipleInheritanceClash()
testClashingWithAny()
testInitWithCustomSelector()
testAllocNoRetain()
testNSOutputStreamToMemoryConstructor()
assertEquals(2, ForwardDeclaredEnum.TWO.value)
@@ -397,6 +399,35 @@ private class TestInitWithCustomSelectorSubclass : TestInitWithCustomSelector {
companion object : TestInitWithCustomSelectorMeta()
}
fun testAllocNoRetain() {
// Ensure that calling Kotlin constructor generated for Objective-C initializer doesn't result in
// redundant retain-release sequence for `alloc` result, since it may provoke specific bugs to reproduce, e.g.
// the one found in [[NSOutputStream alloc] initToMemory] sequence where initToMemory deallocates its receiver
// forcibly when replacing it with other object: (to be compiled with ARC enabled)
/*
#import <Foundation/Foundation.h>
void* mem;
NSOutputStream* allocated = nil;
int main() {
allocated = [NSOutputStream alloc];
NSOutputStream* initialized = [allocated initToMemory];
mem = calloc(1, 0x10); // To corrupt the 'allocated' object header.
allocated = nil; // Crashes here in objc_release.
return 0;
}
*/
assertTrue(TestAllocNoRetain().ok)
}
fun testNSOutputStreamToMemoryConstructor() {
val stream: Any = NSOutputStream(toMemory = Unit)
assertTrue(stream is NSOutputStream)
}
fun nsArrayOf(vararg elements: Any): NSArray = NSMutableArray().apply {
elements.forEach {
this.addObject(it as ObjCObject)