[PrintAsObjC] Attempt at fixing SR-5018: marking +new unavailable when -init is unavailable.

Currently a loop-hole exists by which one could end up invoking an unavailable -init initializer from Obj-C
when it is unavailable by using +new (which itself calls -init)

https://bugs.swift.org/browse/SR-5018
This commit is contained in:
Javier Soto
2017-10-04 13:01:58 -07:00
parent c69469780f
commit 49c65facc9
4 changed files with 19 additions and 0 deletions

View File

@@ -604,6 +604,7 @@ private:
}
bool skipAvailability = false;
bool makeNewUnavailable = false;
// Swift designated initializers are Objective-C designated initializers.
if (auto ctor = dyn_cast<ConstructorDecl>(AFD)) {
if (ctor->hasStubImplementation()
@@ -612,6 +613,9 @@ private:
// required access
os << " SWIFT_UNAVAILABLE";
skipAvailability = true;
// If -init is unavailable, then +new should be, too:
const bool selectorIsInit = selectorPieces.getNumArgs() == 0 && selectorPieces.front().str() == "init";
makeNewUnavailable = selectorIsInit;
} else if (ctor->isDesignatedInit() &&
!isa<ProtocolDecl>(ctor->getDeclContext())) {
os << " OBJC_DESIGNATED_INITIALIZER";
@@ -643,6 +647,10 @@ private:
}
os << ";\n";
if (makeNewUnavailable) {
os << "+ (nonnull instancetype)new SWIFT_UNAVAILABLE;\n";
}
}
void printAbstractFunctionAsFunction(FuncDecl *FD) {

View File

@@ -57,6 +57,7 @@
// CHECK-LABEL: @interface AvailabilitySub
// CHECK-NEXT: - (nonnull instancetype)init SWIFT_UNAVAILABLE;
// CHECK-NEXT: + (nonnull instancetype)new SWIFT_UNAVAILABLE;
// CHECK-NEXT: - (nonnull instancetype)initWithX:(NSInteger)_ SWIFT_UNAVAILABLE;
// CHECK-NEXT: @end

View File

@@ -175,6 +175,15 @@ class DiscardableResult : NSObject {
@objc init(evenMoreFun: ()) { super.init() }
}
// CHECK-LABEL: @interface InheritedInitializersRequired
// CHECK-NEXT: - (nonnull instancetype)initWithEvenMoreFun OBJC_DESIGNATED_INITIALIZER;
// CHECK-NEXT: - (nonnull instancetype)init SWIFT_UNAVAILABLE;
// CHECK-NEXT: + (nonnull instancetype)new SWIFT_UNAVAILABLE;
// CHECK-NEXT: @end
@objc class InheritedInitializersRequired : InheritedInitializers {
@objc required init(evenMoreFun: ()) { super.init() }
}
// NEGATIVE-NOT: NotObjC
class NotObjC {}

View File

@@ -55,6 +55,7 @@ protocol CustomNameType2 {}
// CHECK-LABEL: @interface MyObject : NSObject <NSCoding, Fungible>
// CHECK-NEXT: initWithCoder
// CHECK-NEXT: init SWIFT_UNAVAILABLE
// CHECK-NEXT: new SWIFT_UNAVAILABLE
// CHECK-NEXT: @end
// NEGATIVE-NOT: @protocol NSCoding
class MyObject : NSObject, NSCoding, Fungible {