Skip to content

Commit e0df8cd

Browse files
committed
[cxx-interop] Avoid spurious references to _OBJC_CLASS symbols for C++ foreign reference types
This removes erroneous references to `_OBJC_CLASS_$__xyz` symbols that Swift was emitting for certain usages of C/C++ foreign reference types. This was discovered when trying to iterate over a Swift array of foreign reference types using a Swift for-in loop. `Builtin.canBeClass` was returning true for foreign reference types, which led to the optimizer specializing the generic `canBeClass<T>` function to unconditionally return true for foreign reference types. This meant that `_isClassOrObjCExistential` for a foreign reference type evaluated to true, which made the Swift stdlib take the code path that was intended for Objective-C classes in `ArrayBuffer.getElement`, which assumed that the `Element` type conforms to `AnyObject`. Foreign reference types do not actually conform to `AnyObject`. rdar://161814644
1 parent bc88160 commit e0df8cd

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

lib/AST/Type.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4413,6 +4413,12 @@ bool Type::findIf(llvm::function_ref<bool(Type)> pred) const {
44134413
}
44144414

44154415
TypeTraitResult TypeBase::canBeClass() {
4416+
// Foreign reference types are represented as Swift classes in the AST,
4417+
// however, they use custom retain/release operations, and therefore aren't
4418+
// AnyObjects.
4419+
if (isForeignReferenceType())
4420+
return TypeTraitResult::IsNot;
4421+
44164422
// Any bridgeable object type can be a class.
44174423
if (isBridgeableObjectType())
44184424
return TypeTraitResult::Is;

test/Interop/Cxx/foreign-reference/array-of-classes.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ func go() {
5858
y.append(x)
5959
// CHECK: 1
6060
print(y.count)
61+
62+
var loopCount = 0
63+
for it in y {
64+
// CHECK: RefType()
65+
print(it)
66+
loopCount += 1
67+
}
68+
// CHECK: 1
69+
print(loopCount)
6170
}
6271

6372
go()

0 commit comments

Comments
 (0)