@@ -608,6 +608,41 @@ void RewriteSystem::verifyRewriteRules(ValidityPolicy policy) const {
608
608
#undef ASSERT_RULE
609
609
}
610
610
611
+ // / Determine whether this is a redundantly inheritable Objective-C protocol.
612
+ // /
613
+ // / A redundantly-inheritable Objective-C protocol is one where we will
614
+ // / silently accept a directly-stated redundant conformance to this protocol,
615
+ // / and emit this protocol in the list of "inherited" protocols. There are
616
+ // / two cases where we allow this:
617
+ // /
618
+ // 1) For a protocol defined in Objective-C, so that we will match Clang's
619
+ // / behavior, and
620
+ // / 2) For an @objc protocol defined in Swift that directly inherits from
621
+ // / JavaScriptCore's JSExport, which depends on this behavior.
622
+ static bool isRedundantlyInheritableObjCProtocol (const ProtocolDecl *inheritingProto,
623
+ const ProtocolDecl *proto) {
624
+ if (!proto->isObjC ()) return false ;
625
+
626
+ // Check the two conditions in which we will suppress the diagnostic and
627
+ // emit the redundant inheritance.
628
+ if (!inheritingProto->hasClangNode () && !proto->getName ().is (" JSExport" ))
629
+ return false ;
630
+
631
+ // If the inheriting protocol already has @_restatedObjCConformance with
632
+ // this protocol, we're done.
633
+ for (auto *attr : inheritingProto->getAttrs ()
634
+ .getAttributes <RestatedObjCConformanceAttr>()) {
635
+ if (attr->Proto == proto) return true ;
636
+ }
637
+
638
+ // Otherwise, add @_restatedObjCConformance.
639
+ auto &ctx = proto->getASTContext ();
640
+ const_cast <ProtocolDecl *>(inheritingProto)
641
+ ->getAttrs ().add (new (ctx) RestatedObjCConformanceAttr (
642
+ const_cast <ProtocolDecl *>(proto)));
643
+ return true ;
644
+ }
645
+
611
646
// / Computes the set of explicit redundant requirements to
612
647
// / emit warnings for in the source code.
613
648
void RewriteSystem::computeRedundantRequirementDiagnostics (
@@ -689,8 +724,18 @@ void RewriteSystem::computeRedundantRequirementDiagnostics(
689
724
auto isRedundantRule = [&](unsigned ruleID) {
690
725
const auto &rule = getRules ()[ruleID];
691
726
692
- return (rule.isRedundant () &&
693
- nonExplicitNonRedundantRules.count (ruleID) == 0 );
727
+ if (!rule.isRedundant ())
728
+ return false ;
729
+
730
+ if (nonExplicitNonRedundantRules.count (ruleID) > 0 )
731
+ return false ;
732
+
733
+ if (rule.isProtocolRefinementRule (Context) &&
734
+ isRedundantlyInheritableObjCProtocol (rule.getLHS ()[0 ].getProtocol (),
735
+ rule.getLHS ()[1 ].getProtocol ()))
736
+ return false ;
737
+
738
+ return true ;
694
739
};
695
740
696
741
// Finally walk through the written requirements, diagnosing any that are
0 commit comments