1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
// RUN: %empty-directory(%t)
// RUN: split-file %s %t
// RUN: %target-swift-frontend -typecheck %t/use-objc-types.swift -typecheck -module-name UseObjCTy -emit-clang-header-path %t/UseObjCTy.h -I %t -enable-experimental-cxx-interop -clang-header-expose-decls=all-public
// RUN: %target-interop-build-clangxx -std=c++20 -fobjc-arc -c %t/use-swift-objc-types.mm -I %t -o %t/swift-objc-execution.o
// RUN: %target-interop-build-swift %t/use-objc-types.swift -o %t/swift-objc-execution -Xlinker %t/swift-objc-execution.o -module-name UseObjCTy -Xfrontend -entry-point-function-name -Xfrontend swiftMain -I %t
// RUN: %target-codesign %t/swift-objc-execution
// RUN: %target-run %t/swift-objc-execution | %FileCheck %s
// RUN: %target-run %t/swift-objc-execution | %FileCheck --check-prefix=DESTROY %s
// REQUIRES: executable_test
// REQUIRES: objc_interop
// REQUIRES: rdar107657204
//--- header.h
#import <Foundation/Foundation.h>
@interface ObjCKlass: NSObject
-(ObjCKlass * _Nonnull) init:(int)x;
-(int)getValue;
@end
//--- module.modulemap
module ObjCTest {
header "header.h"
}
//--- use-objc-types.swift
import ObjCTest
public func retObjClass() -> ObjCKlass {
return ObjCKlass(1)
}
public func retObjClassNull() -> ObjCKlass? {
return nil
}
public func retObjClassNullable() -> ObjCKlass? {
return retObjClass()
}
public func takeObjCClass(_ x: ObjCKlass) {
print("OBJClass:", x.getValue());
}
public func takeObjCClassInout(_ x: inout ObjCKlass) {
x = ObjCKlass(x.getValue() + 1)
}
public func takeObjCClassNullable(_ x: ObjCKlass?) {
if let x = x {
print("OBJClass:", x.getValue());
} else {
print("NIL");
}
}
public func passThroughObjClass(_ x: ObjCKlass?) -> ObjCKlass? {
return x
}
//--- use-swift-objc-types.mm
#include "header.h"
#include "UseObjCTy.h"
#include <assert.h>
#include <stdio.h>
int globalCounter = 0;
struct DeinitPrinter {
~DeinitPrinter() {
puts("destroy ObjCKlass");
--globalCounter;
}
};
@implementation ObjCKlass {
int _x;
DeinitPrinter _printer;
}
- (ObjCKlass * _Nonnull) init:(int)x {
ObjCKlass *result = [super init];
result->_x = x;
puts("create ObjCKlass");
++globalCounter;
return result;
}
-(int)getValue {
return self->_x;
}
@end
int main() {
using namespace UseObjCTy;
@autoreleasepool {
ObjCKlass* val = retObjClass();
assert(val.getValue == 1);
assert(globalCounter == 1);
takeObjCClass(val);
takeObjCClassInout(val);
takeObjCClassNullable(val);
takeObjCClassNullable(retObjClassNull());
}
assert(globalCounter == 0);
// CHECK: create ObjCKlass
// CHECK-NEXT: OBJClass: 1
// CHECK-NEXT: create ObjCKlass
// CHECK: OBJClass: 2
// CHECK-NEXT: NIL
// DESTROY: destroy ObjCKlass
// DESTROY: destroy ObjCKlass
puts("Part2");
@autoreleasepool {
ObjCKlass* val = retObjClassNullable();
assert(globalCounter == 1);
assert(val.getValue == 1);
takeObjCClassNullable(passThroughObjClass(val));
}
assert(globalCounter == 0);
// CHECK: Part2
// CHECK-NEXT: create ObjCKlass
// CHECK-NEXT: OBJClass: 1
// CHECK-NEXT: destroy ObjCKlass
// DESTROY: destroy ObjCKlass
return 0;
}
|