Skip to content

Commit 4313f67

Browse files
committed
[Strict memory safety] Diagnose unsafe types in the superclass of a class
1 parent c9cfed2 commit 4313f67

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8162,6 +8162,10 @@ NOTE(decl_storage_mark_safe,none,
81628162
"add '@safe' if this type encapsulates the unsafe storage in "
81638163
"a safe interface", ())
81648164

8165+
GROUPED_WARNING(unsafe_superclass,Unsafe,none,
8166+
"%kindbase0 has superclass involving unsafe type %1",
8167+
(const ValueDecl *, Type))
8168+
81658169
GROUPED_WARNING(conformance_involves_unsafe,Unsafe,none,
81668170
"conformance of %0 to %kind1 involves unsafe code; use '@unsafe' to "
81678171
"indicate that the conformance is not memory-safe",

lib/Sema/TypeCheckUnsafe.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,27 @@ void swift::checkUnsafeStorage(NominalTypeDecl *nominal) {
392392
break;
393393
}
394394

395+
// Check whether the superclass is unsafe. If so, the only thing one can
396+
// do is mark the class unsafe.
397+
ASTContext &ctx = nominal->getASTContext();
398+
if (auto classDecl = dyn_cast<ClassDecl>(nominal)) {
399+
if (Type superclassType = classDecl->getSuperclass()) {
400+
superclassType = classDecl->mapTypeIntoContext(superclassType);
401+
bool diagnosed = false;
402+
diagnoseUnsafeType(ctx, classDecl->getLoc(), superclassType, [&](Type type) {
403+
if (diagnosed)
404+
return;
405+
406+
classDecl->diagnose(diag::unsafe_superclass, classDecl, type)
407+
.fixItInsert(classDecl->getAttributeInsertionLoc(false), "@unsafe ");
408+
diagnosed = true;
409+
});
410+
411+
if (diagnosed)
412+
return;
413+
}
414+
}
415+
395416
// Visitor that finds unsafe storage.
396417
class UnsafeStorageVisitor: public StorageVisitor {
397418
ASTContext &ctx;
@@ -421,7 +442,6 @@ void swift::checkUnsafeStorage(NominalTypeDecl *nominal) {
421442
};
422443

423444
// Look for any unsafe storage in this nominal type.
424-
ASTContext &ctx = nominal->getASTContext();
425445
SmallVector<UnsafeUse, 4> unsafeUses;
426446
UnsafeStorageVisitor(ctx, unsafeUses).visit(nominal, nominal->getDeclContext());
427447

test/Unsafe/unsafe.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ class ExclusivityChecking {
120120
func f() { }
121121
};
122122

123-
// TODO: diagnose the need for @unsafe when there's an unsafe superclass.
123+
// expected-warning@+1{{class 'UnsafeSub' has superclass involving unsafe type 'UnsafeSuper' [Unsafe]}}{{1-1=@unsafe }}
124124
class UnsafeSub: UnsafeSuper { }
125125

126126
// -----------------------------------------------------------------------

0 commit comments

Comments
 (0)