Skip to content

Commit 6d269e5

Browse files
refactor and add test
1 parent 5d9e77d commit 6d269e5

File tree

6 files changed

+98
-29
lines changed

6 files changed

+98
-29
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -250,29 +250,6 @@ getSwiftStdlibType(const clang::TypedefNameDecl *D,
250250
}
251251
#include "MappedTypes.def"
252252

253-
if (Name.str() == "CGFloat") {
254-
SwiftModuleName = "CoreGraphics";
255-
256-
ModuleDecl *M = Impl.getNamedModule("CoreFoundation");
257-
if (M) {
258-
Type SwiftType = Impl.getNamedSwiftType(M, "CGFloat");
259-
if (SwiftType) {
260-
SwiftModuleName = "CoreFoundation";
261-
}
262-
}
263-
264-
CTypeKind = MappedCTypeKind::CGFloat;
265-
Bitwidth = 0;
266-
IsSwiftModule = false;
267-
SwiftTypeName = "CGFloat";
268-
CanBeMissing = false;
269-
NameMapping = MappedTypeNameKind::DoNothing;
270-
assert(verifyNameMapping(MappedTypeNameKind::DoNothing,
271-
"CGFloat", "CGFloat") &&
272-
"MappedTypes.def: Identical names must use DoNothing");
273-
break;
274-
}
275-
276253
// We handle `BOOL` as a special case because the selection here is more
277254
// complicated as the type alias exists on multiple platforms as different
278255
// types. It appears in an Objective-C context where it is a `signed char`
@@ -460,16 +437,20 @@ getSwiftStdlibType(const clang::TypedefNameDecl *D,
460437
M = Impl.getStdlibModule();
461438
else
462439
M = Impl.getNamedModule(SwiftModuleName);
463-
if (!M) {
464-
// User did not import the library module that contains the type we want to
465-
// substitute.
466-
*IsError = true;
467-
return std::make_pair(Type(), "");
468-
}
469440

470441
Type SwiftType = Impl.getNamedSwiftType(M, SwiftTypeName);
442+
443+
if (!SwiftType && CTypeKind == MappedCTypeKind::CGFloat) {
444+
// Fall back to looking for CGFloat in Core Graphics.
445+
M = Impl.getNamedModule("CoreGraphics");
446+
SwiftType = Impl.getNamedSwiftType(M, SwiftTypeName);
447+
}
448+
471449
if (!SwiftType && !CanBeMissing) {
472450
// The required type is not defined in the standard library.
451+
// The required type is not defined in the library, or the user has not
452+
// imported the library that defines it (so `M` was null and
453+
// `getNamedSwiftType()` returned early).
473454
*IsError = true;
474455
return std::make_pair(Type(), "");
475456
}

lib/ClangImporter/MappedTypes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ MAP_STDLIB_TYPE(
155155
Impl.SwiftContext.getSwiftName(KnownFoundationEntity::NSUInteger),
156156
UnsignedWord, 0, "Int", false, DoNothing)
157157

158+
// CGFloat.
159+
MAP_TYPE("CGFloat", CGFloat, 0, "CoreFoundation", "CGFloat", false, DoNothing)
160+
158161
// CoreFoundation types.
159162
// Note that we're preserving the typealias for CFIndex.
160163
MAP_STDLIB_TYPE("CFTypeID", UnsignedWord, 0, "UInt", false, DefineAndUse)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,51 @@
11
@_exported import CoreFoundation
22

33
protocol _CFObject: Hashable {}
4+
5+
#if CGFLOAT_IN_COREFOUNDATION
6+
public struct CGFloat {
7+
#if arch(i386) || arch(arm) || arch(arm64_32)
8+
public typealias UnderlyingType = Float
9+
#elseif arch(x86_64) || arch(arm64) || arch(powerpc64le) || arch(s390x)
10+
public typealias UnderlyingType = Double
11+
#endif
12+
13+
public init() {
14+
self.value = 0.0
15+
}
16+
17+
public init(_ value: Int) {
18+
self.value = UnderlyingType(value)
19+
}
20+
21+
public init(_ value: Float) {
22+
self.value = UnderlyingType(value)
23+
}
24+
25+
public init(_ value: Double) {
26+
self.value = UnderlyingType(value)
27+
}
28+
29+
var value: UnderlyingType
30+
}
31+
32+
public func ==(lhs: CGFloat, rhs: CGFloat) -> Bool {
33+
return lhs.value == rhs.value
34+
}
35+
36+
extension CGFloat : ExpressibleByIntegerLiteral, ExpressibleByFloatLiteral, Equatable {
37+
public init(integerLiteral value: UnderlyingType) {
38+
self.value = value
39+
}
40+
41+
public init(floatLiteral value: UnderlyingType) {
42+
self.value = value
43+
}
44+
}
45+
46+
public extension Double {
47+
init(_ value: CGFloat) {
48+
self = Double(value.value)
49+
}
50+
}
51+
#endif

test/Inputs/clang-importer-sdk/swift-modules/CoreGraphics.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ public func == (lhs: CGPoint, rhs: CGPoint) -> Bool {
55
return lhs.x == rhs.x && lhs.y == rhs.y
66
}
77

8+
#if !CGFLOAT_IN_COREFOUNDATION
89
public struct CGFloat {
910
#if arch(i386) || arch(arm) || arch(arm64_32)
1011
public typealias UnderlyingType = Float
@@ -50,3 +51,4 @@ public extension Double {
5051
self = Double(value.value)
5152
}
5253
}
54+
#endif
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -DCGFLOAT_IN_COREFOUNDATION -emit-module -o %t %clang-importer-sdk-path/swift-modules/CoreFoundation.swift
13+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource) -DCGFLOAT_IN_COREFOUNDATION -emit-module -o %t %clang-importer-sdk-path/swift-modules/CoreGraphics.swift
14+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %clang-importer-sdk-path/swift-modules/Foundation.swift
15+
16+
// REQUIRES: objc_interop
17+
18+
import CoreGraphics
19+
import Foundation
20+
21+
// CHECK: @import CoreGraphics;
22+
23+
// CHECK-NOT: @class NSNumber;
24+
25+
// CHECK-LABEL: @interface Test : NSObject{{$}}
26+
public class Test: NSObject {
27+
// CHECK-NEXT: - (CGFloat)level
28+
@objc public func level() -> CGFloat { 9000.0 }
29+
// CHECK-NEXT: - (BOOL)isEnabled
30+
@objc public func isEnabled() -> Bool { true }
31+
// CHECK-NEXT: init
32+
} // CHECK-NEXT: @end

test/PrintAsObjC/bridged-known-types.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
// RUN: %empty-directory(%t)
1010
// RUN: %target-swift-frontend -typecheck %s -parse-as-library -emit-objc-header-path %t/swift.h
1111
// RUN: %FileCheck %s < %t/swift.h
12+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %clang-importer-sdk-path/swift-modules/CoreFoundation.swift
13+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource) -emit-module -o %t %clang-importer-sdk-path/swift-modules/CoreGraphics.swift
14+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %clang-importer-sdk-path/swift-modules/Foundation.swift
1215

1316
// REQUIRES: objc_interop
1417

0 commit comments

Comments
 (0)