AST: Fix runtime unavailability for universally unavailable decls.

The logic that computes whether a decl is unavailable at runtime was allowing
`@available` attributes for specific availability domains override
`@available(*, unavailable)`. Universally unavailable decls are always
unavailable, regardless of their other `@available` attributes.
This commit is contained in:
Allan Shortlidge
2025-08-28 16:36:24 -07:00
parent 707c4aa52c
commit e390cce662
4 changed files with 44 additions and 10 deletions

View File

@@ -623,6 +623,10 @@ computeDeclRuntimeAvailability(const Decl *decl) {
continue;
llvm::erase_if(unavailableDomains, [domain](auto unavailableDomain) {
// Unavailability in '*' cannot be superseded by an @available attribute
// for a more specific availability domain.
if (unavailableDomain.isUniversal())
return false;
return unavailableDomain.contains(domain);
});
}

View File

@@ -3,15 +3,7 @@
// RUN: -define-enabled-availability-domain EnabledDomain \
// RUN: -define-disabled-availability-domain DisabledDomain \
// RUN: -define-dynamic-availability-domain DynamicDomain \
// RUN: | %FileCheck %s
// RUN: %target-swift-emit-silgen -module-name Test %s -verify \
// RUN: -enable-experimental-feature CustomAvailability \
// RUN: -define-enabled-availability-domain EnabledDomain \
// RUN: -define-disabled-availability-domain DisabledDomain \
// RUN: -define-dynamic-availability-domain DynamicDomain \
// RUN: -unavailable-decl-optimization=stub \
// RUN: | %FileCheck %s
// RUN: | %FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT
// RUN: %target-swift-emit-silgen -module-name Test %s -verify \
// RUN: -enable-experimental-feature CustomAvailability \
@@ -19,7 +11,7 @@
// RUN: -define-disabled-availability-domain DisabledDomain \
// RUN: -define-dynamic-availability-domain DynamicDomain \
// RUN: -unavailable-decl-optimization=complete \
// RUN: | %FileCheck %s
// RUN: | %FileCheck %s --check-prefixes=CHECK,CHECK-OPT
// REQUIRES: swift_feature_CustomAvailability
@@ -84,3 +76,25 @@ public func availableInEnabledAndDisabledDomain() { }
@available(DisabledDomain)
@available(EnabledDomain)
public func availableInDisabledAndEnabledDomain() { }
// CHECK-NOOPT: s4Test49availableInEnabledDomainAndUnavailableUniversallyyyF
// CHECK-OPT-NOT: s4Test49availableInEnabledDomainAndUnavailableUniversallyyyF
@available(*, unavailable)
@available(EnabledDomain)
public func availableInEnabledDomainAndUnavailableUniversally() { }
// CHECK-NOT: s4Test40unavailableInEnabledDomainAndUniversallyyyF
@available(*, unavailable)
@available(EnabledDomain, unavailable)
public func unavailableInEnabledDomainAndUniversally() { }
// CHECK-NOT: s4Test50availableInDisabledDomainAndUnavailableUniversallyyyF
@available(*, unavailable)
@available(DisabledDomain)
public func availableInDisabledDomainAndUnavailableUniversally() { }
// CHECK-NOOPT: s4Test41unavailableInDisabledDomainAndUniversallyyyF
// CHECK-OPT-NOT: s4Test41unavailableInDisabledDomainAndUniversallyyyF
@available(*, unavailable)
@available(DisabledDomain, unavailable)
public func unavailableInDisabledDomainAndUniversally() { }

View File

@@ -12,6 +12,14 @@ public func unavailableFunc() -> S {
return S()
}
// CHECK-LABEL: sil{{.*}}@$s4Test33unavailableFuncIntroducedInSwift5yyF
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss31_diagnoseUnavailableCodeReacheds5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyFTwb)]] : $@convention(thin) () -> Never
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
// CHECK: } // end sil function '$s4Test33unavailableFuncIntroducedInSwift5yyF'
@available(*, unavailable)
@available(swift 5)
public func unavailableFuncIntroducedInSwift5() { }
// CHECK-LABEL: sil{{.*}}@$s4Test025unavailableFuncWithNestedC0yyF
// CHECK: [[FNREF:%.*]] = function_ref @$[[DIAGNOSEFN:(ss31_diagnoseUnavailableCodeReacheds5NeverOyF|ss31_diagnoseUnavailableCodeReacheds5NeverOyFTwb)]] : $@convention(thin) () -> Never
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()

View File

@@ -24,6 +24,14 @@ public func unavailableFunc() {}
@available(macOS, unavailable)
public func unavailableOnMacOSFunc() {}
// CHECK-LABEL: sil{{.*}}@$s4Test36unavailableFuncWithMacOSIntroductionyyF
// CHECK: [[FNREF:%.*]] = function_ref @$ss31_diagnoseUnavailableCodeReacheds5NeverOyFTwb : $@convention(thin) () -> Never
// CHECK-NEXT: [[APPLY:%.*]] = apply [[FNREF]]()
// CHECK: } // end sil function '$s4Test36unavailableFuncWithMacOSIntroductionyyF'
@available(*, unavailable)
@available(macOS 12.0, *)
public func unavailableFuncWithMacOSIntroduction() {}
// CHECK-LABEL: sil{{.*}}@$s4Test31unavailableOnMacOSExtensionFuncyyF
// CHECK-NOT: _diagnoseUnavailableCodeReached
// CHECK: } // end sil function '$s4Test31unavailableOnMacOSExtensionFuncyyF'