Skip to content

Commit b5e4e8a

Browse files
authored
[ClangImporter] Not all protocols adopted in ObjC come from ObjC. (#6320)
So when sorting, don't just jump directly to the Clang decl and get its name, because there might not be a Clang decl; instead, use the 'objc' attribute if there is one and the protocol's base name if not. We're not using ProtocolType::compareProtocols because we'd rather not depend on knowing for sure which Clang module a protocol lives in. This wasn't caught until now because it required adopting a protocol in Objective-C that itself adopted (directly or indirectly) at least two protocols, at least one of which originally came from Swift. rdar://problem/26232085
1 parent 92aad64 commit b5e4e8a

File tree

3 files changed

+14
-2
lines changed

3 files changed

+14
-2
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6707,9 +6707,13 @@ void ClangImporter::Implementation::finishProtocolConformance(
67076707
inheritedProtos.end(),
67086708
[](ProtocolDecl * const *left,
67096709
ProtocolDecl * const *right) -> int {
6710-
// We know all Objective-C protocols have unique names.
6710+
// We know all Objective-C protocols in a translation unit have unique
6711+
// names, so go by the Objective-C name.
67116712
auto getDeclName = [](const ProtocolDecl *proto) -> StringRef {
6712-
return cast<clang::ObjCProtocolDecl>(proto->getClangDecl())->getName();
6713+
if (auto *objCAttr = proto->getAttrs().getAttribute<ObjCAttr>())
6714+
if (auto name = objCAttr->getName())
6715+
return name.getValue().getSelectorPieces().front().str();
6716+
return proto->getName().str();
67136717
};
67146718
return getDeclName(*left).compare(getDeclName(*right));
67156719
});

test/ClangImporter/MixedSource/Inputs/resolve-cross-language/BaseUser.framework/Headers/BaseUser.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,10 @@ void useRenamedEnumObjC(RenamedEnumObjC);
5555

5656
@interface AnotherClass (EnumProtoConformance) <EnumProto>
5757
@end
58+
59+
@protocol AnotherProto
60+
@end
61+
@protocol ExtendsTwoProtosOneOfWhichIsFromSwift <BaseProto, AnotherProto>
62+
@end
63+
@interface ExtendsTwoProtosImpl : NSObject <ExtendsTwoProtosOneOfWhichIsFromSwift>
64+
@end

test/ClangImporter/MixedSource/resolve-cross-language.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ seo = SwiftEnumObjC.corge
6161
seo = SwiftEnumObjC.grault
6262

6363
var seoRaw: CUnsignedChar = seo.rawValue
64+
_ = ExtendsTwoProtosImpl.self
6465

6566
// Make sure we're actually parsing stuff.
6667
useBaseClass() // expected-error{{missing argument for parameter #1}}

0 commit comments

Comments
 (0)