Skip to content

Commit c56dd2e

Browse files
committed
[ASTGen] Generate miscellaneous availability related nodes
* `@_specialize` with `availability:` arguments * `@backDeployed` attributes * `@_originallyDefinedIn` attributes * `#available()` and `#unavailable()` statement conditions
1 parent 8d69807 commit c56dd2e

File tree

12 files changed

+328
-50
lines changed

12 files changed

+328
-50
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ enum class MacroRole : uint32_t;
5151
class MacroIntroducedDeclName;
5252
enum class MacroIntroducedDeclNameKind;
5353
enum class ParamSpecifier : uint8_t;
54+
enum class PlatformKind : uint8_t;
5455
class ProtocolConformanceRef;
5556
class RegexLiteralPatternFeature;
5657
class RegexLiteralPatternFeatureKind;
@@ -589,6 +590,8 @@ enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedPlatformKind : size_t {
589590
SWIFT_NAME("BridgedPlatformKind.init(from:)")
590591
BridgedPlatformKind BridgedPlatformKind_fromString(BridgedStringRef cStr);
591592

593+
swift::PlatformKind unbridge(BridgedPlatformKind cPlatform);
594+
592595
SWIFT_NAME("BridgedAvailabilityMacroMap.has(self:name:)")
593596
bool BridgedAvailabilityMacroMap_hasName(BridgedAvailabilityMacroMap map,
594597
BridgedStringRef name);
@@ -627,6 +630,10 @@ SWIFT_NAME("getter:BridgedAvailabilitySpec.domain(self:)")
627630
BridgedAvailabilityDomain
628631
BridgedAvailabilitySpec_getDomain(BridgedAvailabilitySpec spec);
629632

633+
SWIFT_NAME("getter:BridgedAvailabilitySpec.platform(self:)")
634+
BridgedPlatformKind
635+
BridgedAvailabilitySpec_getPlatform(BridgedAvailabilitySpec spec);
636+
630637
SWIFT_NAME("getter:BridgedAvailabilitySpec.version(self:)")
631638
BridgedVersionTuple
632639
BridgedAvailabilitySpec_getVersion(BridgedAvailabilitySpec spec);
@@ -802,6 +809,13 @@ BridgedAllowFeatureSuppressionAttr_createParsed(
802809
bool inverted,
803810
BridgedArrayRef cFeatures);
804811

812+
SWIFT_NAME(
813+
"BridgedBackDeployedAttr.createParsed(_:atLoc:range:platform:version:)")
814+
BridgedBackDeployedAttr BridgedBackDeployedAttr_createParsed(
815+
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
816+
BridgedSourceRange cRange, BridgedPlatformKind cPlatform,
817+
BridgedVersionTuple cVersion);
818+
805819
SWIFT_NAME("BridgedCDeclAttr.createParsed(_:atLoc:range:name:)")
806820
BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
807821
BridgedSourceLoc cAtLoc,
@@ -949,6 +963,13 @@ BridgedMacroRoleAttr BridgedMacroRoleAttr_createParsed(
949963
BridgedSourceLoc cLParenLoc, BridgedMacroRole cRole, BridgedArrayRef cNames,
950964
BridgedArrayRef cConformances, BridgedSourceLoc cRParenLoc);
951965

966+
SWIFT_NAME("BridgedOriginallyDefinedInAttr.createParsed(_:atLoc:range:"
967+
"moduleName:platform:version:)")
968+
BridgedOriginallyDefinedInAttr BridgedOriginallyDefinedInAttr_createParsed(
969+
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
970+
BridgedSourceRange cRange, BridgedStringRef cModuleName,
971+
BridgedPlatformKind cPlatform, BridgedVersionTuple cVersion);
972+
952973
SWIFT_NAME("BridgedStorageRestrictionsAttr.createParsed(_:atLoc:range:"
953974
"initializes:accesses:)")
954975
BridgedStorageRestrictionsAttr BridgedStorageRestrictionsAttr_createParsed(
@@ -1949,6 +1970,17 @@ BridgedStmtConditionElement BridgedStmtConditionElement_createPatternBinding(
19491970
BridgedASTContext cContext, BridgedSourceLoc cIntroducerLoc,
19501971
BridgedPattern cPattern, BridgedExpr cInitializer);
19511972

1973+
SWIFT_NAME("BridgedStmtConditionElement.createPoundAvailable(info:)")
1974+
BridgedStmtConditionElement BridgedStmtConditionElement_createPoundAvailable(
1975+
BridgedPoundAvailableInfo info);
1976+
1977+
SWIFT_NAME("BridgedPoundAvailableInfo.createParsed(_:poundLoc:lParenLoc:specs:"
1978+
"rParenLoc:isUnavailable:)")
1979+
BridgedPoundAvailableInfo BridgedPoundAvailableInfo_createParsed(
1980+
BridgedASTContext cContext, BridgedSourceLoc cPoundLoc,
1981+
BridgedSourceLoc cLParenLoc, BridgedArrayRef cSpecs,
1982+
BridgedSourceLoc cRParenLoc, bool isUnavailability);
1983+
19521984
struct BridgedCaseLabelItemInfo {
19531985
SWIFT_NAME("isDefault")
19541986
bool IsDefault;

include/swift/AST/ASTBridgingWrappers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ AST_BRIDGING_WRAPPER_NULLABLE(PlatformVersionConstraintAvailabilitySpec)
111111
AST_BRIDGING_WRAPPER_NULLABLE(PlatformAgnosticVersionConstraintAvailabilitySpec)
112112
AST_BRIDGING_WRAPPER_NULLABLE(OtherPlatformAvailabilitySpec)
113113
AST_BRIDGING_WRAPPER_CONST_NONNULL(AvailabilityMacroMap)
114+
AST_BRIDGING_WRAPPER_NONNULL(PoundAvailableInfo)
114115

115116
// Non-AST types to generate wrappers for.
116117
AST_BRIDGING_WRAPPER_NULLABLE(DiagnosticEngine)

include/swift/AST/AvailabilitySpec.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
6060

6161
std::optional<AvailabilityDomain> getDomain() const;
6262

63+
std::optional<PlatformKind> getPlatform() const;
64+
6365
llvm::VersionTuple getVersion() const;
6466

6567
SourceRange getVersionSrcRange() const;

lib/AST/AvailabilitySpec.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@ std::optional<AvailabilityDomain> AvailabilitySpec::getDomain() const {
5252
llvm_unreachable("bad AvailabilitySpecKind");
5353
}
5454

55+
std::optional<PlatformKind> AvailabilitySpec::getPlatform() const {
56+
switch (getKind()) {
57+
case AvailabilitySpecKind::PlatformVersionConstraint: {
58+
auto spec = cast<PlatformVersionConstraintAvailabilitySpec>(this);
59+
return spec->getPlatform();
60+
}
61+
case AvailabilitySpecKind::LanguageVersionConstraint:
62+
case AvailabilitySpecKind::PackageDescriptionVersionConstraint:
63+
case AvailabilitySpecKind::OtherPlatform:
64+
return std::nullopt;
65+
}
66+
llvm_unreachable("bad AvailabilitySpecKind");
67+
}
68+
5569
llvm::VersionTuple AvailabilitySpec::getVersion() const {
5670
switch (getKind()) {
5771
case AvailabilitySpecKind::PlatformVersionConstraint: {

lib/AST/Bridging/AvailabilityBridging.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ BridgedPlatformKind BridgedPlatformKind_fromString(BridgedStringRef cStr) {
5858
}
5959
}
6060

61-
static PlatformKind unbridge(BridgedPlatformKind platform) {
61+
PlatformKind unbridge(BridgedPlatformKind platform) {
6262
switch (platform) {
6363
case BridgedPlatformKind_None:
6464
return PlatformKind::none;
@@ -70,6 +70,18 @@ static PlatformKind unbridge(BridgedPlatformKind platform) {
7070
llvm_unreachable("unhandled enum value");
7171
}
7272

73+
static BridgedPlatformKind bridge(PlatformKind platform) {
74+
switch (platform) {
75+
case PlatformKind::none:
76+
return BridgedPlatformKind_None;
77+
#define AVAILABILITY_PLATFORM(X, PrettyName) \
78+
case PlatformKind::X: \
79+
return BridgedPlatformKind_##X;
80+
#include "swift/AST/PlatformKinds.def"
81+
}
82+
llvm_unreachable("unhandled enum value");
83+
}
84+
7385
//===----------------------------------------------------------------------===//
7486
// MARK: AvailabilitySpec
7587
//===----------------------------------------------------------------------===//
@@ -87,6 +99,14 @@ BridgedAvailabilitySpec_getDomain(BridgedAvailabilitySpec spec) {
8799
return BridgedAvailabilityDomain();
88100
}
89101

102+
BridgedPlatformKind
103+
BridgedAvailabilitySpec_getPlatform(BridgedAvailabilitySpec spec) {
104+
auto platform = spec.unbridged()->getPlatform();
105+
if (platform)
106+
return bridge(*platform);
107+
return BridgedPlatformKind_None;
108+
}
109+
90110
BridgedVersionTuple
91111
BridgedAvailabilitySpec_getVersion(BridgedAvailabilitySpec spec) {
92112
return spec.unbridged()->getVersion();

lib/AST/Bridging/DeclAttributeBridging.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,15 @@ BridgedAllowFeatureSuppressionAttr_createParsed(BridgedASTContext cContext,
185185
/*implicit*/ false, inverted, features);
186186
}
187187

188+
BridgedBackDeployedAttr BridgedBackDeployedAttr_createParsed(
189+
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
190+
BridgedSourceRange cRange, BridgedPlatformKind cPlatform,
191+
BridgedVersionTuple cVersion) {
192+
return new (cContext.unbridged()) BackDeployedAttr(
193+
cAtLoc.unbridged(), cRange.unbridged(), unbridge(cPlatform),
194+
cVersion.unbridged(), /*Implicit=*/false);
195+
}
196+
188197
BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
189198
BridgedSourceLoc cAtLoc,
190199
BridgedSourceRange cRange,
@@ -388,6 +397,16 @@ BridgedMacroRoleAttr BridgedMacroRoleAttr_createParsed(
388397
conformances, cRParenLoc.unbridged(), /*implicit=*/false);
389398
}
390399

400+
BridgedOriginallyDefinedInAttr BridgedOriginallyDefinedInAttr_createParsed(
401+
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
402+
BridgedSourceRange cRange, BridgedStringRef cModuleName,
403+
BridgedPlatformKind cPlatform, BridgedVersionTuple cVersion) {
404+
return new (cContext.unbridged()) OriginallyDefinedInAttr(
405+
cAtLoc.unbridged(), cRange.unbridged(), cModuleName.unbridged(),
406+
unbridge(cPlatform), cVersion.unbridged(),
407+
/*Implicit=*/false);
408+
}
409+
391410
BridgedStorageRestrictionsAttr BridgedStorageRestrictionsAttr_createParsed(
392411
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
393412
BridgedSourceRange cRange, BridgedArrayRef cInitializes,

lib/AST/Bridging/StmtBridging.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,23 @@ BridgedStmtConditionElement BridgedStmtConditionElement_createPatternBinding(
5252
cInitializer.unbridged()));
5353
}
5454

55+
BridgedStmtConditionElement BridgedStmtConditionElement_createPoundAvailable(
56+
BridgedPoundAvailableInfo info) {
57+
return StmtConditionElement(info.unbridged());
58+
}
59+
60+
BridgedPoundAvailableInfo BridgedPoundAvailableInfo_createParsed(
61+
BridgedASTContext cContext, BridgedSourceLoc cPoundLoc,
62+
BridgedSourceLoc cLParenLoc, BridgedArrayRef cSpecs,
63+
BridgedSourceLoc cRParenLoc, bool isUnavailability) {
64+
SmallVector<AvailabilitySpec *, 4> specs;
65+
for (auto cSpec : cSpecs.unbridged<BridgedAvailabilitySpec>())
66+
specs.push_back(cSpec.unbridged());
67+
return PoundAvailableInfo::create(cContext.unbridged(), cPoundLoc.unbridged(),
68+
cLParenLoc.unbridged(), specs,
69+
cRParenLoc.unbridged(), isUnavailability);
70+
}
71+
5572
BridgedBraceStmt BridgedBraceStmt_createParsed(BridgedASTContext cContext,
5673
BridgedSourceLoc cLBLoc,
5774
BridgedArrayRef elements,

lib/ASTGen/Sources/ASTGen/Availability.swift

Lines changed: 99 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,12 @@ import SwiftIfConfig
1919
@_spi(RawSyntax) @_spi(Compiler) import SwiftSyntax
2020

2121
extension ASTGenVisitor {
22-
/// E.g.:
23-
/// ```
24-
/// @available(macOS 10.12, iOS 13, *)
25-
/// @available(macOS, introduced: 10.12)
26-
/// ```
27-
func generateAvailableAttr(attribute node: AttributeSyntax) -> [BridgedAvailableAttr] {
28-
guard let args = node.arguments else {
29-
self.diagnose(.expectedArgumentsInAttribute(node))
30-
return []
31-
}
32-
guard let args = args.as(AvailabilityArgumentListSyntax.self) else {
33-
// TODO: Diagnose.
34-
return []
35-
}
22+
/// Implementation detail for `generateAvailableAttr(attribute:)` and `generateSpecializeAttr(attribute:)`.
23+
func generateAvailableAttr(
24+
atLoc: BridgedSourceLoc,
25+
range: BridgedSourceRange,
26+
args: AvailabilityArgumentListSyntax
27+
) -> [BridgedAvailableAttr] {
3628

3729
// Check if this is "shorthand" syntax.
3830
if let firstArg = args.first?.argument {
@@ -48,17 +40,20 @@ extension ASTGenVisitor {
4840
isShorthand = false
4941
}
5042
if isShorthand {
51-
return self.generateAvailableAttrShorthand(attribute: node)
43+
return self.generateAvailableAttrShorthand(atLoc: atLoc, range: range, args: args)
5244
}
5345
}
5446

5547
// E.g.
5648
// @available(macOS, introduced: 10.12, deprecated: 11.2)
5749
// @available(*, unavailable, message: "out of service")
58-
if let generated = self.generateAvailableAttrExtended(attribute: node) {
59-
return [generated]
50+
let attr = self.generateAvailableAttrExtended(atLoc: atLoc, range: range, args: args)
51+
52+
if let attr {
53+
return [attr]
54+
} else {
55+
return []
6056
}
61-
return []
6257
}
6358

6459
func generate(versionTuple node: VersionTupleSyntax?) -> VersionTuple? {
@@ -68,13 +63,12 @@ extension ASTGenVisitor {
6863
return tuple
6964
}
7065

71-
func generateAvailableAttrShorthand(attribute node: AttributeSyntax) -> [BridgedAvailableAttr] {
72-
let atLoc = self.generateSourceLoc(node.atSign)
73-
let range = self.generateAttrSourceRange(node)
74-
let specs = self.generateAvailabilitySpecList(
75-
args: node.arguments!.cast(AvailabilityArgumentListSyntax.self),
76-
context: .availableAttr
77-
)
66+
func generateAvailableAttrShorthand(
67+
atLoc: BridgedSourceLoc,
68+
range: BridgedSourceRange,
69+
args: AvailabilityArgumentListSyntax
70+
) -> [BridgedAvailableAttr] {
71+
let specs = self.generateAvailabilitySpecList(args: args, context: .availableAttr)
7872

7973
var result: [BridgedAvailableAttr] = []
8074
for spec in specs {
@@ -103,8 +97,12 @@ extension ASTGenVisitor {
10397
return result
10498
}
10599

106-
func generateAvailableAttrExtended(attribute node: AttributeSyntax) -> BridgedAvailableAttr? {
107-
var args = node.arguments!.cast(AvailabilityArgumentListSyntax.self)[...]
100+
func generateAvailableAttrExtended(
101+
atLoc: BridgedSourceLoc,
102+
range: BridgedSourceRange,
103+
args: AvailabilityArgumentListSyntax
104+
) -> BridgedAvailableAttr? {
105+
var args = args[...]
108106

109107
// The platfrom.
110108
guard let platformToken = args.popFirst()?.argument.as(TokenSyntax.self) else {
@@ -234,8 +232,8 @@ extension ASTGenVisitor {
234232

235233
return BridgedAvailableAttr.createParsed(
236234
self.ctx,
237-
atLoc: self.generateSourceLoc(node.atSign),
238-
range: self.generateAttrSourceRange(node),
235+
atLoc: atLoc,
236+
range: range,
239237
domainString: platformStr.bridged,
240238
domainLoc: platformLoc,
241239
kind: attrKind,
@@ -274,6 +272,8 @@ extension ASTGenVisitor {
274272

275273
enum AvailabilitySpecListContext {
276274
case availableAttr
275+
case poundAvailable
276+
case poundUnavailable
277277
case macro
278278
}
279279

@@ -362,6 +362,76 @@ extension ASTGenVisitor {
362362

363363
return result
364364
}
365+
366+
typealias GeneratedPlatformVersion = (platform: BridgedPlatformKind, version: BridgedVersionTuple)
367+
368+
func generate(platformVersionList node: PlatformVersionItemListSyntax) -> [GeneratedPlatformVersion] {
369+
var result: [GeneratedPlatformVersion] = []
370+
371+
for element in node {
372+
let platformVersionNode = element.platformVersion
373+
let platformName = platformVersionNode.platform.rawText
374+
let version = self.generate(versionTuple: platformVersionNode.version)?.bridged ?? BridgedVersionTuple()
375+
376+
// If the name is a platform name, use it.
377+
let platform = BridgedPlatformKind(from: platformName.bridged)
378+
if platform != .none {
379+
result.append((platform: platform, version: version))
380+
continue
381+
}
382+
383+
// If there's matching macro, use it.
384+
let expanded = ctx.availabilityMacroMap.get(
385+
name: platformName.bridged,
386+
version: version
387+
)
388+
if !expanded.isEmpty {
389+
expanded.withElements(ofType: UnsafeRawPointer.self) { buffer in
390+
for ptr in buffer {
391+
let spec = BridgedAvailabilitySpec(raw: UnsafeMutableRawPointer(mutating: ptr))
392+
let platform = spec.platform
393+
guard platform != .none else {
394+
continue
395+
}
396+
result.append((platform: platform, version: spec.version))
397+
}
398+
}
399+
continue
400+
}
401+
402+
// Error.
403+
// TODO: Diagnostics
404+
fatalError("invalid platform name")
405+
}
406+
return result
407+
}
408+
409+
func generate(availabilityCondition node: AvailabilityConditionSyntax) -> BridgedPoundAvailableInfo {
410+
let specListContext: AvailabilitySpecListContext
411+
switch node.availabilityKeyword.rawText {
412+
case "#available":
413+
specListContext = .poundAvailable
414+
case "#unavailable":
415+
specListContext = .poundUnavailable
416+
default:
417+
// TODO: Diagnostics?
418+
fatalError("invalid availabilityKeyword")
419+
}
420+
let specs = self.generateAvailabilitySpecList(
421+
args: node.availabilityArguments,
422+
context: specListContext
423+
)
424+
425+
return .createParsed(
426+
self.ctx,
427+
poundLoc: self.generateSourceLoc(node.availabilityKeyword),
428+
lParenLoc: self.generateSourceLoc(node.leftParen),
429+
specs: specs.lazy.bridgedArray(in: self),
430+
rParenLoc: self.generateSourceLoc(node.rightParen),
431+
isUnavailable: specListContext == .poundUnavailable
432+
)
433+
}
434+
365435
}
366436

367437
/// Parse an argument for '-define-availability' compiler option.

0 commit comments

Comments
 (0)