Skip to content

Commit 607fd9f

Browse files
committed
[PrintAsObjc] Import/fwd-declare the unbridged type for known types.
For non-Clang types that conform to `_ObjectiveCBridgeable` but have type mappings defined in `getKnownTypeInfo`, always use the Clang type in the mapping to determine which module to import. `CGFloat` is a rare case of an `_ObjectiveCBridgeable` type that is a native Swift `struct` declared in an overlay instead of extending the original Clang decl with the conformance. Since `hasClangNode` returns false in this case, it fell through to the rest of the logic for `getObjCBridgedClass` and would forward declare `@class NSNumber` instead of `@import CoreGraphics`. Thus, in some cases (e.g., the header only defines APIs that use `CGFloat`), the header would be invalid. Fixes SR-14266.
1 parent ef318a1 commit 607fd9f

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

lib/PrintAsObjC/DeclAndTypePrinter.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,7 +1183,7 @@ class DeclAndTypePrinter::Implementation
11831183
copyTy->isDictionary() ||
11841184
copyTy->isSet() ||
11851185
copyTy->isString() ||
1186-
(!getKnownTypeInfo(nominal) && getObjCBridgedClass(nominal))) {
1186+
getObjCBridgedClass(nominal)) {
11871187
// We fast-path the most common cases in the condition above.
11881188
os << ", copy";
11891189
} else if (copyTy->isUnmanaged()) {
@@ -1371,10 +1371,15 @@ class DeclAndTypePrinter::Implementation
13711371

13721372
public:
13731373
/// If \p nominal is bridged to an Objective-C class (via a conformance to
1374-
/// _ObjectiveCBridgeable), return that class.
1374+
/// _ObjectiveCBridgeable) and is not an imported Clang type or a known type,
1375+
/// return that class.
13751376
///
13761377
/// Otherwise returns null.
13771378
const ClassDecl *getObjCBridgedClass(const NominalTypeDecl *nominal) {
1379+
// Print known types as their unbridged type.
1380+
if (getKnownTypeInfo(nominal))
1381+
return nullptr;
1382+
13781383
// Print imported bridgeable decls as their unbridged type.
13791384
if (nominal->hasClangNode())
13801385
return nullptr;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Test that known types that conform to `_ObjectiveCBridgeable` import or
2+
// forward-declare based on the Clang type in their known type mapping, not
3+
// their bridged type.
4+
//
5+
// This is particularly important for `CGFloat`, which has a native Swift decl
6+
// in the CoreGraphics overlay that shadows the imported Clang decl, so relying
7+
// solely on whether or not the decl has a Clang node is not sufficient.
8+
9+
// RUN: %empty-directory(%t)
10+
// RUN: %target-swift-frontend -typecheck %s -parse-as-library -emit-objc-header-path %t/swift.h
11+
// RUN: %FileCheck %s < %t/swift.h
12+
13+
// REQUIRES: objc_interop
14+
15+
import CoreGraphics
16+
import Foundation
17+
18+
// CHECK: @import CoreGraphics;
19+
20+
// CHECK-NOT: @class NSNumber;
21+
22+
// CHECK-LABEL: @interface Test : NSObject{{$}}
23+
public class Test: NSObject {
24+
// CHECK-NEXT: - (CGFloat)level
25+
@objc public func level() -> CGFloat { 9000.0 }
26+
// CHECK-NEXT: - (BOOL)isEnabled
27+
@objc public func isEnabled() -> Bool { true }
28+
// CHECK-NEXT: init
29+
} // CHECK-NEXT: @end

0 commit comments

Comments
 (0)