Skip to content

Commit 065be95

Browse files
committed
[cxx-interop][Runtime] Initialize metadata of a Swift array of C++ references correctly
This fixes a crash at runtime when destroying a Swift array of values of a C++ foreign reference type. Swift optimizes the amount of metadata emitted for `_ContiguousArrayStorage<Element>` by reusing `_ContiguousArrayStorage<AnyObject>` whenever possible (see `getContiguousArrayStorageType`). However, C++ foreign reference types are not `AnyObject`s, since they have custom retain/release operations. This change disables the `_ContiguousArrayStorage` metadata optimization for C++ reference types, which makes sure that `swift_arrayDestroy` will call the correct release operation for elements of `[MyCxxRefType]`. rdar://127154770
1 parent c20331b commit 065be95

File tree

4 files changed

+32
-2
lines changed

4 files changed

+32
-2
lines changed

include/swift/ABI/Metadata.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,6 @@ struct TargetMetadata {
297297
case MetadataKind::Class:
298298
case MetadataKind::ObjCClassWrapper:
299299
case MetadataKind::ForeignClass:
300-
case MetadataKind::ForeignReferenceType:
301300
return true;
302301

303302
default:

test/Interop/Cxx/foreign-reference/not-any-object.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ module Test {
1515

1616
inline void* operator new(unsigned long, void* p) { return p; }
1717

18-
struct __attribute__((swift_attr("import_reference"))) Empty {
18+
struct __attribute__((swift_attr("import_reference")))
19+
__attribute__((swift_attr("retain:immortal")))
20+
__attribute__((swift_attr("release:immortal"))) Empty {
1921
static Empty *create() { return new (malloc(sizeof(Empty))) Empty(); }
2022
};
2123

@@ -27,3 +29,4 @@ public func test(_ _: AnyObject) {}
2729

2830
// TODO: make this a better error.
2931
test(Empty.create()) // expected-error {{type of expression is ambiguous without a type annotation}}
32+
test([Empty.create()][0]) // expected-error {{argument type 'Any' expected to be an instance of a class or class-constrained type}}

test/Interop/Cxx/foreign-reference/reference-counted-irgen.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,17 @@ public func getNullable(wantNullptr: Bool) -> GlobalCountNullableInit? {
5151
// CHECK: lifetime.cont:
5252
// CHECK: ret i64 %2
5353
// CHECK-NEXT: }
54+
55+
56+
public func getArrayOfLocalCount() -> [NS.LocalCount] {
57+
return [NS.LocalCount.create()]
58+
}
59+
60+
// CHECK: define {{.*}}swiftcc ptr @"$s4main20getArrayOfLocalCountSaySo2NSO0eF0VGyF"()
61+
// CHECK-NEXT: entry:
62+
// CHECK-NEXT: %0 = call swiftcc %swift.metadata_response @"$sSo2NSO10LocalCountVMa"(i64 0) #9
63+
// CHECK-NEXT: %1 = extractvalue %swift.metadata_response %0, 0
64+
// CHECK-NEXT: %2 = call swiftcc { ptr, ptr } @"$ss27_allocateUninitializedArrayySayxG_BptBwlF"(i64 1, ptr %1)
65+
// CHECK: %5 = call ptr @{{_ZN2NS10LocalCount6createEv|"\?create\@LocalCount\@NS\@\@SAPEAU12\@XZ"}}()
66+
// CHECK-NEXT: call void @{{_Z8LCRetainPN2NS10LocalCountE|"\?LCRetain\@\@YAXPEAULocalCount\@NS\@\@\@Z"}}(ptr %5)
67+
// CHECK: }

test/Interop/Cxx/foreign-reference/reference-counted.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,18 @@ ReferenceCountedTestSuite.test("Global") {
6767
expectEqual(globalCount, 0)
6868
}
6969

70+
var globalArray: [GlobalCount] = []
71+
72+
ReferenceCountedTestSuite.test("Global array") {
73+
expectEqual(globalCount, 0)
74+
75+
globalArray = [GlobalCount.create()]
76+
#if NO_OPTIMIZATIONS
77+
expectEqual(globalCount, 1)
78+
#endif
79+
80+
globalArray = []
81+
expectEqual(globalCount, 0)
82+
}
83+
7084
runAllTests()

0 commit comments

Comments
 (0)