Skip to content

Commit bf3a30e

Browse files
Merge pull request #61888 from aschwaighofer/rdar101876133
IRGen: Fix usage of clang generated objective-c protocol metadata
2 parents 4e65e14 + 852c59f commit bf3a30e

File tree

3 files changed

+96
-1
lines changed

3 files changed

+96
-1
lines changed

lib/IRGen/GenObjC.cpp

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,67 @@ getProtocolRefsList(llvm::Constant *protocol) {
433433
return std::make_pair(size, protocolRefsList);
434434
}
435435

436+
// Get runtime protocol list used during emission of objective-c protocol
437+
// metadata taking non-runtime protocols into account.
438+
static std::vector<clang::ObjCProtocolDecl *>
439+
getRuntimeProtocolList(clang::ObjCProtocolDecl::protocol_range protocols) {
440+
441+
llvm::DenseSet<clang::ObjCProtocolDecl *> nonRuntimeProtocols;
442+
std::vector<clang::ObjCProtocolDecl*> runtimeProtocols;
443+
for (auto p: protocols) {
444+
auto *proto = p->getCanonicalDecl();
445+
if (proto->isNonRuntimeProtocol())
446+
nonRuntimeProtocols.insert(proto);
447+
else
448+
runtimeProtocols.push_back(proto);
449+
}
450+
451+
if (nonRuntimeProtocols.empty())
452+
return runtimeProtocols;
453+
454+
// Find the non-runtime implied protocols: protocols that occur in the closest
455+
// ancestry of a non-runtime protocol.
456+
llvm::SetVector<clang::ObjCProtocolDecl *> nonRuntimeImpliedProtos;
457+
std::vector<clang::ObjCProtocolDecl *> worklist;
458+
llvm::DenseSet<clang::ObjCProtocolDecl*> seen;
459+
for (auto *nonRuntimeProto : nonRuntimeProtocols) {
460+
worklist.push_back(nonRuntimeProto);
461+
while(!worklist.empty()) {
462+
auto *item = worklist.back();
463+
worklist.pop_back();
464+
if (!seen.insert(item).second)
465+
continue;
466+
467+
if (item->isNonRuntimeProtocol()) {
468+
for (auto *parent : item->protocols())
469+
worklist.push_back(parent);
470+
} else {
471+
nonRuntimeImpliedProtos.insert(item->getCanonicalDecl());
472+
}
473+
}
474+
}
475+
476+
// Subtract the implied protocols of the runtime protocols and non runtime
477+
// protoocls implied protocols form the non runtime implied protocols.
478+
llvm::DenseSet<const clang::ObjCProtocolDecl *> impliedProtocols;
479+
for (auto *p : runtimeProtocols) {
480+
impliedProtocols.insert(p);
481+
p->getImpliedProtocols(impliedProtocols);
482+
}
483+
484+
for (auto *p : nonRuntimeImpliedProtos) {
485+
p->getImpliedProtocols(impliedProtocols);
486+
}
487+
488+
for (auto *p : nonRuntimeImpliedProtos) {
489+
if (!impliedProtocols.contains(p)) {
490+
runtimeProtocols.push_back(p);
491+
}
492+
}
493+
494+
return runtimeProtocols;
495+
}
496+
436497
static void updateProtocolRefs(IRGenModule &IGM,
437498
const clang::ObjCProtocolDecl *objcProtocol,
438499
llvm::Constant *protocol) {
@@ -448,7 +509,8 @@ static void updateProtocolRefs(IRGenModule &IGM,
448509
llvm::ConstantArray *protocolRefs;
449510
std::tie(protocolRefsSize, protocolRefs) = getProtocolRefsList(protocol);
450511
unsigned currentIdx = 0;
451-
for (auto inheritedObjCProtocol : objcProtocol->protocols()) {
512+
auto inheritedObjCProtocols = getRuntimeProtocolList(objcProtocol->protocols());
513+
for (auto inheritedObjCProtocol : inheritedObjCProtocols) {
452514
assert(currentIdx < protocolRefsSize);
453515
auto oldVar = protocolRefs->getOperand(currentIdx);
454516
// Map the objc protocol to swift protocol.

test/IRGen/Inputs/usr/include/Gizmo.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,3 +171,32 @@ __attribute__((swift_name("OuterType.InnerType")))
171171

172172
@interface FungingArray <Element: id<NSFunging>> : NSObject
173173
@end
174+
175+
__attribute__((objc_non_runtime_protocol))
176+
@protocol NonRuntimeP
177+
@end
178+
179+
@protocol RuntimeP<NonRuntimeP>
180+
@end
181+
182+
@protocol P1
183+
@end
184+
@protocol P2
185+
@end
186+
@protocol P3
187+
@end
188+
189+
__attribute__((objc_non_runtime_protocol))
190+
@protocol AnotherNonRuntimeP<P1, P2, P3>
191+
@end
192+
193+
__attribute__((objc_non_runtime_protocol))
194+
@protocol AnotherNonRuntime2P<P1, P2>
195+
@end
196+
197+
__attribute__((objc_non_runtime_protocol))
198+
@protocol OtherNonRuntimeP <AnotherNonRuntimeP, AnotherNonRuntime2P>
199+
@end
200+
201+
@protocol Runtime2P<NonRuntimeP, OtherNonRuntimeP, P3>
202+
@end

test/IRGen/objc_protocols.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,7 @@ func gallop<T : Vanner>(_ t: Stirrup<T>) {
218218
func triggerDoubleInheritedFunging() -> AnyObject {
219219
return NSDoubleInheritedFunging.self as AnyObject
220220
}
221+
222+
class TestNonRuntimeProto : RuntimeP { }
223+
224+
class TestNonRuntime2Proto : Runtime2P {}

0 commit comments

Comments
 (0)