Skip to content

Commit d631b9a

Browse files
author
Gabor Horvath
committed
[cxx-interop] Support foreing reference types in generic context
Print the type traits in reverse interop to enable the use of foreign reference type in generics like Swift arrays. Also make sure optional foreign reference types can be passed around as raw pointers. rdar://108139769
1 parent a8111e4 commit d631b9a

File tree

4 files changed

+30
-7
lines changed

4 files changed

+30
-7
lines changed

lib/PrintAsClang/ModuleContentsWriter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,8 +579,9 @@ class ModuleWriter {
579579
forwardDeclareCxxValueTypeIfNeeded(NTD);
580580
else if (isa<StructDecl>(TD) && NTD->hasClangNode())
581581
emitReferencedClangTypeMetadata(NTD);
582-
else if (isa<ClassDecl>(TD) && TD->isObjC())
583-
emitReferencedClangTypeMetadata(NTD);
582+
else if (const auto *cd = dyn_cast<ClassDecl>(TD))
583+
if (cd->isObjC() || cd->isForeignReferenceType())
584+
emitReferencedClangTypeMetadata(NTD);
584585
} else if (auto TAD = dyn_cast<TypeAliasDecl>(TD)) {
585586
if (TAD->hasClangNode())
586587
emitReferencedClangTypeMetadata(TAD);

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,15 @@ static bool isOptionalObjCExistential(Type ty) {
618618
return false;
619619
}
620620

621+
static bool isOptionalForeignReferenceType(Type ty) {
622+
if (auto obj = ty->getOptionalObjectType()) {
623+
if (const auto *cd =
624+
dyn_cast_or_null<ClassDecl>(obj->getNominalOrBoundGenericNominal()))
625+
return cd->isForeignReferenceType();
626+
}
627+
return false;
628+
}
629+
621630
// Returns false if the given direct type is not yet supported because
622631
// of its ABI.
623632
template <class T>
@@ -658,7 +667,8 @@ static bool printDirectReturnOrParamCType(
658667
if (isKnownCType(valueType, typeMapping) ||
659668
(Count == 1 && lastOffset.isZero() && !valueType->hasTypeParameter() &&
660669
(valueType->isAnyClassReferenceType() ||
661-
isOptionalObjCExistential(valueType)))) {
670+
isOptionalObjCExistential(valueType) ||
671+
isOptionalForeignReferenceType(valueType)))) {
662672
prettifiedValuePrinter();
663673
return true;
664674
}
@@ -1506,10 +1516,9 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
15061516
if (!nonOptResultType)
15071517
nonOptResultType = resultTy;
15081518
if (auto *classDecl = nonOptResultType->getClassOrBoundGenericClass();
1509-
classDecl || nonOptResultType->isObjCExistentialType()) {
1519+
(classDecl && isa<clang::ObjCContainerDecl>(classDecl->getClangDecl())) ||
1520+
nonOptResultType->isObjCExistentialType()) {
15101521
assert(!classDecl || classDecl->hasClangNode());
1511-
assert(!classDecl ||
1512-
isa<clang::ObjCContainerDecl>(classDecl->getClangDecl()));
15131522
os << "return (__bridge_transfer ";
15141523
declPrinter.withOutputStream(os).print(nonOptResultType);
15151524
os << ")(__bridge void *)";
@@ -1766,6 +1775,9 @@ bool DeclAndTypeClangFunctionPrinter::hasKnownOptionalNullableCxxMapping(
17661775
optionalObjectType->getNominalOrBoundGenericNominal())) {
17671776
return typeInfo->canBeNullable;
17681777
}
1778+
if (const auto *cd = dyn_cast<ClassDecl>(nominal))
1779+
if (cd->isForeignReferenceType())
1780+
return true;
17691781
return isa_and_nonnull<clang::ObjCInterfaceDecl>(nominal->getClangDecl());
17701782
}
17711783
}

lib/PrintAsClang/PrintClangValueType.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,9 @@ void ClangValueTypePrinter::printTypeGenericTraits(
641641
typeDecl, typeMetadataFuncName, typeMetadataFuncRequirements);
642642
});
643643
}
644-
bool addPointer = typeDecl->isObjC();
644+
auto classDecl = dyn_cast<ClassDecl>(typeDecl);
645+
bool addPointer =
646+
typeDecl->isObjC() || (classDecl && classDecl->isForeignReferenceType());
645647

646648
os << "#pragma clang diagnostic push\n";
647649
os << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";

test/Interop/CxxToSwiftToCxx/allow-shared-frt-back-to-cxx.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// RUN: split-file %s %t
33

44
// RUN: %target-swift-frontend %t/use-cxx-types.swift -module-name UseCxxTy -typecheck -verify -emit-clang-header-path %t/UseCxxTy.h -I %t -enable-experimental-cxx-interop -clang-header-expose-decls=all-public -disable-availability-checking
5+
// RUN: cat %t/header.h >> %t/full-header.h
6+
// RUN: cat %t/UseCxxTy.h >> %t/full-header.h
7+
// RUN: %target-interop-build-clangxx -std=c++20 -c -xc++-header %t/full-header.h -o %t/o.o
58

69
// RUN: %FileCheck %s < %t/UseCxxTy.h
710

@@ -29,6 +32,11 @@ import CxxTest
2932
public func consumeSharedFRT(_ x: consuming SharedFRT) {}
3033
public func takeSharedFRT(_ x: SharedFRT) {}
3134

35+
public func takeSharedFRTGeneric(_ x: [SharedFRT]) {}
36+
public func returnSharedFRTGeneric() -> [SharedFRT] { [] }
37+
public func takeSharedFRTOptional(_ x: SharedFRT?) {}
38+
public func returnSharedFRTOptional() -> SharedFRT? { nil }
39+
3240
// CHECK: SWIFT_EXTERN void $s8UseCxxTy16consumeSharedFRTyySo0eF0VnF(SharedFRT *_Nonnull x) SWIFT_NOEXCEPT SWIFT_CALL; // consumeSharedFRT(_:)
3341

3442
// CHECK: SWIFT_EXTERN void $s8UseCxxTy13takeSharedFRTyySo0eF0VF(SharedFRT *_Nonnull x) SWIFT_NOEXCEPT SWIFT_CALL; // takeSharedFRT(_:)

0 commit comments

Comments
 (0)