AST: Fix AvailabilityContext::forDeclSignature().

It had a bug that would cause it to return incorrect results for some decls
with invalid source locations. Since not all declarations introduce a new
`DeclContext`, it's not sufficient to walk the decl context hiearchy when
computing availability for a decl.
This commit is contained in:
Allan Shortlidge
2025-07-21 16:01:34 -07:00
parent 3bacfa7fb9
commit 030a3da88c
2 changed files with 22 additions and 1 deletions

View File

@@ -211,7 +211,23 @@ AvailabilityContext::forLocation(SourceLoc loc, const DeclContext *declContext,
}
AvailabilityContext AvailabilityContext::forDeclSignature(const Decl *decl) {
return forLocation(decl->getLoc(), decl->getInnermostDeclContext());
// For decls with valid source locations, query the availability scope tree.
auto loc = decl->getLoc();
if (loc.isValid())
return forLocation(loc, decl->getInnermostDeclContext());
// Otherwise, walk the decl hierarchy to compute availability. This can't be
// delegated to `AvailabilityContext::forLocation()` since it walks up the
// `DeclContext` hierachy for invalid source locations and that may skip
// some declarations with availability attributes.
auto &ctx = decl->getASTContext();
auto availability = forInliningTarget(ctx);
while (decl) {
availability.constrainWithDecl(decl);
decl = decl->parentDeclForAvailability();
}
return availability;
}
AvailabilityContext

View File

@@ -47,6 +47,11 @@ struct TypeWithUnavailableMethods {
func foo() -> Int {
.random() ? 1 : 2
}
@available(*, unavailable)
var qux: Int {
.random() ? 1 : 2
}
}
@available(*, unavailable)