mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[cxx-interop] Support ObjC protocols in C++ interop
This patch introduces handling of ObjC protocols similar to how ObjC classes work. Since this only works in ObjC++, all declarations containing ObjC protocols will be protected by the __OBJC__ macro. This patch results in some `_bridgeObjC` methods being exposed, we might end up hiding those in the future, but there is no harm having them in the interop header for the interim period. rdar://136757913
This commit is contained in:
@@ -67,7 +67,7 @@ StringRef
|
||||
getNameForCxx(const ValueDecl *VD,
|
||||
CustomNamesOnly_t customNamesOnly = objc_translation::Normal);
|
||||
|
||||
enum RepresentationKind { Representable, Unsupported };
|
||||
enum RepresentationKind { Representable, ObjCxxOnly, Unsupported };
|
||||
|
||||
enum RepresentationError {
|
||||
UnrepresentableObjC,
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include <optional>
|
||||
|
||||
using namespace swift;
|
||||
|
||||
@@ -232,8 +233,11 @@ swift::cxx_translation::getDeclRepresentation(const ValueDecl *VD) {
|
||||
genericSignature = AFD->getGenericSignature();
|
||||
}
|
||||
if (const auto *typeDecl = dyn_cast<NominalTypeDecl>(VD)) {
|
||||
if (isa<ProtocolDecl>(typeDecl))
|
||||
if (isa<ProtocolDecl>(typeDecl)) {
|
||||
if (typeDecl->hasClangNode())
|
||||
return {ObjCxxOnly, std::nullopt};
|
||||
return {Unsupported, UnrepresentableProtocol};
|
||||
}
|
||||
// Swift's consume semantics are not yet supported in C++.
|
||||
if (!typeDecl->canBeCopyable())
|
||||
return {Unsupported, UnrepresentableMoveOnly};
|
||||
@@ -336,7 +340,7 @@ bool swift::cxx_translation::isExposableToCxx(GenericSignature genericSig) {
|
||||
return false;
|
||||
|
||||
auto proto = req.getProtocolDecl();
|
||||
if (!proto->isMarkerProtocol())
|
||||
if (!proto->isMarkerProtocol() && !proto->hasClangNode())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ void ClangSyntaxPrinter::printObjCBlock(
|
||||
llvm::function_ref<void(raw_ostream &OS)> bodyPrinter) const {
|
||||
os << "#if defined(__OBJC__)\n";
|
||||
bodyPrinter(os);
|
||||
os << "\n#endif\n";
|
||||
os << "\n#endif // defined(__OBJC__)\n";
|
||||
}
|
||||
|
||||
void ClangSyntaxPrinter::printSwiftImplQualifier() const {
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "swift/AST/SwiftNameTranslation.h"
|
||||
#include "swift/AST/TypeCheckRequests.h"
|
||||
#include "swift/AST/TypeVisitor.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
#include "swift/IDE/CommentConversion.h"
|
||||
#include "swift/IRGen/IRABIDetailsProvider.h"
|
||||
@@ -1046,6 +1047,7 @@ private:
|
||||
auto result = methodTy->getResult();
|
||||
if (result->isUninhabited())
|
||||
return getASTContext().TheEmptyTupleType;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1493,8 +1495,6 @@ private:
|
||||
StringRef comment = "") {
|
||||
std::string cRepresentationString;
|
||||
llvm::raw_string_ostream cRepresentationOS(cRepresentationString);
|
||||
cRepresentationOS << "SWIFT_EXTERN ";
|
||||
|
||||
DeclAndTypeClangFunctionPrinter funcPrinter(
|
||||
cRepresentationOS, owningPrinter.prologueOS, owningPrinter.typeMapping,
|
||||
owningPrinter.interopContext, owningPrinter);
|
||||
@@ -1528,6 +1528,8 @@ private:
|
||||
FD->getName().print(os);
|
||||
}
|
||||
os << "\n";
|
||||
if (representation.isObjCxxOnly())
|
||||
os << "#endif\n";
|
||||
return representation;
|
||||
}
|
||||
|
||||
@@ -1636,6 +1638,8 @@ private:
|
||||
/*typeDeclContext=*/nullptr, FD->getModuleContext(), resultTy,
|
||||
FD->getParameters(), funcTy->isThrowing(), funcTy);
|
||||
os << "}\n";
|
||||
if (result.isObjCxxOnly())
|
||||
os << "#endif\n";
|
||||
}
|
||||
|
||||
enum class PrintLeadingSpace : bool {
|
||||
@@ -2982,8 +2986,9 @@ void DeclAndTypePrinter::print(const Decl *D) {
|
||||
getImpl().print(D);
|
||||
}
|
||||
|
||||
void DeclAndTypePrinter::print(Type ty) {
|
||||
getImpl().print(ty, /*overridingOptionality*/ std::nullopt);
|
||||
void DeclAndTypePrinter::print(
|
||||
Type ty, std::optional<OptionalTypeKind> overrideOptionalTypeKind) {
|
||||
getImpl().print(ty, overrideOptionalTypeKind);
|
||||
}
|
||||
|
||||
void DeclAndTypePrinter::printTypeName(raw_ostream &os, Type ty,
|
||||
|
||||
@@ -80,7 +80,7 @@ private:
|
||||
public:
|
||||
DeclAndTypePrinter(ModuleDecl &mod, raw_ostream &out, raw_ostream &prologueOS,
|
||||
raw_ostream &outOfLineDefinitionsOS,
|
||||
DelayedMemberSet &delayed,
|
||||
const DelayedMemberSet &delayed,
|
||||
CxxDeclEmissionScope &topLevelEmissionScope,
|
||||
PrimitiveTypeMapping &typeMapping,
|
||||
SwiftToClangInteropContext &interopContext,
|
||||
@@ -103,6 +103,13 @@ public:
|
||||
return *cxxDeclEmissionScope;
|
||||
}
|
||||
|
||||
DeclAndTypePrinter withOutputStream(raw_ostream &s) {
|
||||
return DeclAndTypePrinter(
|
||||
M, s, prologueOS, outOfLineDefinitionsOS, objcDelayedMembers,
|
||||
*cxxDeclEmissionScope, typeMapping, interopContext, minRequiredAccess,
|
||||
requiresExposedAttribute, exposedModules, outputLang);
|
||||
}
|
||||
|
||||
void setCxxDeclEmissionScope(CxxDeclEmissionScope &scope) {
|
||||
cxxDeclEmissionScope = &scope;
|
||||
}
|
||||
@@ -116,7 +123,8 @@ public:
|
||||
bool isVisible(const ValueDecl *vd) const;
|
||||
|
||||
void print(const Decl *D);
|
||||
void print(Type ty);
|
||||
void print(Type ty, std::optional<OptionalTypeKind> overrideOptionalTypeKind =
|
||||
std::nullopt);
|
||||
|
||||
/// Prints the name of the type including generic arguments.
|
||||
void printTypeName(raw_ostream &os, Type ty, const ModuleDecl *moduleContext);
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "swift/AST/SwiftNameTranslation.h"
|
||||
#include "swift/AST/Type.h"
|
||||
#include "swift/AST/TypeVisitor.h"
|
||||
#include "swift/AST/Types.h"
|
||||
#include "swift/Basic/Assertions.h"
|
||||
#include "swift/ClangImporter/ClangImporter.h"
|
||||
#include "swift/IRGen/IRABIDetailsProvider.h"
|
||||
@@ -265,6 +266,22 @@ public:
|
||||
return ClangRepresentation::unsupported;
|
||||
}
|
||||
|
||||
ClangRepresentation
|
||||
visitExistentialType(ExistentialType *ty,
|
||||
std::optional<OptionalTypeKind> optionalKind,
|
||||
bool isInOutParam) {
|
||||
if (ty->isObjCExistentialType()) {
|
||||
declPrinter.withOutputStream(os).print(ty, optionalKind);
|
||||
if (isInOutParam) {
|
||||
os << " __strong";
|
||||
printInoutTypeModifier();
|
||||
}
|
||||
return ClangRepresentation::objcxxonly;
|
||||
}
|
||||
|
||||
return visitPart(ty->getConstraintType(), optionalKind, isInOutParam);
|
||||
}
|
||||
|
||||
ClangRepresentation
|
||||
visitTupleType(TupleType *TT, std::optional<OptionalTypeKind> optionalKind,
|
||||
bool isInOutParam) {
|
||||
@@ -592,6 +609,14 @@ static std::string encodeTypeInfo(const T &abiTypeInfo,
|
||||
return std::move(typeEncodingOS.str());
|
||||
}
|
||||
|
||||
static bool isOptionalObjCExistential(Type ty) {
|
||||
if (auto obj = ty->getOptionalObjectType()) {
|
||||
if (obj->isObjCExistentialType())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns false if the given direct type is not yet supported because
|
||||
// of its ABI.
|
||||
template <class T>
|
||||
@@ -631,7 +656,8 @@ static bool printDirectReturnOrParamCType(
|
||||
// FIXME: is this "prettyfying" logic sound for multiple return values?
|
||||
if (isKnownCType(valueType, typeMapping) ||
|
||||
(Count == 1 && lastOffset.isZero() && !valueType->hasTypeParameter() &&
|
||||
valueType->isAnyClassReferenceType())) {
|
||||
(valueType->isAnyClassReferenceType() ||
|
||||
isOptionalObjCExistential(valueType)))) {
|
||||
prettifiedValuePrinter();
|
||||
return true;
|
||||
}
|
||||
@@ -964,8 +990,12 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
|
||||
// Emit 'void' in an empty parameter list for C function declarations.
|
||||
functionSignatureOS << "void";
|
||||
functionSignatureOS << ')';
|
||||
if (!resultingRepresentation.isUnsupported())
|
||||
if (!resultingRepresentation.isUnsupported()) {
|
||||
if (resultingRepresentation.isObjCxxOnly())
|
||||
os << "#if defined(__OBJC__)\n";
|
||||
os << "SWIFT_EXTERN ";
|
||||
os << functionSignatureOS.str();
|
||||
}
|
||||
return resultingRepresentation;
|
||||
}
|
||||
|
||||
@@ -1010,8 +1040,12 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
|
||||
ClangSyntaxPrinter(functionSignatureOS)
|
||||
.printSymbolUSRAttribute(
|
||||
modifiers.symbolUSROverride ? modifiers.symbolUSROverride : FD);
|
||||
if (!resultingRepresentation.isUnsupported())
|
||||
if (!resultingRepresentation.isUnsupported()) {
|
||||
if (resultingRepresentation.isObjCxxOnly() &&
|
||||
outputLang == OutputLanguageMode::Cxx)
|
||||
os << "#if defined(__OBJC__)\n";
|
||||
os << functionSignatureOS.str();
|
||||
}
|
||||
return resultingRepresentation;
|
||||
}
|
||||
|
||||
@@ -1043,6 +1077,12 @@ void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse(
|
||||
return;
|
||||
}
|
||||
|
||||
if (type->isObjCExistentialType() || isOptionalObjCExistential(type)) {
|
||||
if (isInOut)
|
||||
os << '&';
|
||||
namePrinter();
|
||||
return;
|
||||
}
|
||||
if (auto *classDecl = type->getClassOrBoundGenericClass()) {
|
||||
if (classDecl->hasClangNode()) {
|
||||
if (isInOut)
|
||||
@@ -1423,7 +1463,9 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
|
||||
[&]() { printCallToCFunc(/*additionalParam=*/std::nullopt); });
|
||||
return;
|
||||
}
|
||||
if (auto *decl = resultTy->getNominalOrBoundGenericNominal()) {
|
||||
if (auto *decl = resultTy->getNominalOrBoundGenericNominal();
|
||||
decl && !resultTy->isObjCExistentialType() &&
|
||||
!isOptionalObjCExistential(resultTy)) {
|
||||
auto valueTypeReturnThunker = [&](StringRef resultPointerName) {
|
||||
if (auto directResultType = signature.getDirectResultType()) {
|
||||
std::string typeEncoding =
|
||||
@@ -1458,13 +1500,14 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
|
||||
auto nonOptResultType = resultTy->getOptionalObjectType();
|
||||
if (!nonOptResultType)
|
||||
nonOptResultType = resultTy;
|
||||
if (auto *classDecl = nonOptResultType->getClassOrBoundGenericClass()) {
|
||||
assert(classDecl->hasClangNode());
|
||||
assert(isa<clang::ObjCContainerDecl>(classDecl->getClangDecl()));
|
||||
if (auto *classDecl = nonOptResultType->getClassOrBoundGenericClass();
|
||||
classDecl || nonOptResultType->isObjCExistentialType()) {
|
||||
assert(!classDecl || classDecl->hasClangNode());
|
||||
assert(!classDecl ||
|
||||
isa<clang::ObjCContainerDecl>(classDecl->getClangDecl()));
|
||||
os << "return (__bridge_transfer ";
|
||||
ClangSyntaxPrinter(os).printIdentifier(
|
||||
cast<clang::NamedDecl>(classDecl->getClangDecl())->getName());
|
||||
os << " *)(__bridge void *)";
|
||||
declPrinter.withOutputStream(os).print(nonOptResultType);
|
||||
os << ")(__bridge void *)";
|
||||
printCallToCFunc(/*additionalParam=*/std::nullopt);
|
||||
os << ";\n";
|
||||
return;
|
||||
@@ -1575,6 +1618,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
|
||||
declAndTypePrinter.printAvailability(os, FD);
|
||||
if (!isDefinition) {
|
||||
os << ";\n";
|
||||
if (result.isObjCxxOnly())
|
||||
os << "#endif\n";
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1586,6 +1631,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
|
||||
FD->getInterfaceType()->castTo<AnyFunctionType>(), isStatic,
|
||||
dispatchInfo);
|
||||
os << " }\n";
|
||||
if (result.isObjCxxOnly())
|
||||
os << "#endif\n";
|
||||
}
|
||||
|
||||
/// Returns true if the given property name like `isEmpty` can be remapped
|
||||
@@ -1648,6 +1695,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
|
||||
declAndTypePrinter.printAvailability(os, accessor->getStorage());
|
||||
if (!isDefinition) {
|
||||
os << ";\n";
|
||||
if (result.isObjCxxOnly())
|
||||
os << "#endif\n";
|
||||
return;
|
||||
}
|
||||
os << " {\n";
|
||||
@@ -1657,6 +1706,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod(
|
||||
accessor->getParameters(),
|
||||
/*hasThrows=*/false, nullptr, isStatic, dispatchInfo);
|
||||
os << " }\n";
|
||||
if (result.isObjCxxOnly())
|
||||
os << "#endif\n";
|
||||
}
|
||||
|
||||
void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
|
||||
@@ -1682,6 +1733,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
|
||||
declAndTypePrinter.printAvailability(os, accessor->getStorage());
|
||||
if (!isDefinition) {
|
||||
os << ";\n";
|
||||
if (result.isObjCxxOnly())
|
||||
os << "#endif\n";
|
||||
if (multiParam)
|
||||
os << "#endif // #if __cplusplus >= 202302L\n";
|
||||
return;
|
||||
@@ -1693,6 +1746,8 @@ void DeclAndTypeClangFunctionPrinter::printCxxSubscriptAccessorMethod(
|
||||
accessor->getModuleContext(), resultTy, accessor->getParameters(),
|
||||
/*hasThrows=*/false, nullptr, /*isStatic=*/false, dispatchInfo);
|
||||
os << " }\n";
|
||||
if (result.isObjCxxOnly())
|
||||
os << "#endif\n";
|
||||
if (multiParam)
|
||||
os << "#endif // #if __cplusplus >= 202302L\n";
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class SwiftToClangInteropContext;
|
||||
class DeclAndTypePrinter;
|
||||
|
||||
struct ClangRepresentation {
|
||||
enum Kind { representable, unsupported };
|
||||
enum Kind { representable, objcxxonly, unsupported };
|
||||
|
||||
ClangRepresentation(Kind kind) : kind(kind) {}
|
||||
|
||||
@@ -50,8 +50,14 @@ struct ClangRepresentation {
|
||||
/// language mode.
|
||||
bool isUnsupported() const { return kind == unsupported; }
|
||||
|
||||
/// Returns true if the given Swift node is only supported in
|
||||
/// Objective C++ mode.
|
||||
bool isObjCxxOnly() const { return kind == objcxxonly; }
|
||||
|
||||
const ClangRepresentation &merge(ClangRepresentation other) {
|
||||
if (kind != unsupported)
|
||||
if (other.kind == unsupported)
|
||||
kind = unsupported;
|
||||
else if (kind == representable)
|
||||
kind = other.kind;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,16 @@
|
||||
-(int)getValue;
|
||||
@end
|
||||
|
||||
@protocol ObjCProtocol
|
||||
@required
|
||||
- (int)method;
|
||||
@end
|
||||
|
||||
@interface ObjCKlassConforming : NSObject<ObjCProtocol>
|
||||
- (ObjCKlassConforming * _Nonnull) init:(int)x;
|
||||
- (int)method;
|
||||
@end
|
||||
|
||||
//--- module.modulemap
|
||||
module ObjCTest {
|
||||
header "header.h"
|
||||
@@ -64,6 +74,18 @@ public func passThroughObjClass(_ x: ObjCKlass?) -> ObjCKlass? {
|
||||
return x
|
||||
}
|
||||
|
||||
public func takeObjCProtocol(_ x: ObjCProtocol) {
|
||||
print("ObjCKlassConforming:", x.method());
|
||||
}
|
||||
|
||||
public func retObjCProtocol() -> ObjCProtocol {
|
||||
return ObjCKlassConforming(2)
|
||||
}
|
||||
|
||||
public func retObjCProtocolNullable() -> ObjCProtocol? {
|
||||
return ObjCKlassConforming(2)
|
||||
}
|
||||
|
||||
//--- use-swift-objc-types.mm
|
||||
|
||||
#include "header.h"
|
||||
@@ -98,6 +120,30 @@ struct DeinitPrinter {
|
||||
|
||||
@end
|
||||
|
||||
struct DeinitPrinter2 {
|
||||
~DeinitPrinter2() {
|
||||
puts("destroy ObjCKlassConforming");
|
||||
--globalCounter;
|
||||
}
|
||||
};
|
||||
|
||||
@implementation ObjCKlassConforming {
|
||||
int _x;
|
||||
DeinitPrinter2 _printer;
|
||||
}
|
||||
- (ObjCKlassConforming * _Nonnull) init:(int)x {
|
||||
ObjCKlassConforming *result = [super init];
|
||||
result->_x = x;
|
||||
puts("create ObjCKlassConforming");
|
||||
++globalCounter;
|
||||
return result;
|
||||
}
|
||||
|
||||
-(int)method {
|
||||
return self->_x;
|
||||
}
|
||||
@end
|
||||
|
||||
int main() {
|
||||
using namespace UseObjCTy;
|
||||
@autoreleasepool {
|
||||
@@ -130,5 +176,17 @@ int main() {
|
||||
// CHECK-NEXT: OBJClass: 1
|
||||
// CHECK-NEXT: destroy ObjCKlass
|
||||
// DESTROY: destroy ObjCKlass
|
||||
puts("Part3");
|
||||
@autoreleasepool {
|
||||
id <ObjCProtocol> val = retObjCProtocol();
|
||||
assert(globalCounter == 1);
|
||||
assert([val method] == 2);
|
||||
takeObjCProtocol(val);
|
||||
}
|
||||
// CHECK: Part3
|
||||
// CHECK-NEXT: create ObjCKlassConforming
|
||||
// CHECK-NEXT: ObjCKlassConforming: 2
|
||||
// CHECK-NEXT: destroy ObjCKlassConforming
|
||||
// DESTROY: destroy ObjCKlassConforming
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
|
||||
// RUN: %FileCheck %s < %t/UseObjCTy.h
|
||||
|
||||
// RUN: %target-swift-frontend -typecheck %t/use-objc-types.swift -typecheck -module-name UseObjCTy -emit-clang-header-path %t/UseObjCTyExposeOnly.h -I %t -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr
|
||||
|
||||
// RUN: %FileCheck %s < %t/UseObjCTyExposeOnly.h
|
||||
|
||||
// FIXME: remove once https://github.com/apple/swift/pull/60971 lands.
|
||||
// RUN: echo "#include \"header.h\"" > %t/full-header.h
|
||||
// RUN: cat %t/UseObjCTy.h >> %t/full-header.h
|
||||
@@ -18,11 +14,22 @@
|
||||
// REQUIRES: objc_interop
|
||||
|
||||
//--- header.h
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface ObjCKlass
|
||||
-(ObjCKlass * _Nonnull) init;
|
||||
@end
|
||||
|
||||
@protocol ObjCProtocol
|
||||
@required
|
||||
- (void)method;
|
||||
@end
|
||||
|
||||
@interface ObjCKlassConforming : NSObject<ObjCProtocol>
|
||||
- (ObjCKlassConforming * _Nonnull) init;
|
||||
- (void)method;
|
||||
@end
|
||||
|
||||
//--- module.modulemap
|
||||
module ObjCTest {
|
||||
header "header.h"
|
||||
@@ -31,33 +38,65 @@ module ObjCTest {
|
||||
//--- use-objc-types.swift
|
||||
import ObjCTest
|
||||
|
||||
@_expose(Cxx)
|
||||
public func retObjClass() -> ObjCKlass {
|
||||
return ObjCKlass()
|
||||
}
|
||||
|
||||
@_expose(Cxx)
|
||||
public func takeObjCClass(_ x: ObjCKlass) {
|
||||
}
|
||||
|
||||
@_expose(Cxx)
|
||||
public func takeObjCClassInout(_ x: inout ObjCKlass) {
|
||||
}
|
||||
|
||||
@_expose(Cxx)
|
||||
public func takeObjCClassNullable(_ x: ObjCKlass?) {
|
||||
}
|
||||
|
||||
@_expose(Cxx)
|
||||
public func retObjClassNullable() -> ObjCKlass? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func takeObjCProtocol(_ x: ObjCProtocol) {
|
||||
}
|
||||
|
||||
public func retObjCProtocol() -> ObjCProtocol {
|
||||
return ObjCKlassConforming()
|
||||
}
|
||||
|
||||
public func takeObjCProtocolNullable(_ x: ObjCProtocol?) {
|
||||
}
|
||||
|
||||
public func retObjCProtocolNullable() -> ObjCProtocol? {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CHECK: SWIFT_EXTERN id <ObjCProtocol> _Nonnull $s9UseObjCTy03retB9CProtocolSo0bE0_pyF(void) SWIFT_NOEXCEPT SWIFT_CALL; // retObjCProtocol()
|
||||
// CHECK-NEXT: #endif
|
||||
// CHECK-NEXT: #if defined(__OBJC__)
|
||||
// CHECK-NEXT: SWIFT_EXTERN id <ObjCProtocol> _Nullable $s9UseObjCTy03retB17CProtocolNullableSo0bE0_pSgyF(void) SWIFT_NOEXCEPT SWIFT_CALL; // retObjCProtocolNullable()
|
||||
// CHECK-NEXT: #endif
|
||||
// CHECK: ObjCKlass *_Nonnull $s9UseObjCTy03retB5ClassSo0B6CKlassCyF(void) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
// CHECK-NEXT: ObjCKlass *_Nullable $s9UseObjCTy03retB13ClassNullableSo0B6CKlassCSgyF(void) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
// CHECK-NEXT: void $s9UseObjCTy04takeB6CClassyySo0B6CKlassCF(ObjCKlass *_Nonnull x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
// CHECK-NEXT: void $s9UseObjCTy04takeB11CClassInoutyySo0B6CKlassCzF(ObjCKlass *_Nonnull __strong * _Nonnull x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
// CHECK-NEXT: void $s9UseObjCTy04takeB14CClassNullableyySo0B6CKlassCSgF(ObjCKlass *_Nullable x) SWIFT_NOEXCEPT SWIFT_CALL;
|
||||
// CHECK-NEXT: #if defined(__OBJC__)
|
||||
// CHECK-NEXT: SWIFT_EXTERN void $s9UseObjCTy04takeB9CProtocolyySo0bE0_pF(id <ObjCProtocol> _Nonnull x) SWIFT_NOEXCEPT SWIFT_CALL; // takeObjCProtocol(_:)
|
||||
// CHECK-NEXT: #endif
|
||||
// CHECK-NEXT: #if defined(__OBJC__)
|
||||
// CHECK-NEXT: SWIFT_EXTERN void $s9UseObjCTy04takeB17CProtocolNullableyySo0bE0_pSgF(id <ObjCProtocol> _Nullable x) SWIFT_NOEXCEPT SWIFT_CALL; // takeObjCProtocolNullable(_:)
|
||||
// CHECK-NEXT: #endif
|
||||
|
||||
// CHECK: #if defined(__OBJC__)
|
||||
// CHECK-NEXT: SWIFT_INLINE_THUNK id <ObjCProtocol> _Nonnull retObjCProtocol() noexcept SWIFT_SYMBOL("s:9UseObjCTy03retB9CProtocolSo0bE0_pyF") SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return (__bridge_transfer id <ObjCProtocol>)(__bridge void *)UseObjCTy::_impl::$s9UseObjCTy03retB9CProtocolSo0bE0_pyF();
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: #endif
|
||||
|
||||
// CHECK: #if defined(__OBJC__)
|
||||
// CHECK-NEXT: SWIFT_INLINE_THUNK id <ObjCProtocol> _Nullable retObjCProtocolNullable() noexcept SWIFT_SYMBOL("s:9UseObjCTy03retB17CProtocolNullableSo0bE0_pSgyF") SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return (__bridge_transfer id <ObjCProtocol>)(__bridge void *)UseObjCTy::_impl::$s9UseObjCTy03retB17CProtocolNullableSo0bE0_pSgyF();
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: #endif
|
||||
|
||||
// CHECK: SWIFT_INLINE_THUNK ObjCKlass *_Nonnull retObjClass() noexcept SWIFT_SYMBOL({{.*}}) SWIFT_WARN_UNUSED_RESULT {
|
||||
// CHECK-NEXT: return (__bridge_transfer ObjCKlass *)(__bridge void *)UseObjCTy::_impl::$s9UseObjCTy03retB5ClassSo0B6CKlassCyF();
|
||||
@@ -73,3 +112,16 @@ public func retObjClassNullable() -> ObjCKlass? {
|
||||
|
||||
// CHECK: SWIFT_INLINE_THUNK void takeObjCClassNullable(ObjCKlass *_Nullable x) noexcept SWIFT_SYMBOL({{.*}}) {
|
||||
// CHECK-NEXT: _impl::$s9UseObjCTy04takeB14CClassNullableyySo0B6CKlassCSgF(x);
|
||||
|
||||
|
||||
// CHECK: #if defined(__OBJC__)
|
||||
// CHECK-NEXT: SWIFT_INLINE_THUNK void takeObjCProtocol(id <ObjCProtocol> _Nonnull x) noexcept SWIFT_SYMBOL("s:9UseObjCTy04takeB9CProtocolyySo0bE0_pF") {
|
||||
// CHECK-NEXT: UseObjCTy::_impl::$s9UseObjCTy04takeB9CProtocolyySo0bE0_pF(x);
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: #endif
|
||||
|
||||
// CHECK: #if defined(__OBJC__)
|
||||
// CHECK-NEXT: SWIFT_INLINE_THUNK void takeObjCProtocolNullable(id <ObjCProtocol> _Nullable x) noexcept SWIFT_SYMBOL("s:9UseObjCTy04takeB17CProtocolNullableyySo0bE0_pSgF") {
|
||||
// CHECK-NEXT: UseObjCTy::_impl::$s9UseObjCTy04takeB17CProtocolNullableyySo0bE0_pSgF(x);
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: #endif
|
||||
|
||||
@@ -86,8 +86,7 @@
|
||||
// CHECK: SWIFT_INLINE_THUNK void append(const String& other)
|
||||
// CHECK: SWIFT_INLINE_THUNK UTF8View getUtf8() const SWIFT_SYMBOL({{.*}});
|
||||
// CHECK-NEXT: SWIFT_INLINE_THUNK void setUtf8(const UTF8View& newValue) SWIFT_SYMBOL({{.*}});
|
||||
// CHECK: #if defined(__OBJC__)
|
||||
// CHECK-NEXT: SWIFT_INLINE_THUNK operator NSString * _Nonnull () const noexcept {
|
||||
// CHECK: SWIFT_INLINE_THUNK operator NSString * _Nonnull () const noexcept {
|
||||
// CHECK-NEXT: return (__bridge_transfer NSString *)(_impl::$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF(_impl::swift_interop_passDirect_Swift_String(_getOpaquePointer())));
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: static SWIFT_INLINE_THUNK String init(NSString * _Nonnull nsString) noexcept {
|
||||
@@ -97,7 +96,7 @@
|
||||
// CHECK-NEXT: return result;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-EMPTY:
|
||||
// CHECK-NEXT: #endif
|
||||
// CHECK-NEXT: #endif // defined(__OBJC__)
|
||||
// CHECK-NEXT: #define SWIFT_CXX_INTEROP_STRING_MIXIN
|
||||
|
||||
// CHECK-NEXT: #pragma clang diagnostic push
|
||||
|
||||
Reference in New Issue
Block a user