Skip to content

Commit f115676

Browse files
committed
Frontend: Introduce options for defining availability domains.
1 parent 3cc3031 commit f115676

File tree

5 files changed

+100
-0
lines changed

5 files changed

+100
-0
lines changed

include/swift/Frontend/FrontendOptions.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,18 @@ class FrontendOptions {
573573
/// All block list configuration files to be honored in this compilation.
574574
std::vector<std::string> BlocklistConfigFilePaths;
575575

576+
struct CustomAvailabilityDomains {
577+
/// Domains defined with `-define-enabled-availability-domain=`.
578+
llvm::SmallVector<std::string> EnabledDomains;
579+
/// Domains defined with `-define-disabled-availability-domain=`.
580+
llvm::SmallVector<std::string> DisabledDomains;
581+
/// Domains defined with `-define-dynamic-availability-domain=`.
582+
llvm::SmallVector<std::string> DynamicDomains;
583+
};
584+
585+
/// The collection of AvailabilityDomain definitions specified as arguments.
586+
CustomAvailabilityDomains AvailabilityDomains;
587+
576588
private:
577589
static bool canActionEmitDependencies(ActionType);
578590
static bool canActionEmitReferenceDependencies(ActionType);

include/swift/Option/Options.td

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,21 @@ def unavailable_decl_optimization_EQ : Joined<["-"], "unavailable-decl-optimizat
561561
"value may be 'none' (no optimization) or 'complete' (code is not "
562562
"generated at all unavailable declarations)">;
563563

564+
def define_enabled_availability_domain : Separate<["-"], "define-enabled-availability-domain">,
565+
Flags<[HelpHidden, FrontendOption, NoInteractiveOption, ModuleInterfaceOptionIgnorable]>,
566+
HelpText<"Defines a custom availability domain that is available at compile time">,
567+
MetaVarName<"<domain>">;
568+
569+
def define_disabled_availability_domain : Separate<["-"], "define-disabled-availability-domain">,
570+
Flags<[HelpHidden, FrontendOption, NoInteractiveOption, ModuleInterfaceOptionIgnorable]>,
571+
HelpText<"Defines a custom availability domain that is unavailable at compile time">,
572+
MetaVarName<"<domain>">;
573+
574+
def define_dynamic_availability_domain : Separate<["-"], "define-dynamic-availability-domain">,
575+
Flags<[HelpHidden, FrontendOption, NoInteractiveOption, ModuleInterfaceOptionIgnorable]>,
576+
HelpText<"Defines a custom availability domain that can be enabled or disabled at runtime">,
577+
MetaVarName<"<domain>">;
578+
564579
def experimental_package_bypass_resilience : Flag<["-"], "experimental-package-bypass-resilience">,
565580
Flags<[FrontendOption]>,
566581
HelpText<"Deprecated; has no effect">;

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,10 @@ bool ArgsToFrontendOptionsConverter::convert(
419419
}
420420

421421
Opts.DisableSandbox = Args.hasArg(OPT_disable_sandbox);
422+
423+
if (computeAvailabilityDomains())
424+
return true;
425+
422426
return false;
423427
}
424428

@@ -548,6 +552,39 @@ void ArgsToFrontendOptionsConverter::computeDumpScopeMapLocations() {
548552
Diags.diagnose(SourceLoc(), diag::error_no_source_location_scope_map);
549553
}
550554

555+
bool ArgsToFrontendOptionsConverter::computeAvailabilityDomains() {
556+
using namespace options;
557+
558+
bool hadError = false;
559+
llvm::SmallSet<std::string, 4> seenDomains;
560+
561+
for (const Arg *A :
562+
Args.filtered_reverse(OPT_define_enabled_availability_domain,
563+
OPT_define_disabled_availability_domain,
564+
OPT_define_dynamic_availability_domain)) {
565+
std::string domain = A->getValue();
566+
if (!seenDomains.insert(domain).second)
567+
continue;
568+
569+
if (!Lexer::isIdentifier(domain)) {
570+
Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
571+
A->getAsString(Args), A->getValue());
572+
hadError = true;
573+
continue;
574+
}
575+
576+
auto &option = A->getOption();
577+
if (option.matches(OPT_define_enabled_availability_domain))
578+
Opts.AvailabilityDomains.EnabledDomains.emplace_back(domain);
579+
else if (option.matches(OPT_define_disabled_availability_domain))
580+
Opts.AvailabilityDomains.DisabledDomains.emplace_back(domain);
581+
else if (option.matches(OPT_define_dynamic_availability_domain))
582+
Opts.AvailabilityDomains.DynamicDomains.emplace_back(domain);
583+
}
584+
585+
return hadError;
586+
}
587+
551588
FrontendOptions::ActionType
552589
ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) {
553590
using namespace options;

lib/Frontend/ArgsToFrontendOptionsConverter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class ArgsToFrontendOptionsConverter {
4848
void computePlaygroundOptions();
4949
void computePrintStatsOptions();
5050
void computeTBDOptions();
51+
bool computeAvailabilityDomains();
5152

5253
bool setUpImmediateArgs();
5354

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %target-typecheck-verify-swift \
2+
// RUN: -enable-experimental-feature CustomAvailability \
3+
// RUN: -define-enabled-availability-domain EnabledDomain \
4+
// RUN: -define-enabled-availability-domain RedefinedDomain \
5+
// RUN: -define-disabled-availability-domain DisabledDomain \
6+
// RUN: -define-dynamic-availability-domain DynamicDomain \
7+
// RUN: -define-disabled-availability-domain RedefinedDomain
8+
9+
// REQUIRES: swift_feature_CustomAvailability
10+
11+
// expected-error@+1 {{expected ',' in 'available' attribute}}
12+
@available(EnabledDomain) // expected-warning {{unknown platform 'EnabledDomain' for attribute 'available'}}
13+
func availableInEnabledDomain() { }
14+
15+
@available(DisabledDomain, unavailable) // expected-warning {{unknown platform 'DisabledDomain' for attribute 'available'}}
16+
func availableInDisabledDomain() { }
17+
18+
@available(RedefinedDomain, deprecated, message: "Use something else") // expected-warning {{unknown platform 'RedefinedDomain' for attribute 'available'}}
19+
func availableInRedefinedDomain() { }
20+
21+
// expected-error@+1 {{expected ',' in 'available' attribute}}
22+
@available(DynamicDomain) // expected-warning {{unknown platform 'DynamicDomain' for attribute 'available'}}
23+
func availableInDynamicDomain() { }
24+
25+
// expected-error@+1 {{expected ',' in 'available' attribute}}
26+
@available(UnknownDomain) // expected-warning {{unknown platform 'UnknownDomain' for attribute 'available'}}
27+
func availableInUnknownDomain() { }
28+
29+
func test() {
30+
availableInEnabledDomain()
31+
availableInDisabledDomain()
32+
availableInRedefinedDomain()
33+
availableInDynamicDomain()
34+
availableInUnknownDomain()
35+
}

0 commit comments

Comments
 (0)