Skip to content

Commit cf526b4

Browse files
committed
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 <NSCopying>` that converts them to `id <NSObject, NSCopying>`. Fix rdar://problem/34597302
1 parent 40016b5 commit cf526b4

File tree

3 files changed

+49
-20
lines changed

3 files changed

+49
-20
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -921,27 +921,32 @@ namespace {
921921
return {};
922922
}
923923
if (nsObjectTy && importedType->isEqual(nsObjectTy)) {
924-
SmallVector<clang::ObjCProtocolDecl *, 4> protocols{
925-
type->qual_begin(), type->qual_end()
926-
};
927-
auto *nsObjectProto =
928-
Impl.getNSObjectProtocolType()->getAnyNominal();
929-
if (!nsObjectProto) {
930-
// Input is malformed
931-
return {};
924+
// Skip if there is no NSObject protocol.
925+
auto nsObjectProtoType =
926+
Impl.getNSObjectProtocolType();
927+
if (nsObjectProtoType) {
928+
auto *nsObjectProto = nsObjectProtoType->getAnyNominal();
929+
if (!nsObjectProto) {
930+
// Input is malformed
931+
return {};
932+
}
933+
934+
SmallVector<clang::ObjCProtocolDecl *, 4> protocols{
935+
type->qual_begin(), type->qual_end()
936+
};
937+
auto *clangProto =
938+
cast<clang::ObjCProtocolDecl>(nsObjectProto->getClangDecl());
939+
protocols.push_back(
940+
const_cast<clang::ObjCProtocolDecl *>(clangProto));
941+
942+
clang::ASTContext &clangCtx = Impl.getClangASTContext();
943+
clang::QualType protosOnlyType =
944+
clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy,
945+
/*type args*/{},
946+
protocols,
947+
/*kindof*/false);
948+
return Visit(clangCtx.getObjCObjectPointerType(protosOnlyType));
932949
}
933-
auto *clangProto =
934-
cast<clang::ObjCProtocolDecl>(nsObjectProto->getClangDecl());
935-
protocols.push_back(
936-
const_cast<clang::ObjCProtocolDecl *>(clangProto));
937-
938-
clang::ASTContext &clangCtx = Impl.getClangASTContext();
939-
clang::QualType protosOnlyType =
940-
clangCtx.getObjCObjectType(clangCtx.ObjCBuiltinIdTy,
941-
/*type args*/{},
942-
protocols,
943-
/*kindof*/false);
944-
return Visit(clangCtx.getObjCObjectPointerType(protosOnlyType));
945950
}
946951
}
947952

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Define our own NSObject interface, but not the protocol.
2+
@interface NSObject
3+
- nsobjectFunc;
4+
@end
5+
6+
@protocol FooProtocol
7+
- fooFunc;
8+
@end
9+
10+
typedef NSObject<FooProtocol> Foo;
11+
12+
@interface Bar : Foo
13+
- (instancetype)init;
14+
- (NSObject<FooProtocol> *)barFunc;
15+
@end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/// Don't crash when there's no NSObject protocol.
2+
/// rdar://problem/34597302
3+
4+
// RUN: %target-swift-frontend -typecheck %s -import-objc-header %S/Inputs/no-nsobject-protocol.h -enable-objc-interop
5+
6+
var a = Bar()!
7+
var b = a.barFunc()!;
8+
b.nsobjectFunc()
9+
b.fooFunc()

0 commit comments

Comments
 (0)