@@ -433,6 +433,67 @@ getProtocolRefsList(llvm::Constant *protocol) {
433
433
return std::make_pair (size, protocolRefsList);
434
434
}
435
435
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
+
436
497
static void updateProtocolRefs (IRGenModule &IGM,
437
498
const clang::ObjCProtocolDecl *objcProtocol,
438
499
llvm::Constant *protocol) {
@@ -448,7 +509,8 @@ static void updateProtocolRefs(IRGenModule &IGM,
448
509
llvm::ConstantArray *protocolRefs;
449
510
std::tie (protocolRefsSize, protocolRefs) = getProtocolRefsList (protocol);
450
511
unsigned currentIdx = 0 ;
451
- for (auto inheritedObjCProtocol : objcProtocol->protocols ()) {
512
+ auto inheritedObjCProtocols = getRuntimeProtocolList (objcProtocol->protocols ());
513
+ for (auto inheritedObjCProtocol : inheritedObjCProtocols) {
452
514
assert (currentIdx < protocolRefsSize);
453
515
auto oldVar = protocolRefs->getOperand (currentIdx);
454
516
// Map the objc protocol to swift protocol.
0 commit comments