@@ -3042,6 +3042,7 @@ class ObjCImplementationChecker {
30423042 WrongDeclKind,
30433043 WrongType,
30443044 WrongWritability,
3045+ WrongRequiredAttr,
30453046
30463047 Match,
30473048 MatchWithExplicitObjCName,
@@ -3339,6 +3340,10 @@ class ObjCImplementationChecker {
33393340 !cast<AbstractStorageDecl>(cand)->isSettable (nullptr ))
33403341 return MatchOutcome::WrongWritability;
33413342
3343+ if (auto reqCtor = dyn_cast<ConstructorDecl>(req))
3344+ if (reqCtor->isRequired () != cast<ConstructorDecl>(cand)->isRequired ())
3345+ return MatchOutcome::WrongRequiredAttr;
3346+
33423347 // If we got here, everything matched. But at what quality?
33433348 if (explicitObjCName)
33443349 return MatchOutcome::MatchWithExplicitObjCName;
@@ -3426,6 +3431,22 @@ class ObjCImplementationChecker {
34263431 diagnose (cand, diag::objc_implementation_must_be_settable,
34273432 cand->getDescriptiveKind (), cand, req->getDescriptiveKind ());
34283433 return ;
3434+
3435+ case MatchOutcome::WrongRequiredAttr: {
3436+ bool shouldBeRequired = cast<ConstructorDecl>(req)->isRequired ();
3437+
3438+ auto diag =
3439+ diagnose (cand, diag::objc_implementation_required_attr_mismatch,
3440+ cand->getDescriptiveKind (), cand, shouldBeRequired);
3441+
3442+ if (shouldBeRequired)
3443+ diag.fixItInsert (cand->getAttributeInsertionLoc (/* forModifier=*/ true ),
3444+ " required " );
3445+ else
3446+ diag.fixItRemove (cand->getAttrs ().getAttribute <RequiredAttr>()
3447+ ->getLocation ());
3448+ return ;
3449+ }
34293450 }
34303451
34313452 llvm_unreachable (" Unknown MatchOutcome" );
0 commit comments