mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
AST: Introduce an "always enabled" custom availability domain kind.
An always enabled availability domain is implicitly available in all contexts, so uses of declarations that are marked as `@available` in the domain are never rejected. This is useful for an availability domain representing a feature flag that has become permanently enabled. Partially resolves rdar://157593409.
This commit is contained in:
@@ -226,11 +226,12 @@ public:
|
||||
|
||||
/// Returns true if this domain is considered active in the current
|
||||
/// compilation context.
|
||||
bool isActive(const ASTContext &ctx) const;
|
||||
bool isActive(const ASTContext &ctx, bool forTargetVariant = false) const;
|
||||
|
||||
/// Returns true if this domain is a platform domain and is considered active
|
||||
/// in the current compilation context.
|
||||
bool isActivePlatform(const ASTContext &ctx) const;
|
||||
bool isActivePlatform(const ASTContext &ctx,
|
||||
bool forTargetVariant = false) const;
|
||||
|
||||
/// Returns the domain's minimum available range for type checking. For
|
||||
/// example, for the domain of the platform that compilation is targeting,
|
||||
@@ -332,6 +333,9 @@ public:
|
||||
enum class Kind {
|
||||
/// A domain that is known to be enabled at compile time.
|
||||
Enabled,
|
||||
/// A domain that is known to be enabled at compile time and is also assumed
|
||||
/// to be enabled for all deployments.
|
||||
AlwaysEnabled,
|
||||
/// A domain that is known to be disabled at compile time.
|
||||
Disabled,
|
||||
/// A domain with an enablement state that must be queried at runtime.
|
||||
|
||||
@@ -615,6 +615,8 @@ public:
|
||||
struct CustomAvailabilityDomains {
|
||||
/// Domains defined with `-define-enabled-availability-domain=`.
|
||||
llvm::SmallVector<std::string> EnabledDomains;
|
||||
/// Domains defined with `-define-always-enabled-availability-domain=`.
|
||||
llvm::SmallVector<std::string> AlwaysEnabledDomains;
|
||||
/// Domains defined with `-define-disabled-availability-domain=`.
|
||||
llvm::SmallVector<std::string> DisabledDomains;
|
||||
/// Domains defined with `-define-dynamic-availability-domain=`.
|
||||
|
||||
@@ -576,6 +576,14 @@ def define_enabled_availability_domain : Separate<["-"], "define-enabled-availab
|
||||
HelpText<"Defines a custom availability domain that is available at compile time">,
|
||||
MetaVarName<"<domain>">;
|
||||
|
||||
def define_always_enabled_availability_domain
|
||||
: Separate<["-"], "define-always-enabled-availability-domain">,
|
||||
Flags<[HelpHidden, FrontendOption, NoInteractiveOption,
|
||||
ModuleInterfaceOptionIgnorable]>,
|
||||
HelpText<"Defines a custom availability domain that is available for all "
|
||||
"deployments">,
|
||||
MetaVarName<"<domain>">;
|
||||
|
||||
def define_disabled_availability_domain : Separate<["-"], "define-disabled-availability-domain">,
|
||||
Flags<[HelpHidden, FrontendOption, NoInteractiveOption, ModuleInterfaceOptionIgnorable]>,
|
||||
HelpText<"Defines a custom availability domain that is unavailable at compile time">,
|
||||
|
||||
@@ -204,11 +204,15 @@ getAvailabilityConstraintForAttr(const Decl *decl,
|
||||
|
||||
auto &ctx = decl->getASTContext();
|
||||
auto domain = attr.getDomain();
|
||||
auto deploymentRange = domain.getDeploymentRange(ctx);
|
||||
bool domainSupportsRefinement = domain.supportsContextRefinement();
|
||||
std::optional<AvailabilityRange> availableRange =
|
||||
domainSupportsRefinement ? context.getAvailabilityRange(domain, ctx)
|
||||
: deploymentRange;
|
||||
|
||||
// Compute the available range in the given context. If there is no explicit
|
||||
// range defined by the context, use the deployment range as fallback.
|
||||
std::optional<AvailabilityRange> availableRange;
|
||||
if (domainSupportsRefinement)
|
||||
availableRange = context.getAvailabilityRange(domain, ctx);
|
||||
if (!availableRange)
|
||||
availableRange = domain.getDeploymentRange(ctx);
|
||||
|
||||
// Is the decl obsoleted in this context?
|
||||
if (auto obsoletedRange = attr.getObsoletedRange(ctx)) {
|
||||
@@ -323,24 +327,78 @@ swift::getAvailabilityConstraintForDeclInDomain(
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/// Returns true if unsatisfied `@available(..., unavailable)` constraints for
|
||||
/// \p domain make code unreachable at runtime
|
||||
static bool
|
||||
domainCanBeUnconditionallyUnavailableAtRuntime(AvailabilityDomain domain,
|
||||
const ASTContext &ctx) {
|
||||
switch (domain.getKind()) {
|
||||
case AvailabilityDomain::Kind::Universal:
|
||||
return true;
|
||||
|
||||
case AvailabilityDomain::Kind::Platform:
|
||||
if (ctx.LangOpts.TargetVariant &&
|
||||
domain.isActive(ctx, /*forTargetVariant=*/true))
|
||||
return true;
|
||||
return domain.isActive(ctx);
|
||||
|
||||
case AvailabilityDomain::Kind::SwiftLanguage:
|
||||
case AvailabilityDomain::Kind::PackageDescription:
|
||||
return false;
|
||||
|
||||
case AvailabilityDomain::Kind::Embedded:
|
||||
return ctx.LangOpts.hasFeature(Feature::Embedded);
|
||||
|
||||
case AvailabilityDomain::Kind::Custom:
|
||||
switch (domain.getCustomDomain()->getKind()) {
|
||||
case CustomAvailabilityDomain::Kind::Enabled:
|
||||
case CustomAvailabilityDomain::Kind::AlwaysEnabled:
|
||||
return true;
|
||||
case CustomAvailabilityDomain::Kind::Disabled:
|
||||
case CustomAvailabilityDomain::Kind::Dynamic:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if unsatisfied introduction constraints for \p domain make
|
||||
/// code unreachable at runtime.
|
||||
static bool
|
||||
domainIsUnavailableAtRuntimeIfUnintroduced(AvailabilityDomain domain,
|
||||
const ASTContext &ctx) {
|
||||
switch (domain.getKind()) {
|
||||
case AvailabilityDomain::Kind::Universal:
|
||||
case AvailabilityDomain::Kind::Platform:
|
||||
case AvailabilityDomain::Kind::SwiftLanguage:
|
||||
case AvailabilityDomain::Kind::PackageDescription:
|
||||
return false;
|
||||
|
||||
case AvailabilityDomain::Kind::Embedded:
|
||||
return !ctx.LangOpts.hasFeature(Feature::Embedded);
|
||||
|
||||
case AvailabilityDomain::Kind::Custom:
|
||||
switch (domain.getCustomDomain()->getKind()) {
|
||||
case CustomAvailabilityDomain::Kind::Enabled:
|
||||
case CustomAvailabilityDomain::Kind::AlwaysEnabled:
|
||||
case CustomAvailabilityDomain::Kind::Dynamic:
|
||||
return false;
|
||||
case CustomAvailabilityDomain::Kind::Disabled:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool constraintIndicatesRuntimeUnavailability(
|
||||
const AvailabilityConstraint &constraint, const ASTContext &ctx) {
|
||||
std::optional<CustomAvailabilityDomain::Kind> customDomainKind;
|
||||
if (auto customDomain = constraint.getDomain().getCustomDomain())
|
||||
customDomainKind = customDomain->getKind();
|
||||
|
||||
auto domain = constraint.getDomain();
|
||||
switch (constraint.getReason()) {
|
||||
case AvailabilityConstraint::Reason::UnavailableUnconditionally:
|
||||
if (customDomainKind)
|
||||
return customDomainKind == CustomAvailabilityDomain::Kind::Enabled;
|
||||
return true;
|
||||
return domainCanBeUnconditionallyUnavailableAtRuntime(domain, ctx);
|
||||
case AvailabilityConstraint::Reason::UnavailableObsolete:
|
||||
case AvailabilityConstraint::Reason::UnavailableUnintroduced:
|
||||
return false;
|
||||
case AvailabilityConstraint::Reason::Unintroduced:
|
||||
if (customDomainKind)
|
||||
return customDomainKind == CustomAvailabilityDomain::Kind::Disabled;
|
||||
return false;
|
||||
return domainIsUnavailableAtRuntimeIfUnintroduced(domain, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ getCustomDomainKind(clang::FeatureAvailKind featureAvailKind) {
|
||||
return CustomAvailabilityDomain::Kind::Disabled;
|
||||
case clang::FeatureAvailKind::Dynamic:
|
||||
return CustomAvailabilityDomain::Kind::Dynamic;
|
||||
// FIXME: [availability] Add support for AlwaysEnabled.
|
||||
default:
|
||||
llvm::report_fatal_error("unexpected kind");
|
||||
}
|
||||
@@ -53,6 +54,7 @@ customDomainForClangDecl(ValueDecl *decl) {
|
||||
return nullptr;
|
||||
|
||||
// Check that the domain has a supported availability kind.
|
||||
// FIXME: [availability] Add support for AlwaysEnabled.
|
||||
switch (featureInfo.second.Kind) {
|
||||
case clang::FeatureAvailKind::Available:
|
||||
case clang::FeatureAvailKind::Unavailable:
|
||||
@@ -181,7 +183,8 @@ bool AvailabilityDomain::supportsQueries() const {
|
||||
}
|
||||
}
|
||||
|
||||
bool AvailabilityDomain::isActive(const ASTContext &ctx) const {
|
||||
bool AvailabilityDomain::isActive(const ASTContext &ctx,
|
||||
bool forTargetVariant) const {
|
||||
switch (getKind()) {
|
||||
case Kind::Universal:
|
||||
case Kind::SwiftLanguage:
|
||||
@@ -189,7 +192,7 @@ bool AvailabilityDomain::isActive(const ASTContext &ctx) const {
|
||||
case Kind::Embedded:
|
||||
return true;
|
||||
case Kind::Platform:
|
||||
return isPlatformActive(getPlatformKind(), ctx.LangOpts);
|
||||
return isPlatformActive(getPlatformKind(), ctx.LangOpts, forTargetVariant);
|
||||
case Kind::Custom:
|
||||
// For now, custom domains are always active but it's conceivable that in
|
||||
// the future someone might want to define a domain but leave it inactive.
|
||||
@@ -197,11 +200,12 @@ bool AvailabilityDomain::isActive(const ASTContext &ctx) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool AvailabilityDomain::isActivePlatform(const ASTContext &ctx) const {
|
||||
bool AvailabilityDomain::isActivePlatform(const ASTContext &ctx,
|
||||
bool forTargetVariant) const {
|
||||
if (!isPlatform())
|
||||
return false;
|
||||
|
||||
return isActive(ctx);
|
||||
return isActive(ctx, forTargetVariant);
|
||||
}
|
||||
|
||||
static std::optional<llvm::VersionTuple>
|
||||
@@ -224,8 +228,23 @@ getDeploymentVersion(const AvailabilityDomain &domain, const ASTContext &ctx) {
|
||||
|
||||
std::optional<AvailabilityRange>
|
||||
AvailabilityDomain::getDeploymentRange(const ASTContext &ctx) const {
|
||||
if (auto version = getDeploymentVersion(*this, ctx))
|
||||
return AvailabilityRange{*version};
|
||||
if (isVersioned()) {
|
||||
if (auto version = getDeploymentVersion(*this, ctx))
|
||||
return AvailabilityRange{*version};
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (auto customDomain = getCustomDomain()) {
|
||||
switch (customDomain->getKind()) {
|
||||
case CustomAvailabilityDomain::Kind::AlwaysEnabled:
|
||||
return AvailabilityRange::alwaysAvailable();
|
||||
case CustomAvailabilityDomain::Kind::Enabled:
|
||||
case CustomAvailabilityDomain::Kind::Disabled:
|
||||
case CustomAvailabilityDomain::Kind::Dynamic:
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
@@ -881,6 +881,7 @@ private:
|
||||
|
||||
switch (customDomain->getKind()) {
|
||||
case CustomAvailabilityDomain::Kind::Enabled:
|
||||
case CustomAvailabilityDomain::Kind::AlwaysEnabled:
|
||||
return AvailabilityQuery::constant(domain, true);
|
||||
case CustomAvailabilityDomain::Kind::Disabled:
|
||||
return AvailabilityQuery::constant(domain, false);
|
||||
|
||||
@@ -586,6 +586,7 @@ bool ArgsToFrontendOptionsConverter::computeAvailabilityDomains() {
|
||||
|
||||
for (const Arg *A :
|
||||
Args.filtered_reverse(OPT_define_enabled_availability_domain,
|
||||
OPT_define_always_enabled_availability_domain,
|
||||
OPT_define_disabled_availability_domain,
|
||||
OPT_define_dynamic_availability_domain)) {
|
||||
std::string domain = A->getValue();
|
||||
@@ -602,6 +603,8 @@ bool ArgsToFrontendOptionsConverter::computeAvailabilityDomains() {
|
||||
auto &option = A->getOption();
|
||||
if (option.matches(OPT_define_enabled_availability_domain))
|
||||
Opts.AvailabilityDomains.EnabledDomains.emplace_back(domain);
|
||||
if (option.matches(OPT_define_always_enabled_availability_domain))
|
||||
Opts.AvailabilityDomains.AlwaysEnabledDomains.emplace_back(domain);
|
||||
else if (option.matches(OPT_define_disabled_availability_domain))
|
||||
Opts.AvailabilityDomains.DisabledDomains.emplace_back(domain);
|
||||
else if (option.matches(OPT_define_dynamic_availability_domain))
|
||||
|
||||
@@ -1455,6 +1455,9 @@ static void configureAvailabilityDomains(const ASTContext &ctx,
|
||||
|
||||
for (auto enabled : opts.AvailabilityDomains.EnabledDomains)
|
||||
createAndInsertDomain(enabled, CustomAvailabilityDomain::Kind::Enabled);
|
||||
for (auto alwaysEnabled : opts.AvailabilityDomains.AlwaysEnabledDomains)
|
||||
createAndInsertDomain(alwaysEnabled,
|
||||
CustomAvailabilityDomain::Kind::AlwaysEnabled);
|
||||
for (auto disabled : opts.AvailabilityDomains.DisabledDomains)
|
||||
createAndInsertDomain(disabled, CustomAvailabilityDomain::Kind::Disabled);
|
||||
for (auto dynamic : opts.AvailabilityDomains.DynamicDomains)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// RUN: %target-typecheck-verify-swift \
|
||||
// RUN: -enable-experimental-feature CustomAvailability \
|
||||
// RUN: -define-enabled-availability-domain EnabledDomain \
|
||||
// RUN: -define-always-enabled-availability-domain AlwaysEnabledDomain \
|
||||
// RUN: -define-disabled-availability-domain DisabledDomain \
|
||||
// RUN: -define-dynamic-availability-domain DynamicDomain
|
||||
|
||||
@@ -11,9 +12,15 @@ func alwaysAvailable() { }
|
||||
@available(EnabledDomain)
|
||||
func availableInEnabledDomain() { }
|
||||
|
||||
@available(AlwaysEnabledDomain)
|
||||
func availableInAlwaysEnabledDomain() { }
|
||||
|
||||
@available(EnabledDomain, unavailable)
|
||||
func unavailableInEnabledDomain() { } // expected-note * {{'unavailableInEnabledDomain()' has been explicitly marked unavailable here}}
|
||||
|
||||
@available(AlwaysEnabledDomain, unavailable)
|
||||
func unavailableInAlwaysEnabledDomain() { } // expected-note * {{'unavailableInAlwaysEnabledDomain()' has been explicitly marked unavailable here}}
|
||||
|
||||
@available(DisabledDomain, unavailable)
|
||||
func unavailableInDisabledDomain() { } // expected-note * {{'unavailableInDisabledDomain()' has been explicitly marked unavailable here}}
|
||||
|
||||
@@ -41,7 +48,9 @@ func testDeployment() { // expected-note 3 {{add '@available' attribute to enclo
|
||||
alwaysAvailable()
|
||||
availableInEnabledDomain() // expected-error {{'availableInEnabledDomain()' is only available in EnabledDomain}}
|
||||
// expected-note@-1 {{add 'if #available' version check}}
|
||||
availableInAlwaysEnabledDomain()
|
||||
unavailableInEnabledDomain() // expected-error {{'unavailableInEnabledDomain()' is unavailable}}
|
||||
unavailableInAlwaysEnabledDomain() // expected-error {{'unavailableInAlwaysEnabledDomain()' is unavailable}}
|
||||
unavailableInDisabledDomain() // expected-error {{'unavailableInDisabledDomain()' is unavailable}}
|
||||
deprecatedInDynamicDomain() // expected-warning {{'deprecatedInDynamicDomain()' is deprecated: Use something else}}
|
||||
unavailableInDynamicDomain() // expected-error {{'unavailableInDynamicDomain()' is unavailable}}
|
||||
@@ -53,10 +62,14 @@ func testDeployment() { // expected-note 3 {{add '@available' attribute to enclo
|
||||
availableAndUnavailableInEnabledDomain() // expected-error {{'availableAndUnavailableInEnabledDomain()' is unavailable}}
|
||||
}
|
||||
|
||||
// FIXME: [availability] Test @inlinable functions.
|
||||
|
||||
func testIfAvailable(_ truthy: Bool) { // expected-note 9 {{add '@available' attribute to enclosing global function}}
|
||||
if #available(EnabledDomain) { // expected-note {{enclosing scope here}}
|
||||
availableInEnabledDomain()
|
||||
availableInAlwaysEnabledDomain()
|
||||
unavailableInEnabledDomain() // expected-error {{'unavailableInEnabledDomain()' is unavailable}}
|
||||
unavailableInAlwaysEnabledDomain() // expected-error {{'unavailableInAlwaysEnabledDomain()' is unavailable}}
|
||||
availableInDynamicDomain() // expected-error {{'availableInDynamicDomain()' is only available in DynamicDomain}}
|
||||
// expected-note@-1 {{add 'if #available' version check}}
|
||||
unavailableInDynamicDomain() // expected-error {{'unavailableInDynamicDomain()' is unavailable}}
|
||||
@@ -133,6 +146,14 @@ func testIfAvailable(_ truthy: Bool) { // expected-note 9 {{add '@available' att
|
||||
if #unavailable(EnabledDomain), #available(DynamicDomain) {
|
||||
// expected-error@-1 {{#available and #unavailable cannot be in the same statement}}
|
||||
}
|
||||
|
||||
if #available(AlwaysEnabledDomain) {
|
||||
availableInAlwaysEnabledDomain()
|
||||
unavailableInAlwaysEnabledDomain() // expected-error {{'unavailableInAlwaysEnabledDomain()' is unavailable}}
|
||||
} else {
|
||||
availableInAlwaysEnabledDomain()
|
||||
unavailableInAlwaysEnabledDomain()
|
||||
}
|
||||
}
|
||||
|
||||
func testWhileAvailable() { // expected-note {{add '@available' attribute to enclosing global function}}
|
||||
@@ -207,6 +228,18 @@ func testEnabledDomainUnavailable() { // expected-note {{add '@available' attrib
|
||||
availableInUnknownDomain()
|
||||
}
|
||||
|
||||
@available(AlwaysEnabledDomain)
|
||||
func testAlwaysEnabledDomainAvailable() {
|
||||
availableInAlwaysEnabledDomain()
|
||||
unavailableInAlwaysEnabledDomain() // expected-error {{'unavailableInAlwaysEnabledDomain()' is unavailable}}
|
||||
}
|
||||
|
||||
@available(AlwaysEnabledDomain, unavailable)
|
||||
func testAlwaysEnabledDomainUnavailable() {
|
||||
availableInAlwaysEnabledDomain()
|
||||
unavailableInAlwaysEnabledDomain()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
func testUniversallyUnavailable() {
|
||||
alwaysAvailable()
|
||||
@@ -214,6 +247,9 @@ func testUniversallyUnavailable() {
|
||||
// in contexts that are unavailable to broader domains
|
||||
availableInEnabledDomain() // expected-error {{'availableInEnabledDomain()' is only available in EnabledDomain}}
|
||||
// expected-note@-1 {{add 'if #available' version check}}
|
||||
unavailableInEnabledDomain()
|
||||
availableInAlwaysEnabledDomain()
|
||||
unavailableInAlwaysEnabledDomain()
|
||||
unavailableInDisabledDomain()
|
||||
deprecatedInDynamicDomain() // expected-warning {{'deprecatedInDynamicDomain()' is deprecated: Use something else}}
|
||||
availableInDynamicDomain() // expected-error {{'availableInDynamicDomain()' is only available in DynamicDomain}}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
// RUN: %target-swift-emit-irgen -module-name Test %s -verify \
|
||||
// RUN: -enable-experimental-feature CustomAvailability \
|
||||
// RUN: -define-enabled-availability-domain EnabledDomain \
|
||||
// RUN: -define-always-enabled-availability-domain AlwaysEnabledDomain \
|
||||
// RUN: -define-disabled-availability-domain DisabledDomain \
|
||||
// RUN: -Onone | %FileCheck %s --check-prefixes=CHECK
|
||||
|
||||
// RUN: %target-swift-emit-irgen -module-name Test %s -verify \
|
||||
// RUN: -enable-experimental-feature CustomAvailability \
|
||||
// RUN: -define-enabled-availability-domain EnabledDomain \
|
||||
// RUN: -define-always-enabled-availability-domain AlwaysEnabledDomain \
|
||||
// RUN: -define-disabled-availability-domain DisabledDomain \
|
||||
// RUN: -O | %FileCheck %s --check-prefixes=CHECK
|
||||
|
||||
@@ -29,6 +31,17 @@ public func ifAvailableEnabledDomain() {
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}}swiftcc void @"$s4Test30ifAvailableAlwaysEnabledDomainyyF"()
|
||||
// CHECK: call swiftcc void @always()
|
||||
// CHECK-NOT: call swiftcc void @never()
|
||||
public func ifAvailableAlwaysEnabledDomain() {
|
||||
if #available(AlwaysEnabledDomain) {
|
||||
always()
|
||||
} else {
|
||||
never()
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}}swiftcc void @"$s4Test25ifAvailableDisabledDomainyyF"()
|
||||
// CHECK-NOT: call swiftcc void @never()
|
||||
// CHECK: call swiftcc void @always()
|
||||
@@ -51,6 +64,17 @@ public func ifUnavailableEnabledDomain() {
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}}swiftcc void @"$s4Test32ifUnavailableAlwaysEnabledDomainyyF"()
|
||||
// CHECK-NOT: call swiftcc void @never()
|
||||
// CHECK: call swiftcc void @always()
|
||||
public func ifUnavailableAlwaysEnabledDomain() {
|
||||
if #unavailable(EnabledDomain) {
|
||||
never()
|
||||
} else {
|
||||
always()
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}}swiftcc void @"$s4Test27ifUnavailableDisabledDomainyyF"()
|
||||
// CHECK: call swiftcc void @always()
|
||||
// CHECK-NOT: call swiftcc void @never()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// RUN: %target-swift-emit-silgen -module-name Test %s -verify \
|
||||
// RUN: -enable-experimental-feature CustomAvailability \
|
||||
// RUN: -define-enabled-availability-domain EnabledDomain \
|
||||
// RUN: -define-always-enabled-availability-domain AlwaysEnabledDomain \
|
||||
// RUN: -define-disabled-availability-domain DisabledDomain \
|
||||
// RUN: -define-dynamic-availability-domain DynamicDomain \
|
||||
// RUN: | %FileCheck %s
|
||||
@@ -13,6 +14,12 @@ public func availableInEnabledDomain() { }
|
||||
@available(EnabledDomain, unavailable)
|
||||
public func unavailableInEnabledDomain() { }
|
||||
|
||||
@available(AlwaysEnabledDomain)
|
||||
public func availableInAlwaysEnabledDomain() { }
|
||||
|
||||
@available(AlwaysEnabledDomain, unavailable)
|
||||
public func unavailableInAlwaysEnabledDomain() { }
|
||||
|
||||
@available(DisabledDomain)
|
||||
public func availableInDisabledDomain() { }
|
||||
|
||||
@@ -63,6 +70,44 @@ public func testIfUnavailableEnabledDomain() {
|
||||
}
|
||||
// CHECK: end sil function '$s4Test30testIfUnavailableEnabledDomainyyF'
|
||||
|
||||
// CHECK-LABEL: sil{{.*}}$s4Test34testIfAvailableAlwaysEnabledDomainyyF : $@convention(thin) () -> ()
|
||||
public func testIfAvailableAlwaysEnabledDomain() {
|
||||
// CHECK: bb0:
|
||||
// CHECK: [[PRED:%.*]] = integer_literal $Builtin.Int1, -1
|
||||
// CHECK: cond_br [[PRED]], [[TRUE_BB:bb[0-9]+]], [[FALSE_BB:bb[0-9]+]]
|
||||
|
||||
// CHECK: [[TRUE_BB]]:
|
||||
// CHECK: function_ref @$s4Test30availableInAlwaysEnabledDomainyyF
|
||||
|
||||
// CHECK: [[FALSE_BB]]:
|
||||
// CHECK: function_ref @$s4Test32unavailableInAlwaysEnabledDomainyyF
|
||||
if #available(AlwaysEnabledDomain) {
|
||||
availableInAlwaysEnabledDomain()
|
||||
} else {
|
||||
unavailableInAlwaysEnabledDomain()
|
||||
}
|
||||
}
|
||||
// CHECK: end sil function '$s4Test34testIfAvailableAlwaysEnabledDomainyyF'
|
||||
|
||||
// CHECK-LABEL: sil{{.*}}$s4Test36testIfUnavailableAlwaysEnabledDomainyyF : $@convention(thin) () -> ()
|
||||
public func testIfUnavailableAlwaysEnabledDomain() {
|
||||
// CHECK: bb0:
|
||||
// CHECK: [[PRED:%.*]] = integer_literal $Builtin.Int1, 0
|
||||
// CHECK: cond_br [[PRED]], [[TRUE_BB:bb[0-9]+]], [[FALSE_BB:bb[0-9]+]]
|
||||
|
||||
// CHECK: [[TRUE_BB]]:
|
||||
// CHECK: function_ref @$s4Test32unavailableInAlwaysEnabledDomainyyF
|
||||
|
||||
// CHECK: [[FALSE_BB]]:
|
||||
// CHECK: function_ref @$s4Test30availableInAlwaysEnabledDomainyyF
|
||||
if #unavailable(AlwaysEnabledDomain) {
|
||||
unavailableInAlwaysEnabledDomain()
|
||||
} else {
|
||||
availableInAlwaysEnabledDomain()
|
||||
}
|
||||
}
|
||||
// CHECK: end sil function '$s4Test36testIfUnavailableAlwaysEnabledDomainyyF'
|
||||
|
||||
// CHECK-LABEL: sil{{.*}}$s4Test29testIfAvailableDisabledDomainyyF : $@convention(thin) () -> ()
|
||||
public func testIfAvailableDisabledDomain() {
|
||||
// CHECK: bb0:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// RUN: %target-swift-emit-silgen -module-name Test %s -verify \
|
||||
// RUN: -enable-experimental-feature CustomAvailability \
|
||||
// RUN: -define-enabled-availability-domain EnabledDomain \
|
||||
// RUN: -define-always-enabled-availability-domain AlwaysEnabledDomain \
|
||||
// RUN: -define-disabled-availability-domain DisabledDomain \
|
||||
// RUN: -define-dynamic-availability-domain DynamicDomain \
|
||||
// RUN: | %FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT
|
||||
@@ -8,6 +9,7 @@
|
||||
// RUN: %target-swift-emit-silgen -module-name Test %s -verify \
|
||||
// RUN: -enable-experimental-feature CustomAvailability \
|
||||
// RUN: -define-enabled-availability-domain EnabledDomain \
|
||||
// RUN: -define-always-enabled-availability-domain AlwaysEnabledDomain \
|
||||
// RUN: -define-disabled-availability-domain DisabledDomain \
|
||||
// RUN: -define-dynamic-availability-domain DynamicDomain \
|
||||
// RUN: -unavailable-decl-optimization=complete \
|
||||
@@ -26,6 +28,14 @@ public func availableInEnabledDomain() { }
|
||||
@available(EnabledDomain, unavailable)
|
||||
public func unavailableInEnabledDomain() { }
|
||||
|
||||
// CHECK: s4Test30availableInAlwaysEnabledDomainyyF
|
||||
@available(AlwaysEnabledDomain)
|
||||
public func availableInAlwaysEnabledDomain() { }
|
||||
|
||||
// CHECK-NOT: s4Test32unavailableInAlwaysEnabledDomainyyF
|
||||
@available(AlwaysEnabledDomain, unavailable)
|
||||
public func unavailableInAlwaysEnabledDomain() { }
|
||||
|
||||
// CHECK-NOT: s4Test25availableInDisabledDomainyyF
|
||||
@available(DisabledDomain)
|
||||
public func availableInDisabledDomain() { }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// RUN: %target-typecheck-verify-swift \
|
||||
// RUN: -enable-experimental-feature CustomAvailability \
|
||||
// RUN: -define-enabled-availability-domain EnabledDomain \
|
||||
// RUN: -define-always-enabled-availability-domain AlwaysEnabledDomain \
|
||||
// RUN: -define-enabled-availability-domain RedefinedDomain \
|
||||
// RUN: -define-disabled-availability-domain DisabledDomain \
|
||||
// RUN: -define-dynamic-availability-domain DynamicDomain \
|
||||
@@ -22,6 +23,9 @@ func availableInEnabledDomainWithWildcard() { }
|
||||
@available(EnabledDomain, introduced: 1.0) // expected-error {{unexpected version number for EnabledDomain}}
|
||||
func introducedInEnabledDomain() { }
|
||||
|
||||
@available(AlwaysEnabledDomain, introduced: 1.0) // expected-error {{unexpected version number for AlwaysEnabledDomain}}
|
||||
func introducedInAlwaysEnabledDomain() { }
|
||||
|
||||
@available(EnabledDomain 1.0) // expected-error {{unexpected version number for EnabledDomain}}
|
||||
func introducedInEnabledDomainShort() { }
|
||||
|
||||
@@ -31,6 +35,9 @@ func introducedInEnabledDomainShortWithWildcard() { }
|
||||
@available(macOS 10.10, EnabledDomain, *) // expected-error {{EnabledDomain availability must be specified alone}}
|
||||
func introducedInMacOSAndAvailableInEnabledDomain() { }
|
||||
|
||||
@available(macOS 10.10, AlwaysEnabledDomain, *) // expected-error {{AlwaysEnabledDomain availability must be specified alone}}
|
||||
func introducedInMacOSAndAvailableInAlwaysEnabledDomain() { }
|
||||
|
||||
@available(EnabledDomain, macOS 10.10, *) // expected-error {{expected 'available' option such as 'unavailable', 'introduced', 'deprecated', 'obsoleted', 'message', or 'renamed'}}
|
||||
// expected-error@-1 {{expected declaration}}
|
||||
func availableInEnabledDomainAndIntroducedInMacOS() { }
|
||||
|
||||
Reference in New Issue
Block a user