Skip to content

Commit a60aad8

Browse files
committed
[PrintAsObjC] Forward-declare bridged types
The initial pass through a type’s members to forward-declare or import anything needed by them did not account for _ObjectiveCBridgeable conformances; instead, it would examine the Swift type being bridged from, either tripping an assertion or just failing to do anything. Treat these as references to the bridged type instead. Fixes rdar://67263753.
1 parent a90d63d commit a60aad8

File tree

4 files changed

+43
-0
lines changed

4 files changed

+43
-0
lines changed

lib/PrintAsObjC/DeclAndTypePrinter.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,6 +1339,7 @@ class DeclAndTypePrinter::Implementation
13391339
return true;
13401340
}
13411341

1342+
public:
13421343
/// If \p nominal is bridged to an Objective-C class (via a conformance to
13431344
/// _ObjectiveCBridgeable), return that class.
13441345
///
@@ -1369,6 +1370,7 @@ class DeclAndTypePrinter::Implementation
13691370
return objcType->getClassOrBoundGenericClass();
13701371
}
13711372

1373+
private:
13721374
/// If the nominal type is bridged to Objective-C (via a conformance
13731375
/// to _ObjectiveCBridgeable), print the bridged type.
13741376
void printObjCBridgeableType(const NominalTypeDecl *swiftNominal,
@@ -2067,6 +2069,14 @@ bool DeclAndTypePrinter::isEmptyExtensionDecl(const ExtensionDecl *ED) {
20672069
return getImpl().isEmptyExtensionDecl(ED);
20682070
}
20692071

2072+
const TypeDecl *DeclAndTypePrinter::getObjCTypeDecl(const TypeDecl* TD) {
2073+
if (auto *nominal = dyn_cast<NominalTypeDecl>(TD))
2074+
if (auto *bridged = getImpl().getObjCBridgedClass(nominal))
2075+
return bridged;
2076+
2077+
return TD;
2078+
}
2079+
20702080
StringRef
20712081
DeclAndTypePrinter::maybeGetOSObjectBaseName(const clang::NamedDecl *decl) {
20722082
StringRef name = decl->getName();

lib/PrintAsObjC/DeclAndTypePrinter.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ class DeclAndTypePrinter {
7373
/// Is \p ED empty of members and protocol conformances to include?
7474
bool isEmptyExtensionDecl(const ExtensionDecl *ED);
7575

76+
/// Returns the type that will be printed by PrintAsObjC for a parameter or
77+
/// result type resolved to this declaration.
78+
///
79+
/// \warning This handles \c _ObjectiveCBridgeable types, but it doesn't
80+
/// currently know about other aspects of PrintAsObjC behavior, like known
81+
/// types.
82+
const TypeDecl *getObjCTypeDecl(const TypeDecl* TD);
83+
7684
/// Prints a category declaring the given members.
7785
///
7886
/// All members must have the same parent type. The list must not be empty.

lib/PrintAsObjC/ModuleContentsWriter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,9 @@ class ModuleWriter {
278278
if (TD == container)
279279
return;
280280

281+
// Bridge, if necessary.
282+
TD = printer.getObjCTypeDecl(TD);
283+
281284
if (finder.needsDefinition() && isa<NominalTypeDecl>(TD)) {
282285
// We can delay individual members of classes; do so if necessary.
283286
if (isa<ClassDecl>(container)) {

test/PrintAsObjC/classes.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,26 @@ import SingleGenericClass
4949
// CHECK-NEXT: @end
5050
@objc class B1 : A1 {}
5151

52+
// Used in BridgedTypes test case
53+
struct Notification: _ObjectiveCBridgeable {
54+
func _bridgeToObjectiveC() -> NSNotification { fatalError() }
55+
static func _forceBridgeFromObjectiveC(
56+
_ source: NSNotification,
57+
result: inout Self?
58+
) { fatalError() }
59+
@discardableResult
60+
static func _conditionallyBridgeFromObjectiveC(
61+
_ source: NSNotification,
62+
result: inout Self?
63+
) -> Bool { fatalError() }
64+
@_effects(readonly)
65+
static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?)
66+
-> Self { fatalError() }
67+
}
68+
5269
// CHECK-LABEL: @interface BridgedTypes
5370
// CHECK-NEXT: - (NSDictionary * _Nonnull)dictBridge:(NSDictionary * _Nonnull)x SWIFT_WARN_UNUSED_RESULT;
71+
// CHECK-NEXT: - (NSNotification * _Nonnull)noteBridge:(NSNotification * _Nonnull)x SWIFT_WARN_UNUSED_RESULT;
5472
// CHECK-NEXT: - (NSSet * _Nonnull)setBridge:(NSSet * _Nonnull)x SWIFT_WARN_UNUSED_RESULT;
5573
// CHECK-NEXT: init
5674
// CHECK-NEXT: @end
@@ -59,6 +77,10 @@ import SingleGenericClass
5977
return x
6078
}
6179

80+
@objc func noteBridge(_ x: Notification) -> Notification {
81+
return x
82+
}
83+
6284
@objc func setBridge(_ x: Set<NSObject>) -> Set<NSObject> {
6385
return x
6486
}

0 commit comments

Comments
 (0)