Skip to content

Commit 9abadf5

Browse files
committed
[cxx-interop] Prohibit weak references to foreign reference types
This fixes a runtime crash when a `weak` reference to a C++ foreign reference type is used. Instead of a runtime crash, Swift would now emit a compiler error saying that `weak` keyword is incompatible with foreign reference types. rdar://124040825 / resolves swiftlang#83080
1 parent d8edd86 commit 9abadf5

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6357,6 +6357,9 @@ ERROR(invalid_ownership_protocol_type,none,
63576357
ERROR(invalid_ownership_incompatible_class,none,
63586358
"%0 is incompatible with %1 references",
63596359
(Type, ReferenceOwnership))
6360+
ERROR(invalid_ownership_incompatible_foreign_reference_type,none,
6361+
"%0 is incompatible with 'weak' references, because it is a foreign reference type",
6362+
(Type))
63606363
ERROR(invalid_ownership_with_optional,none,
63616364
"%0 variable cannot have optional type", (ReferenceOwnership))
63626365
ERROR(invalid_ownership_not_optional,none,

lib/Sema/TypeCheckAttr.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5451,13 +5451,28 @@ Type TypeChecker::checkReferenceOwnershipAttr(VarDecl *var, Type type,
54515451
}
54525452

54535453
ClassDecl *underlyingClass = underlyingType->getClassOrBoundGenericClass();
5454-
if (underlyingClass && underlyingClass->isIncompatibleWithWeakReferences()) {
5455-
Diags
5456-
.diagnose(attr->getLocation(),
5457-
diag::invalid_ownership_incompatible_class, underlyingType,
5458-
ownershipKind)
5459-
.fixItRemove(attr->getRange());
5460-
attr->setInvalid();
5454+
if (underlyingClass) {
5455+
if (underlyingClass->isIncompatibleWithWeakReferences()) {
5456+
Diags
5457+
.diagnose(attr->getLocation(),
5458+
diag::invalid_ownership_incompatible_class, underlyingType,
5459+
ownershipKind)
5460+
.fixItRemove(attr->getRange());
5461+
attr->setInvalid();
5462+
}
5463+
// Foreign reference types cannot be held as weak references, since the
5464+
// Swift runtime has no way to make the pointer null when the object is
5465+
// deallocated.
5466+
// Unowned references to foreign reference types are supported.
5467+
if (ownershipKind == ReferenceOwnership::Weak &&
5468+
underlyingClass->isForeignReferenceType()) {
5469+
Diags
5470+
.diagnose(attr->getLocation(),
5471+
diag::invalid_ownership_incompatible_foreign_reference_type,
5472+
underlyingType)
5473+
.fixItRemove(attr->getRange());
5474+
attr->setInvalid();
5475+
}
54615476
}
54625477

54635478
auto PDC = dyn_cast<ProtocolDecl>(dc);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-typecheck-verify-swift -cxx-interoperability-mode=default -I %S/Inputs -disable-availability-checking
2+
3+
import POD
4+
5+
struct HasWeakReference {
6+
weak var x: Empty? // expected-error {{'Empty' is incompatible with 'weak' references, because it is a foreign reference type}}
7+
}
8+
9+
struct HasUnownedReference {
10+
unowned var x: Empty!
11+
}

0 commit comments

Comments
 (0)