@@ -1835,6 +1835,52 @@ static bool diagnoseOverrideForAvailability(ValueDecl *override,
18351835 return true ;
18361836}
18371837
1838+ enum class OverrideUnavailabilityStatus {
1839+ // / The unavailability of the base decl and override decl are compatible.
1840+ Compatible,
1841+ // / The base decl is unavailable but the override decl is not.
1842+ BaseUnavailable,
1843+ // / Do not diagnose the unavailability of these decls.
1844+ Ignored,
1845+ };
1846+
1847+ static std::pair<OverrideUnavailabilityStatus, const AvailableAttr *>
1848+ checkOverrideUnavailability (ValueDecl *override , ValueDecl *base) {
1849+ if (auto *overrideParent = override ->getDeclContext ()->getAsDecl ()) {
1850+ // If the parent of the override is unavailable, then the unavailability of
1851+ // the override decl is irrelevant.
1852+ if (overrideParent->getSemanticUnavailableAttr ())
1853+ return {OverrideUnavailabilityStatus::Ignored, nullptr };
1854+ }
1855+
1856+ if (auto *baseAccessor = dyn_cast<AccessorDecl>(base)) {
1857+ // Ignore implicit accessors since the diagnostics are likely to duplicate
1858+ // the diagnostics for the explicit accessors that availability was inferred
1859+ // from.
1860+ if (baseAccessor->isImplicit ())
1861+ return {OverrideUnavailabilityStatus::Ignored, nullptr };
1862+
1863+ if (auto *overrideAccessor = dyn_cast<AccessorDecl>(override )) {
1864+ // If base and override are accessors, check whether the unavailability of
1865+ // their storage matches. Diagnosing accessors with invalid storage
1866+ // produces redundant diagnostics.
1867+ if (checkOverrideUnavailability (overrideAccessor->getStorage (),
1868+ baseAccessor->getStorage ())
1869+ .first != OverrideUnavailabilityStatus::Compatible)
1870+ return {OverrideUnavailabilityStatus::Ignored, nullptr };
1871+ }
1872+ }
1873+
1874+ auto &ctx = override ->getASTContext ();
1875+ auto *baseUnavailableAttr = base->getAttrs ().getUnavailable (ctx);
1876+ auto *overrideUnavailableAttr = override ->getAttrs ().getUnavailable (ctx);
1877+
1878+ if (baseUnavailableAttr && !overrideUnavailableAttr)
1879+ return {OverrideUnavailabilityStatus::BaseUnavailable, baseUnavailableAttr};
1880+
1881+ return {OverrideUnavailabilityStatus::Compatible, nullptr };
1882+ }
1883+
18381884static bool checkSingleOverride (ValueDecl *override , ValueDecl *base) {
18391885 // This can happen with circular inheritance.
18401886 // FIXME: This shouldn't be possible once name lookup goes through the
@@ -2066,17 +2112,28 @@ static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) {
20662112 }
20672113
20682114 // FIXME: Possibly should extend to more availability checking.
2069- if (auto *attr = base->getAttrs ().getUnavailable (ctx)) {
2070- diagnoseUnavailableOverride (override , base, attr);
2115+ auto unavailabilityStatusAndAttr =
2116+ checkOverrideUnavailability (override , base);
2117+ auto *unavailableAttr = unavailabilityStatusAndAttr.second ;
2118+
2119+ switch (unavailabilityStatusAndAttr.first ) {
2120+ case OverrideUnavailabilityStatus::BaseUnavailable: {
2121+ diagnoseOverrideOfUnavailableDecl (override , base, unavailableAttr);
20712122
20722123 if (isUnavailableInAllVersions (base)) {
20732124 auto modifier = override ->getAttrs ().getAttribute <OverrideAttr>();
20742125 if (modifier && modifier->isValid ()) {
2075- diags.diagnose (override , diag::suggest_removing_override,
2076- override ->getBaseName ())
2077- .fixItRemove (modifier->getRange ());
2126+ diags
2127+ .diagnose (override , diag::suggest_removing_override,
2128+ override ->getBaseName ())
2129+ .fixItRemove (modifier->getRange ());
20782130 }
20792131 }
2132+ break ;
2133+ }
2134+ case OverrideUnavailabilityStatus::Compatible:
2135+ case OverrideUnavailabilityStatus::Ignored:
2136+ break ;
20802137 }
20812138
20822139 if (!ctx.LangOpts .DisableAvailabilityChecking ) {
0 commit comments