27
27
#include " swift/AST/SwiftNameTranslation.h"
28
28
#include " swift/AST/Type.h"
29
29
#include " swift/AST/TypeVisitor.h"
30
+ #include " swift/AST/Types.h"
30
31
#include " swift/Basic/Assertions.h"
31
32
#include " swift/ClangImporter/ClangImporter.h"
32
33
#include " swift/IRGen/IRABIDetailsProvider.h"
@@ -265,6 +266,22 @@ class CFunctionSignatureTypePrinter
265
266
return ClangRepresentation::unsupported;
266
267
}
267
268
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
+
268
285
ClangRepresentation
269
286
visitTupleType (TupleType *TT, std::optional<OptionalTypeKind> optionalKind,
270
287
bool isInOutParam) {
@@ -592,6 +609,14 @@ static std::string encodeTypeInfo(const T &abiTypeInfo,
592
609
return std::move (typeEncodingOS.str ());
593
610
}
594
611
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
+
595
620
// Returns false if the given direct type is not yet supported because
596
621
// of its ABI.
597
622
template <class T >
@@ -631,7 +656,8 @@ static bool printDirectReturnOrParamCType(
631
656
// FIXME: is this "prettyfying" logic sound for multiple return values?
632
657
if (isKnownCType (valueType, typeMapping) ||
633
658
(Count == 1 && lastOffset.isZero () && !valueType->hasTypeParameter () &&
634
- valueType->isAnyClassReferenceType ())) {
659
+ (valueType->isAnyClassReferenceType () ||
660
+ isOptionalObjCExistential (valueType)))) {
635
661
prettifiedValuePrinter ();
636
662
return true ;
637
663
}
@@ -964,8 +990,12 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
964
990
// Emit 'void' in an empty parameter list for C function declarations.
965
991
functionSignatureOS << " void" ;
966
992
functionSignatureOS << ' )' ;
967
- if (!resultingRepresentation.isUnsupported ())
993
+ if (!resultingRepresentation.isUnsupported ()) {
994
+ if (resultingRepresentation.isObjCxxOnly ())
995
+ os << " #if defined(__OBJC__)\n " ;
996
+ os << " SWIFT_EXTERN " ;
968
997
os << functionSignatureOS.str ();
998
+ }
969
999
return resultingRepresentation;
970
1000
}
971
1001
@@ -1010,8 +1040,12 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
1010
1040
ClangSyntaxPrinter (functionSignatureOS)
1011
1041
.printSymbolUSRAttribute (
1012
1042
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 " ;
1014
1047
os << functionSignatureOS.str ();
1048
+ }
1015
1049
return resultingRepresentation;
1016
1050
}
1017
1051
@@ -1043,6 +1077,12 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
1043
1077
return ;
1044
1078
}
1045
1079
1080
+ if (type->isObjCExistentialType () || isOptionalObjCExistential (type)) {
1081
+ if (isInOut)
1082
+ os << ' &' ;
1083
+ namePrinter ();
1084
+ return ;
1085
+ }
1046
1086
if (auto *classDecl = type->getClassOrBoundGenericClass ()) {
1047
1087
if (classDecl->hasClangNode ()) {
1048
1088
if (isInOut)
@@ -1423,7 +1463,9 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
1423
1463
[&]() { printCallToCFunc (/* additionalParam=*/ std::nullopt); });
1424
1464
return ;
1425
1465
}
1426
- if (auto *decl = resultTy->getNominalOrBoundGenericNominal ()) {
1466
+ if (auto *decl = resultTy->getNominalOrBoundGenericNominal ();
1467
+ decl && !resultTy->isObjCExistentialType () &&
1468
+ !isOptionalObjCExistential (resultTy)) {
1427
1469
auto valueTypeReturnThunker = [&](StringRef resultPointerName) {
1428
1470
if (auto directResultType = signature.getDirectResultType ()) {
1429
1471
std::string typeEncoding =
@@ -1458,13 +1500,14 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
1458
1500
auto nonOptResultType = resultTy->getOptionalObjectType ();
1459
1501
if (!nonOptResultType)
1460
1502
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 ()));
1464
1508
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 *)" ;
1468
1511
printCallToCFunc (/* additionalParam=*/ std::nullopt);
1469
1512
os << " ;\n " ;
1470
1513
return ;
@@ -1575,6 +1618,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
1575
1618
declAndTypePrinter.printAvailability (os, FD);
1576
1619
if (!isDefinition) {
1577
1620
os << " ;\n " ;
1621
+ if (result.isObjCxxOnly ())
1622
+ os << " #endif\n " ;
1578
1623
return ;
1579
1624
}
1580
1625
@@ -1586,6 +1631,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
1586
1631
FD->getInterfaceType ()->castTo <AnyFunctionType>(), isStatic,
1587
1632
dispatchInfo);
1588
1633
os << " }\n " ;
1634
+ if (result.isObjCxxOnly ())
1635
+ os << " #endif\n " ;
1589
1636
}
1590
1637
1591
1638
// / Returns true if the given property name like `isEmpty` can be remapped
@@ -1648,6 +1695,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
1648
1695
declAndTypePrinter.printAvailability (os, accessor->getStorage ());
1649
1696
if (!isDefinition) {
1650
1697
os << " ;\n " ;
1698
+ if (result.isObjCxxOnly ())
1699
+ os << " #endif\n " ;
1651
1700
return ;
1652
1701
}
1653
1702
os << " {\n " ;
@@ -1657,6 +1706,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
1657
1706
accessor->getParameters (),
1658
1707
/* hasThrows=*/ false , nullptr , isStatic, dispatchInfo);
1659
1708
os << " }\n " ;
1709
+ if (result.isObjCxxOnly ())
1710
+ os << " #endif\n " ;
1660
1711
}
1661
1712
1662
1713
void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod (
@@ -1682,6 +1733,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
1682
1733
declAndTypePrinter.printAvailability (os, accessor->getStorage ());
1683
1734
if (!isDefinition) {
1684
1735
os << " ;\n " ;
1736
+ if (result.isObjCxxOnly ())
1737
+ os << " #endif\n " ;
1685
1738
if (multiParam)
1686
1739
os << " #endif // #if __cplusplus >= 202302L\n " ;
1687
1740
return ;
@@ -1693,6 +1746,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
1693
1746
accessor->getModuleContext (), resultTy, accessor->getParameters (),
1694
1747
/* hasThrows=*/ false , nullptr , /* isStatic=*/ false , dispatchInfo);
1695
1748
os << " }\n " ;
1749
+ if (result.isObjCxxOnly ())
1750
+ os << " #endif\n " ;
1696
1751
if (multiParam)
1697
1752
os << " #endif // #if __cplusplus >= 202302L\n " ;
1698
1753
}
0 commit comments