@@ -2276,16 +2276,19 @@ getSemanticAvailableRangeDeclAndAttr(const Decl *decl) {
2276
2276
return std::nullopt;
2277
2277
}
2278
2278
2279
- void AttributeChecker::visitAvailableAttr (AvailableAttr *attr ) {
2279
+ void AttributeChecker::visitAvailableAttr (AvailableAttr *parsedAttr ) {
2280
2280
if (Ctx.LangOpts .DisableAvailabilityChecking )
2281
2281
return ;
2282
2282
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
+ }
2289
2292
}
2290
2293
2291
2294
if (attr->isNoAsync ()) {
@@ -2312,7 +2315,7 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
2312
2315
// deinit's may not be unavailable from async contexts
2313
2316
if (isa<DestructorDecl>(D)) {
2314
2317
D->getASTContext ().Diags .diagnose (
2315
- D->getLoc (), diag::invalid_decl_attribute, attr );
2318
+ D->getLoc (), diag::invalid_decl_attribute, parsedAttr );
2316
2319
}
2317
2320
}
2318
2321
@@ -2323,32 +2326,28 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
2323
2326
return ;
2324
2327
2325
2328
// 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))
2331
2330
return ;
2332
2331
2333
2332
// Make sure there isn't a more specific attribute we should be using instead.
2334
2333
// getActiveAvailableAttrForCurrentPlatform() is O(N), so only do this if
2335
2334
// we're checking an iOS attribute while building for macCatalyst.
2336
2335
if (attr->getPlatform () == PlatformKind::iOS &&
2337
2336
isPlatformActive (PlatformKind::macCatalyst, Ctx.LangOpts )) {
2338
- if (semanticAttr != D->getActiveAvailableAttrForCurrentPlatform ()) {
2337
+ if (attr != D->getActiveAvailableAttrForCurrentPlatform ()) {
2339
2338
return ;
2340
2339
}
2341
2340
}
2342
2341
2343
2342
if (attr->getPlatform () == PlatformKind::iOS &&
2344
2343
isPlatformActive (PlatformKind::visionOS, Ctx.LangOpts )) {
2345
- if (semanticAttr != D->getActiveAvailableAttrForCurrentPlatform ()) {
2344
+ if (attr != D->getActiveAvailableAttrForCurrentPlatform ()) {
2346
2345
return ;
2347
2346
}
2348
2347
}
2349
2348
2350
- SourceLoc attrLoc = attr ->getLocation ();
2351
- auto versionAvailability = semanticAttr ->getVersionAvailability (Ctx);
2349
+ SourceLoc attrLoc = parsedAttr ->getLocation ();
2350
+ auto versionAvailability = attr ->getVersionAvailability (Ctx);
2352
2351
if (versionAvailability == AvailableVersionComparison::Obsoleted ||
2353
2352
versionAvailability == AvailableVersionComparison::Unavailable) {
2354
2353
if (auto cannotBeUnavailable =
@@ -2360,7 +2359,7 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
2360
2359
if (auto *PD = dyn_cast<ProtocolDecl>(DC)) {
2361
2360
if (auto *VD = dyn_cast<ValueDecl>(D)) {
2362
2361
if (VD->isProtocolRequirement () && !PD->isObjC ()) {
2363
- diagnoseAndRemoveAttr (attr ,
2362
+ diagnoseAndRemoveAttr (parsedAttr ,
2364
2363
diag::unavailable_method_non_objc_protocol);
2365
2364
return ;
2366
2365
}
@@ -2370,15 +2369,15 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
2370
2369
2371
2370
// The remaining diagnostics are only for attributes with introduced versions
2372
2371
// for specific platforms.
2373
- if (!attr->hasPlatform () || !attr->Introduced .has_value ())
2372
+ if (!attr->isPlatformSpecific () || !attr->getIntroduced () .has_value ())
2374
2373
return ;
2375
2374
2376
2375
// Find the innermost enclosing declaration with an availability
2377
2376
// range annotation and ensure that this attribute's available version range
2378
2377
// is fully contained within that declaration's range. If there is no such
2379
2378
// enclosing declaration, then there is nothing to check.
2380
2379
std::optional<AvailabilityRange> EnclosingAnnotatedRange;
2381
- AvailabilityRange AttrRange = semanticAttr ->getIntroducedRange (Ctx);
2380
+ AvailabilityRange AttrRange = attr ->getIntroducedRange (Ctx);
2382
2381
2383
2382
if (auto *parent = getEnclosingDeclForDecl (D)) {
2384
2383
if (auto enclosingAvailable =
@@ -2399,7 +2398,7 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
2399
2398
limit = DiagnosticBehavior::Warning;
2400
2399
}
2401
2400
diagnose (D->isImplicit () ? enclosingDecl->getLoc ()
2402
- : attr ->getLocation (),
2401
+ : parsedAttr ->getLocation (),
2403
2402
diag::availability_decl_more_than_enclosing,
2404
2403
D->getDescriptiveKind ())
2405
2404
.limitBehavior (limit);
0 commit comments