2727#include " swift/AST/SwiftNameTranslation.h"
2828#include " swift/AST/Type.h"
2929#include " swift/AST/TypeVisitor.h"
30+ #include " swift/AST/Types.h"
3031#include " swift/Basic/Assertions.h"
3132#include " swift/ClangImporter/ClangImporter.h"
3233#include " swift/IRGen/IRABIDetailsProvider.h"
@@ -265,6 +266,22 @@ class CFunctionSignatureTypePrinter
265266 return ClangRepresentation::unsupported;
266267 }
267268
269+ ClangRepresentation
270+ visitExistentialType (ExistentialType *ty,
271+ std::optional<OptionalTypeKind> optionalKind,
272+ bool isInOutParam) {
273+ if (ty->isObjCExistentialType ()) {
274+ declPrinter.withOutputStream (os).print (ty, optionalKind);
275+ if (isInOutParam) {
276+ os << " __strong" ;
277+ printInoutTypeModifier ();
278+ }
279+ return ClangRepresentation::objcxxonly;
280+ }
281+
282+ return visitPart (ty->getConstraintType (), optionalKind, isInOutParam);
283+ }
284+
268285 ClangRepresentation
269286 visitTupleType (TupleType *TT, std::optional<OptionalTypeKind> optionalKind,
270287 bool isInOutParam) {
@@ -592,6 +609,14 @@ static std::string encodeTypeInfo(const T &abiTypeInfo,
592609 return std::move (typeEncodingOS.str ());
593610}
594611
612+ static bool isOptionalObjCExistential (Type ty) {
613+ if (auto obj = ty->getOptionalObjectType ()) {
614+ if (obj->isObjCExistentialType ())
615+ return true ;
616+ }
617+ return false ;
618+ }
619+
595620// Returns false if the given direct type is not yet supported because
596621// of its ABI.
597622template <class T >
@@ -631,7 +656,8 @@ static bool printDirectReturnOrParamCType(
631656 // FIXME: is this "prettyfying" logic sound for multiple return values?
632657 if (isKnownCType (valueType, typeMapping) ||
633658 (Count == 1 && lastOffset.isZero () && !valueType->hasTypeParameter () &&
634- valueType->isAnyClassReferenceType ())) {
659+ (valueType->isAnyClassReferenceType () ||
660+ isOptionalObjCExistential (valueType)))) {
635661 prettifiedValuePrinter ();
636662 return true ;
637663 }
@@ -964,8 +990,12 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
964990 // Emit 'void' in an empty parameter list for C function declarations.
965991 functionSignatureOS << " void" ;
966992 functionSignatureOS << ' )' ;
967- if (!resultingRepresentation.isUnsupported ())
993+ if (!resultingRepresentation.isUnsupported ()) {
994+ if (resultingRepresentation.isObjCxxOnly ())
995+ os << " #if defined(__OBJC__)\n " ;
996+ os << " SWIFT_EXTERN " ;
968997 os << functionSignatureOS.str ();
998+ }
969999 return resultingRepresentation;
9701000 }
9711001
@@ -1010,8 +1040,12 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
10101040 ClangSyntaxPrinter (functionSignatureOS)
10111041 .printSymbolUSRAttribute (
10121042 modifiers.symbolUSROverride ? modifiers.symbolUSROverride : FD);
1013- if (!resultingRepresentation.isUnsupported ())
1043+ if (!resultingRepresentation.isUnsupported ()) {
1044+ if (resultingRepresentation.isObjCxxOnly () &&
1045+ outputLang == OutputLanguageMode::Cxx)
1046+ os << " #if defined(__OBJC__)\n " ;
10141047 os << functionSignatureOS.str ();
1048+ }
10151049 return resultingRepresentation;
10161050}
10171051
@@ -1043,6 +1077,12 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
10431077 return ;
10441078 }
10451079
1080+ if (type->isObjCExistentialType () || isOptionalObjCExistential (type)) {
1081+ if (isInOut)
1082+ os << ' &' ;
1083+ namePrinter ();
1084+ return ;
1085+ }
10461086 if (auto *classDecl = type->getClassOrBoundGenericClass ()) {
10471087 if (classDecl->hasClangNode ()) {
10481088 if (isInOut)
@@ -1423,7 +1463,9 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
14231463 [&]() { printCallToCFunc (/* additionalParam=*/ std::nullopt ); });
14241464 return ;
14251465 }
1426- if (auto *decl = resultTy->getNominalOrBoundGenericNominal ()) {
1466+ if (auto *decl = resultTy->getNominalOrBoundGenericNominal ();
1467+ decl && !resultTy->isObjCExistentialType () &&
1468+ !isOptionalObjCExistential (resultTy)) {
14271469 auto valueTypeReturnThunker = [&](StringRef resultPointerName) {
14281470 if (auto directResultType = signature.getDirectResultType ()) {
14291471 std::string typeEncoding =
@@ -1458,13 +1500,14 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
14581500 auto nonOptResultType = resultTy->getOptionalObjectType ();
14591501 if (!nonOptResultType)
14601502 nonOptResultType = resultTy;
1461- if (auto *classDecl = nonOptResultType->getClassOrBoundGenericClass ()) {
1462- assert (classDecl->hasClangNode ());
1463- assert (isa<clang::ObjCContainerDecl>(classDecl->getClangDecl ()));
1503+ if (auto *classDecl = nonOptResultType->getClassOrBoundGenericClass ();
1504+ classDecl || nonOptResultType->isObjCExistentialType ()) {
1505+ assert (!classDecl || classDecl->hasClangNode ());
1506+ assert (!classDecl ||
1507+ isa<clang::ObjCContainerDecl>(classDecl->getClangDecl ()));
14641508 os << " return (__bridge_transfer " ;
1465- ClangSyntaxPrinter (os).printIdentifier (
1466- cast<clang::NamedDecl>(classDecl->getClangDecl ())->getName ());
1467- os << " *)(__bridge void *)" ;
1509+ declPrinter.withOutputStream (os).print (nonOptResultType);
1510+ os << " )(__bridge void *)" ;
14681511 printCallToCFunc (/* additionalParam=*/ std::nullopt );
14691512 os << " ;\n " ;
14701513 return ;
@@ -1575,6 +1618,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
15751618 declAndTypePrinter.printAvailability (os, FD);
15761619 if (!isDefinition) {
15771620 os << " ;\n " ;
1621+ if (result.isObjCxxOnly ())
1622+ os << " #endif\n " ;
15781623 return ;
15791624 }
15801625
@@ -1586,6 +1631,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
15861631 FD->getInterfaceType ()->castTo <AnyFunctionType>(), isStatic,
15871632 dispatchInfo);
15881633 os << " }\n " ;
1634+ if (result.isObjCxxOnly ())
1635+ os << " #endif\n " ;
15891636}
15901637
15911638// / Returns true if the given property name like `isEmpty` can be remapped
@@ -1648,6 +1695,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
16481695 declAndTypePrinter.printAvailability (os, accessor->getStorage ());
16491696 if (!isDefinition) {
16501697 os << " ;\n " ;
1698+ if (result.isObjCxxOnly ())
1699+ os << " #endif\n " ;
16511700 return ;
16521701 }
16531702 os << " {\n " ;
@@ -1657,6 +1706,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
16571706 accessor->getParameters (),
16581707 /* hasThrows=*/ false , nullptr , isStatic, dispatchInfo);
16591708 os << " }\n " ;
1709+ if (result.isObjCxxOnly ())
1710+ os << " #endif\n " ;
16601711}
16611712
16621713void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod (
@@ -1682,6 +1733,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
16821733 declAndTypePrinter.printAvailability (os, accessor->getStorage ());
16831734 if (!isDefinition) {
16841735 os << " ;\n " ;
1736+ if (result.isObjCxxOnly ())
1737+ os << " #endif\n " ;
16851738 if (multiParam)
16861739 os << " #endif // #if __cplusplus >= 202302L\n " ;
16871740 return ;
@@ -1693,6 +1746,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
16931746 accessor->getModuleContext (), resultTy, accessor->getParameters (),
16941747 /* hasThrows=*/ false , nullptr , /* isStatic=*/ false , dispatchInfo);
16951748 os << " }\n " ;
1749+ if (result.isObjCxxOnly ())
1750+ os << " #endif\n " ;
16961751 if (multiParam)
16971752 os << " #endif // #if __cplusplus >= 202302L\n " ;
16981753}
0 commit comments