mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[cxx-interop] Support ObjC classes in generic context in reverse interop
We have the sufficient type metadata on the Swift side so this PR only makes sure the type traits are correctly generated. rdar://145211212
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
#include "swift/Strings.h"
|
||||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
@@ -285,10 +286,20 @@ public:
|
||||
}
|
||||
|
||||
void emitReferencedClangTypeMetadata(const TypeDecl *typeDecl) {
|
||||
if (!isa<clang::TypeDecl>(typeDecl->getClangDecl()))
|
||||
const auto *clangDecl = typeDecl->getClangDecl();
|
||||
if (const auto *objCInt = dyn_cast<clang::ObjCInterfaceDecl>(clangDecl)) {
|
||||
auto clangType = clangDecl->getASTContext()
|
||||
.getObjCInterfaceType(objCInt)
|
||||
.getCanonicalType();
|
||||
auto it = seenClangTypes.insert(clangType.getTypePtr());
|
||||
if (it.second)
|
||||
ClangValueTypePrinter::printClangTypeSwiftGenericTraits(os, typeDecl, &M,
|
||||
printer);
|
||||
return;
|
||||
}
|
||||
if (!isa<clang::TypeDecl>(clangDecl))
|
||||
return;
|
||||
// Get the underlying clang type from a type alias decl or record decl.
|
||||
auto clangDecl = typeDecl->getClangDecl();
|
||||
auto clangType = clangDecl->getASTContext()
|
||||
.getTypeDeclType(cast<clang::TypeDecl>(clangDecl))
|
||||
.getCanonicalType();
|
||||
@@ -314,6 +325,8 @@ public:
|
||||
forwardDeclareCxxValueTypeIfNeeded(NTD);
|
||||
else if (isa<StructDecl>(TD) && NTD->hasClangNode())
|
||||
emitReferencedClangTypeMetadata(NTD);
|
||||
else if (isa<ClassDecl>(TD) && TD->isObjC())
|
||||
emitReferencedClangTypeMetadata(NTD);
|
||||
} else if (auto TAD = dyn_cast<TypeAliasDecl>(TD)) {
|
||||
if (TAD->hasClangNode())
|
||||
emitReferencedClangTypeMetadata(TAD);
|
||||
|
||||
@@ -641,6 +641,7 @@ void ClangValueTypePrinter::printTypeGenericTraits(
|
||||
typeDecl, typeMetadataFuncName, typeMetadataFuncRequirements);
|
||||
});
|
||||
}
|
||||
bool addPointer = typeDecl->isObjC();
|
||||
|
||||
os << "#pragma clang diagnostic push\n";
|
||||
os << "#pragma clang diagnostic ignored \"-Wc++17-extensions\"\n";
|
||||
@@ -649,6 +650,8 @@ void ClangValueTypePrinter::printTypeGenericTraits(
|
||||
os << "template<>\n";
|
||||
os << "inline const constexpr bool isUsableInGenericContext<";
|
||||
printer.printClangTypeReference(typeDecl->getClangDecl());
|
||||
if (addPointer)
|
||||
os << "*";
|
||||
os << "> = true;\n";
|
||||
}
|
||||
if (!NTD || printer.printNominalTypeOutsideMemberDeclTemplateSpecifiers(NTD))
|
||||
@@ -658,6 +661,8 @@ void ClangValueTypePrinter::printTypeGenericTraits(
|
||||
os << " TypeMetadataTrait<";
|
||||
if (typeDecl->hasClangNode()) {
|
||||
printer.printClangTypeReference(typeDecl->getClangDecl());
|
||||
if (addPointer)
|
||||
os << "*";
|
||||
} else {
|
||||
assert(NTD);
|
||||
printer.printNominalTypeReference(NTD,
|
||||
@@ -682,7 +687,7 @@ void ClangValueTypePrinter::printTypeGenericTraits(
|
||||
|
||||
os << "namespace " << cxx_synthesis::getCxxImplNamespaceName() << "{\n";
|
||||
|
||||
if (typeDecl->hasClangNode()) {
|
||||
if (typeDecl->hasClangNode() && !typeDecl->isObjC()) {
|
||||
os << "template<>\n";
|
||||
os << "inline const constexpr bool isSwiftBridgedCxxRecord<";
|
||||
printer.printClangTypeReference(typeDecl->getClangDecl());
|
||||
|
||||
@@ -86,6 +86,10 @@ public func retObjCProtocolNullable() -> ObjCProtocol? {
|
||||
return ObjCKlassConforming(2)
|
||||
}
|
||||
|
||||
public func retObjClassArray() -> [ObjCKlass] {
|
||||
return [ObjCKlass(1)]
|
||||
}
|
||||
|
||||
//--- use-swift-objc-types.mm
|
||||
|
||||
#include "header.h"
|
||||
@@ -188,5 +192,14 @@ int main() {
|
||||
// CHECK-NEXT: ObjCKlassConforming: 2
|
||||
// CHECK-NEXT: destroy ObjCKlassConforming
|
||||
// DESTROY: destroy ObjCKlassConforming
|
||||
puts("Part4");
|
||||
@autoreleasepool {
|
||||
swift::Array<ObjCKlass*> val = retObjClassArray();
|
||||
assert(val[0].getValue == 1);
|
||||
assert(globalCounter == 1);
|
||||
}
|
||||
assert(globalCounter == 0);
|
||||
// CHECK: create ObjCKlass
|
||||
// DESTROY: destroy ObjCKlass
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,10 @@ public func retObjCProtocolNullable() -> ObjCProtocol? {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func retObjCClassArray() -> [ObjCKlass] {
|
||||
return []
|
||||
}
|
||||
|
||||
// CHECK: SWIFT_EXTERN id <ObjCProtocol> _Nonnull $s9UseObjCTy03retB9CProtocolSo0bE0_pyF(void) SWIFT_NOEXCEPT SWIFT_CALL; // retObjCProtocol()
|
||||
// CHECK-NEXT: #endif
|
||||
// CHECK-NEXT: #if defined(__OBJC__)
|
||||
@@ -86,6 +90,14 @@ public func retObjCProtocolNullable() -> ObjCProtocol? {
|
||||
// CHECK-NEXT: SWIFT_EXTERN void $s9UseObjCTy04takeB17CProtocolNullableyySo0bE0_pSgF(id <ObjCProtocol> _Nullable x) SWIFT_NOEXCEPT SWIFT_CALL; // takeObjCProtocolNullable(_:)
|
||||
// CHECK-NEXT: #endif
|
||||
|
||||
// CHECK: inline const constexpr bool isUsableInGenericContext<ObjCKlass*> = true;
|
||||
// CHECK-NEXT: template<>
|
||||
// CHECK-NEXT: struct TypeMetadataTrait<ObjCKlass*> {
|
||||
// CHECK-NEXT: static SWIFT_INLINE_PRIVATE_HELPER void * _Nonnull getTypeMetadata() {
|
||||
// CHECK-NEXT: return _impl::$sSo9ObjCKlassCMa(0)._0;
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: };
|
||||
|
||||
// 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();
|
||||
|
||||
Reference in New Issue
Block a user