From cf526b4adaa5b6ec8ceb6074ec948ada9507dd64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferrie=CC=80re?= Date: Mon, 16 Sep 2019 17:19:42 -0700 Subject: [PATCH] ClangImporter: don't transform NSObject<...> when there's no NSObject protocol If there is no NSObject protocol, skip a special case when importing types like `NSObject ` that converts them to `id `. Fix rdar://problem/34597302 --- lib/ClangImporter/ImportType.cpp | 45 ++++++++++--------- .../Inputs/no-nsobject-protocol.h | 15 +++++++ test/ClangImporter/no-nsobject-protocol.swift | 9 ++++ 3 files changed, 49 insertions(+), 20 deletions(-) create mode 100644 test/ClangImporter/Inputs/no-nsobject-protocol.h create mode 100644 test/ClangImporter/no-nsobject-protocol.swift diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index a2261024629eb..a6a5d517e47c3 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -921,27 +921,32 @@ namespace { return {}; } if (nsObjectTy && importedType->isEqual(nsObjectTy)) { - SmallVector protocols{ - type->qual_begin(), type->qual_end() - }; - auto *nsObjectProto = - Impl.getNSObjectProtocolType()->getAnyNominal(); - if (!nsObjectProto) { - // Input is malformed - return {}; + // Skip if there is no NSObject protocol. + auto nsObjectProtoType = + Impl.getNSObjectProtocolType(); + if (nsObjectProtoType) { + auto *nsObjectProto = nsObjectProtoType->getAnyNominal(); + if (!nsObjectProto) { + // Input is malformed + return {}; + } + + SmallVector protocols{ + type->qual_begin(), type->qual_end() + }; + auto *clangProto = + cast(nsObjectProto->getClangDecl()); + protocols.push_back( + const_cast(clangProto)); + + clang::ASTContext &clangCtx = Impl.getClangASTContext(); + clang::QualType protosOnlyType = + clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy, + /*type args*/{}, + protocols, + /*kindof*/false); + return Visit(clangCtx.getObjCObjectPointerType(protosOnlyType)); } - auto *clangProto = - cast(nsObjectProto->getClangDecl()); - protocols.push_back( - const_cast(clangProto)); - - clang::ASTContext &clangCtx = Impl.getClangASTContext(); - clang::QualType protosOnlyType = - clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy, - /*type args*/{}, - protocols, - /*kindof*/false); - return Visit(clangCtx.getObjCObjectPointerType(protosOnlyType)); } } diff --git a/test/ClangImporter/Inputs/no-nsobject-protocol.h b/test/ClangImporter/Inputs/no-nsobject-protocol.h new file mode 100644 index 0000000000000..6051173715ae6 --- /dev/null +++ b/test/ClangImporter/Inputs/no-nsobject-protocol.h @@ -0,0 +1,15 @@ +// Define our own NSObject interface, but not the protocol. +@interface NSObject + - nsobjectFunc; +@end + +@protocol FooProtocol + - fooFunc; +@end + +typedef NSObject Foo; + +@interface Bar : Foo +- (instancetype)init; +- (NSObject *)barFunc; +@end diff --git a/test/ClangImporter/no-nsobject-protocol.swift b/test/ClangImporter/no-nsobject-protocol.swift new file mode 100644 index 0000000000000..69a18a82b8ef5 --- /dev/null +++ b/test/ClangImporter/no-nsobject-protocol.swift @@ -0,0 +1,9 @@ +/// Don't crash when there's no NSObject protocol. +/// rdar://problem/34597302 + +// RUN: %target-swift-frontend -typecheck %s -import-objc-header %S/Inputs/no-nsobject-protocol.h -enable-objc-interop + +var a = Bar()! +var b = a.barFunc()!; +b.nsobjectFunc() +b.fooFunc()