@@ -2276,16 +2276,19 @@ getSemanticAvailableRangeDeclAndAttr(const Decl *decl) {
22762276 return std::nullopt ;
22772277}
22782278
2279- void AttributeChecker::visitAvailableAttr (AvailableAttr *attr ) {
2279+ void AttributeChecker::visitAvailableAttr (AvailableAttr *parsedAttr ) {
22802280 if (Ctx.LangOpts .DisableAvailabilityChecking )
22812281 return ;
22822282
2283- // FIXME: This seems like it could be diagnosed during parsing instead.
2284- while (attr->isSPI ()) {
2285- if (attr->hasPlatform () && attr->Introduced .has_value ())
2286- break ;
2287- diagnoseAndRemoveAttr (attr, diag::spi_available_malformed);
2288- break ;
2283+ auto attr = D->getSemanticAvailableAttr (parsedAttr);
2284+ if (!attr)
2285+ return ;
2286+
2287+ if (attr->isSPI ()) {
2288+ if (!attr->isPlatformSpecific () || !attr->getIntroduced ().has_value ()) {
2289+ diagnoseAndRemoveAttr (parsedAttr, diag::spi_available_malformed);
2290+ return ;
2291+ }
22892292 }
22902293
22912294 if (attr->isNoAsync ()) {
@@ -2312,7 +2315,7 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
23122315 // deinit's may not be unavailable from async contexts
23132316 if (isa<DestructorDecl>(D)) {
23142317 D->getASTContext ().Diags .diagnose (
2315- D->getLoc (), diag::invalid_decl_attribute, attr );
2318+ D->getLoc (), diag::invalid_decl_attribute, parsedAttr );
23162319 }
23172320 }
23182321
@@ -2323,32 +2326,28 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
23232326 return ;
23242327
23252328 // The remaining diagnostics are only for attributes that are active.
2326- auto semanticAttr = D->getSemanticAvailableAttr (attr);
2327- if (!semanticAttr)
2328- return ;
2329-
2330- if (!semanticAttr->isActive (Ctx))
2329+ if (!attr->isActive (Ctx))
23312330 return ;
23322331
23332332 // Make sure there isn't a more specific attribute we should be using instead.
23342333 // getActiveAvailableAttrForCurrentPlatform() is O(N), so only do this if
23352334 // we're checking an iOS attribute while building for macCatalyst.
23362335 if (attr->getPlatform () == PlatformKind::iOS &&
23372336 isPlatformActive (PlatformKind::macCatalyst, Ctx.LangOpts )) {
2338- if (semanticAttr != D->getActiveAvailableAttrForCurrentPlatform ()) {
2337+ if (attr != D->getActiveAvailableAttrForCurrentPlatform ()) {
23392338 return ;
23402339 }
23412340 }
23422341
23432342 if (attr->getPlatform () == PlatformKind::iOS &&
23442343 isPlatformActive (PlatformKind::visionOS, Ctx.LangOpts )) {
2345- if (semanticAttr != D->getActiveAvailableAttrForCurrentPlatform ()) {
2344+ if (attr != D->getActiveAvailableAttrForCurrentPlatform ()) {
23462345 return ;
23472346 }
23482347 }
23492348
2350- SourceLoc attrLoc = attr ->getLocation ();
2351- auto versionAvailability = semanticAttr ->getVersionAvailability (Ctx);
2349+ SourceLoc attrLoc = parsedAttr ->getLocation ();
2350+ auto versionAvailability = attr ->getVersionAvailability (Ctx);
23522351 if (versionAvailability == AvailableVersionComparison::Obsoleted ||
23532352 versionAvailability == AvailableVersionComparison::Unavailable) {
23542353 if (auto cannotBeUnavailable =
@@ -2360,7 +2359,7 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
23602359 if (auto *PD = dyn_cast<ProtocolDecl>(DC)) {
23612360 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23622361 if (VD->isProtocolRequirement () && !PD->isObjC ()) {
2363- diagnoseAndRemoveAttr (attr ,
2362+ diagnoseAndRemoveAttr (parsedAttr ,
23642363 diag::unavailable_method_non_objc_protocol);
23652364 return ;
23662365 }
@@ -2370,15 +2369,15 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
23702369
23712370 // The remaining diagnostics are only for attributes with introduced versions
23722371 // for specific platforms.
2373- if (!attr->hasPlatform () || !attr->Introduced .has_value ())
2372+ if (!attr->isPlatformSpecific () || !attr->getIntroduced () .has_value ())
23742373 return ;
23752374
23762375 // Find the innermost enclosing declaration with an availability
23772376 // range annotation and ensure that this attribute's available version range
23782377 // is fully contained within that declaration's range. If there is no such
23792378 // enclosing declaration, then there is nothing to check.
23802379 std::optional<AvailabilityRange> EnclosingAnnotatedRange;
2381- AvailabilityRange AttrRange = semanticAttr ->getIntroducedRange (Ctx);
2380+ AvailabilityRange AttrRange = attr ->getIntroducedRange (Ctx);
23822381
23832382 if (auto *parent = getEnclosingDeclForDecl (D)) {
23842383 if (auto enclosingAvailable =
@@ -2399,7 +2398,7 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
23992398 limit = DiagnosticBehavior::Warning;
24002399 }
24012400 diagnose (D->isImplicit () ? enclosingDecl->getLoc ()
2402- : attr ->getLocation (),
2401+ : parsedAttr ->getLocation (),
24032402 diag::availability_decl_more_than_enclosing,
24042403 D->getDescriptiveKind ())
24052404 .limitBehavior (limit);
0 commit comments