From 1861073cf12052d8b517b98c86f79817efb885cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Horv=C3=A1th?= Date: Fri, 8 Aug 2025 22:28:21 +0100 Subject: [PATCH] [6.2][cxx-interop] Fix passing optional CoreFoundation types from Swift to C++ ExplanationThese types are passed around as reference counted pointers, so the optional representation of them are nullable pointers. Previously, we tried to wrap them in swift::Optional. Issues: rdar://157667946 Original PRs: #83609 Risk: Low, the fix is narrow. Testing: Added a compiler test. Reviewers: @hnrklssn --- lib/PrintAsClang/PrintClangFunction.cpp | 6 ++++-- .../stdlib/core-foundation-types-in-cxx.swift | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/PrintAsClang/PrintClangFunction.cpp b/lib/PrintAsClang/PrintClangFunction.cpp index 1bd546494efbf..52dcaa6e1bf16 100644 --- a/lib/PrintAsClang/PrintClangFunction.cpp +++ b/lib/PrintAsClang/PrintClangFunction.cpp @@ -622,7 +622,8 @@ static bool isOptionalForeignReferenceType(Type ty) { if (auto obj = ty->getOptionalObjectType()) { if (const auto *cd = dyn_cast_or_null(obj->getNominalOrBoundGenericNominal())) - return cd->isForeignReferenceType(); + return cd->isForeignReferenceType() || + cd->getForeignClassKind() == ClassDecl::ForeignKind::CFType; } return false; } @@ -1780,7 +1781,8 @@ bool DeclAndTypeClangFunctionPrinter::hasKnownOptionalNullableCxxMapping( return typeInfo->canBeNullable; } if (const auto *cd = dyn_cast(nominal)) - if (cd->isForeignReferenceType()) + if (cd->isForeignReferenceType() || + cd->getForeignClassKind() == ClassDecl::ForeignKind::CFType) return true; return isa_and_nonnull(nominal->getClangDecl()); } diff --git a/test/Interop/SwiftToCxx/stdlib/core-foundation-types-in-cxx.swift b/test/Interop/SwiftToCxx/stdlib/core-foundation-types-in-cxx.swift index 0a924713c4cea..aa62cd38ec94d 100644 --- a/test/Interop/SwiftToCxx/stdlib/core-foundation-types-in-cxx.swift +++ b/test/Interop/SwiftToCxx/stdlib/core-foundation-types-in-cxx.swift @@ -16,6 +16,12 @@ public func foobar(_ a: CFData) -> Bool { true } +public func returnsCFDate() -> CFDate? { + nil +} + +public func takesCFDate(x: CFDate?) {} + public func networkThing() -> in_addr? { return nil } @@ -25,4 +31,9 @@ public enum MyEnum { } // CHECK: SWIFT_EXTERN bool $s17UseCoreFoundation6foobarySbSo9CFDataRefaF(CFDataRef _Nonnull a) SWIFT_NOEXCEPT SWIFT_CALL; // foobar(_:) +// CHECK: SWIFT_EXTERN CFDateRef _Nullable $s17UseCoreFoundation13returnsCFDateSo0E3RefaSgyF(void) SWIFT_NOEXCEPT SWIFT_CALL; // returnsCFDate() +// CHECK: SWIFT_EXTERN void $s17UseCoreFoundation11takesCFDate1xySo0E3RefaSg_tF(CFDateRef _Nullable x) SWIFT_NOEXCEPT SWIFT_CALL; // takesCFDate(x:) + // CHECK: SWIFT_INLINE_THUNK swift::Optional networkThing() noexcept SWIFT_SYMBOL("s:17UseCoreFoundation12networkThingSo7in_addrVSgyF") SWIFT_WARN_UNUSED_RESULT { +// CHECK: SWIFT_INLINE_THUNK CFDateRef _Nullable returnsCFDate() noexcept SWIFT_SYMBOL("s:17UseCoreFoundation13returnsCFDateSo0E3RefaSgyF") SWIFT_WARN_UNUSED_RESULT { +// CHECK: SWIFT_INLINE_THUNK void takesCFDate(CFDateRef _Nullable x) noexcept SWIFT_SYMBOL("s:17UseCoreFoundation11takesCFDate1xySo0E3RefaSg_tF") {