Skip to content

[ASTGen] Generate miscellaneous availability related nodes #79203

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ enum class MacroRole : uint32_t;
class MacroIntroducedDeclName;
enum class MacroIntroducedDeclNameKind;
enum class ParamSpecifier : uint8_t;
enum class PlatformKind : uint8_t;
class ProtocolConformanceRef;
class RegexLiteralPatternFeature;
class RegexLiteralPatternFeatureKind;
Expand Down Expand Up @@ -589,6 +590,8 @@ enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedPlatformKind : size_t {
SWIFT_NAME("BridgedPlatformKind.init(from:)")
BridgedPlatformKind BridgedPlatformKind_fromString(BridgedStringRef cStr);

swift::PlatformKind unbridge(BridgedPlatformKind cPlatform);

SWIFT_NAME("BridgedAvailabilityMacroMap.has(self:name:)")
bool BridgedAvailabilityMacroMap_hasName(BridgedAvailabilityMacroMap map,
BridgedStringRef name);
Expand Down Expand Up @@ -627,6 +630,10 @@ SWIFT_NAME("getter:BridgedAvailabilitySpec.domain(self:)")
BridgedAvailabilityDomain
BridgedAvailabilitySpec_getDomain(BridgedAvailabilitySpec spec);

SWIFT_NAME("getter:BridgedAvailabilitySpec.platform(self:)")
BridgedPlatformKind
BridgedAvailabilitySpec_getPlatform(BridgedAvailabilitySpec spec);

SWIFT_NAME("getter:BridgedAvailabilitySpec.version(self:)")
BridgedVersionTuple
BridgedAvailabilitySpec_getVersion(BridgedAvailabilitySpec spec);
Expand Down Expand Up @@ -802,6 +809,13 @@ BridgedAllowFeatureSuppressionAttr_createParsed(
bool inverted,
BridgedArrayRef cFeatures);

SWIFT_NAME(
"BridgedBackDeployedAttr.createParsed(_:atLoc:range:platform:version:)")
BridgedBackDeployedAttr BridgedBackDeployedAttr_createParsed(
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
BridgedSourceRange cRange, BridgedPlatformKind cPlatform,
BridgedVersionTuple cVersion);

SWIFT_NAME("BridgedCDeclAttr.createParsed(_:atLoc:range:name:)")
BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
BridgedSourceLoc cAtLoc,
Expand Down Expand Up @@ -949,6 +963,13 @@ BridgedMacroRoleAttr BridgedMacroRoleAttr_createParsed(
BridgedSourceLoc cLParenLoc, BridgedMacroRole cRole, BridgedArrayRef cNames,
BridgedArrayRef cConformances, BridgedSourceLoc cRParenLoc);

SWIFT_NAME("BridgedOriginallyDefinedInAttr.createParsed(_:atLoc:range:"
"moduleName:platform:version:)")
BridgedOriginallyDefinedInAttr BridgedOriginallyDefinedInAttr_createParsed(
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
BridgedSourceRange cRange, BridgedStringRef cModuleName,
BridgedPlatformKind cPlatform, BridgedVersionTuple cVersion);

SWIFT_NAME("BridgedStorageRestrictionsAttr.createParsed(_:atLoc:range:"
"initializes:accesses:)")
BridgedStorageRestrictionsAttr BridgedStorageRestrictionsAttr_createParsed(
Expand Down Expand Up @@ -1949,6 +1970,17 @@ BridgedStmtConditionElement BridgedStmtConditionElement_createPatternBinding(
BridgedASTContext cContext, BridgedSourceLoc cIntroducerLoc,
BridgedPattern cPattern, BridgedExpr cInitializer);

SWIFT_NAME("BridgedStmtConditionElement.createPoundAvailable(info:)")
BridgedStmtConditionElement BridgedStmtConditionElement_createPoundAvailable(
BridgedPoundAvailableInfo info);

SWIFT_NAME("BridgedPoundAvailableInfo.createParsed(_:poundLoc:lParenLoc:specs:"
"rParenLoc:isUnavailable:)")
BridgedPoundAvailableInfo BridgedPoundAvailableInfo_createParsed(
BridgedASTContext cContext, BridgedSourceLoc cPoundLoc,
BridgedSourceLoc cLParenLoc, BridgedArrayRef cSpecs,
BridgedSourceLoc cRParenLoc, bool isUnavailability);

struct BridgedCaseLabelItemInfo {
SWIFT_NAME("isDefault")
bool IsDefault;
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/ASTBridgingWrappers.def
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ AST_BRIDGING_WRAPPER_NULLABLE(PlatformVersionConstraintAvailabilitySpec)
AST_BRIDGING_WRAPPER_NULLABLE(PlatformAgnosticVersionConstraintAvailabilitySpec)
AST_BRIDGING_WRAPPER_NULLABLE(OtherPlatformAvailabilitySpec)
AST_BRIDGING_WRAPPER_CONST_NONNULL(AvailabilityMacroMap)
AST_BRIDGING_WRAPPER_NONNULL(PoundAvailableInfo)

// Non-AST types to generate wrappers for.
AST_BRIDGING_WRAPPER_NULLABLE(DiagnosticEngine)
Expand Down
2 changes: 2 additions & 0 deletions include/swift/AST/AvailabilitySpec.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {

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

std::optional<PlatformKind> getPlatform() const;

llvm::VersionTuple getVersion() const;

SourceRange getVersionSrcRange() const;
Expand Down
14 changes: 14 additions & 0 deletions lib/AST/AvailabilitySpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ std::optional<AvailabilityDomain> AvailabilitySpec::getDomain() const {
llvm_unreachable("bad AvailabilitySpecKind");
}

std::optional<PlatformKind> AvailabilitySpec::getPlatform() const {
switch (getKind()) {
case AvailabilitySpecKind::PlatformVersionConstraint: {
auto spec = cast<PlatformVersionConstraintAvailabilitySpec>(this);
return spec->getPlatform();
}
case AvailabilitySpecKind::LanguageVersionConstraint:
case AvailabilitySpecKind::PackageDescriptionVersionConstraint:
case AvailabilitySpecKind::OtherPlatform:
return std::nullopt;
}
llvm_unreachable("bad AvailabilitySpecKind");
}

llvm::VersionTuple AvailabilitySpec::getVersion() const {
switch (getKind()) {
case AvailabilitySpecKind::PlatformVersionConstraint: {
Expand Down
22 changes: 21 additions & 1 deletion lib/AST/Bridging/AvailabilityBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ BridgedPlatformKind BridgedPlatformKind_fromString(BridgedStringRef cStr) {
}
}

static PlatformKind unbridge(BridgedPlatformKind platform) {
PlatformKind unbridge(BridgedPlatformKind platform) {
switch (platform) {
case BridgedPlatformKind_None:
return PlatformKind::none;
Expand All @@ -70,6 +70,18 @@ static PlatformKind unbridge(BridgedPlatformKind platform) {
llvm_unreachable("unhandled enum value");
}

static BridgedPlatformKind bridge(PlatformKind platform) {
switch (platform) {
case PlatformKind::none:
return BridgedPlatformKind_None;
#define AVAILABILITY_PLATFORM(X, PrettyName) \
case PlatformKind::X: \
return BridgedPlatformKind_##X;
#include "swift/AST/PlatformKinds.def"
}
llvm_unreachable("unhandled enum value");
}

//===----------------------------------------------------------------------===//
// MARK: AvailabilitySpec
//===----------------------------------------------------------------------===//
Expand All @@ -87,6 +99,14 @@ BridgedAvailabilitySpec_getDomain(BridgedAvailabilitySpec spec) {
return BridgedAvailabilityDomain();
}

BridgedPlatformKind
BridgedAvailabilitySpec_getPlatform(BridgedAvailabilitySpec spec) {
auto platform = spec.unbridged()->getPlatform();
if (platform)
return bridge(*platform);
return BridgedPlatformKind_None;
}

BridgedVersionTuple
BridgedAvailabilitySpec_getVersion(BridgedAvailabilitySpec spec) {
return spec.unbridged()->getVersion();
Expand Down
19 changes: 19 additions & 0 deletions lib/AST/Bridging/DeclAttributeBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@ BridgedAllowFeatureSuppressionAttr_createParsed(BridgedASTContext cContext,
/*implicit*/ false, inverted, features);
}

BridgedBackDeployedAttr BridgedBackDeployedAttr_createParsed(
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
BridgedSourceRange cRange, BridgedPlatformKind cPlatform,
BridgedVersionTuple cVersion) {
return new (cContext.unbridged()) BackDeployedAttr(
cAtLoc.unbridged(), cRange.unbridged(), unbridge(cPlatform),
cVersion.unbridged(), /*Implicit=*/false);
}

BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
BridgedSourceLoc cAtLoc,
BridgedSourceRange cRange,
Expand Down Expand Up @@ -388,6 +397,16 @@ BridgedMacroRoleAttr BridgedMacroRoleAttr_createParsed(
conformances, cRParenLoc.unbridged(), /*implicit=*/false);
}

BridgedOriginallyDefinedInAttr BridgedOriginallyDefinedInAttr_createParsed(
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
BridgedSourceRange cRange, BridgedStringRef cModuleName,
BridgedPlatformKind cPlatform, BridgedVersionTuple cVersion) {
return new (cContext.unbridged()) OriginallyDefinedInAttr(
cAtLoc.unbridged(), cRange.unbridged(), cModuleName.unbridged(),
unbridge(cPlatform), cVersion.unbridged(),
/*Implicit=*/false);
}

BridgedStorageRestrictionsAttr BridgedStorageRestrictionsAttr_createParsed(
BridgedASTContext cContext, BridgedSourceLoc cAtLoc,
BridgedSourceRange cRange, BridgedArrayRef cInitializes,
Expand Down
17 changes: 17 additions & 0 deletions lib/AST/Bridging/StmtBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,23 @@ BridgedStmtConditionElement BridgedStmtConditionElement_createPatternBinding(
cInitializer.unbridged()));
}

BridgedStmtConditionElement BridgedStmtConditionElement_createPoundAvailable(
BridgedPoundAvailableInfo info) {
return StmtConditionElement(info.unbridged());
}

BridgedPoundAvailableInfo BridgedPoundAvailableInfo_createParsed(
BridgedASTContext cContext, BridgedSourceLoc cPoundLoc,
BridgedSourceLoc cLParenLoc, BridgedArrayRef cSpecs,
BridgedSourceLoc cRParenLoc, bool isUnavailability) {
SmallVector<AvailabilitySpec *, 4> specs;
for (auto cSpec : cSpecs.unbridged<BridgedAvailabilitySpec>())
specs.push_back(cSpec.unbridged());
return PoundAvailableInfo::create(cContext.unbridged(), cPoundLoc.unbridged(),
cLParenLoc.unbridged(), specs,
cRParenLoc.unbridged(), isUnavailability);
}

BridgedBraceStmt BridgedBraceStmt_createParsed(BridgedASTContext cContext,
BridgedSourceLoc cLBLoc,
BridgedArrayRef elements,
Expand Down
128 changes: 99 additions & 29 deletions lib/ASTGen/Sources/ASTGen/Availability.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,12 @@ import SwiftIfConfig
@_spi(RawSyntax) @_spi(Compiler) import SwiftSyntax

extension ASTGenVisitor {
/// E.g.:
/// ```
/// @available(macOS 10.12, iOS 13, *)
/// @available(macOS, introduced: 10.12)
/// ```
func generateAvailableAttr(attribute node: AttributeSyntax) -> [BridgedAvailableAttr] {
guard let args = node.arguments else {
self.diagnose(.expectedArgumentsInAttribute(node))
return []
}
guard let args = args.as(AvailabilityArgumentListSyntax.self) else {
// TODO: Diagnose.
return []
}
/// Implementation detail for `generateAvailableAttr(attribute:)` and `generateSpecializeAttr(attribute:)`.
func generateAvailableAttr(
atLoc: BridgedSourceLoc,
range: BridgedSourceRange,
args: AvailabilityArgumentListSyntax
) -> [BridgedAvailableAttr] {

// Check if this is "shorthand" syntax.
if let firstArg = args.first?.argument {
Expand All @@ -48,17 +40,20 @@ extension ASTGenVisitor {
isShorthand = false
}
if isShorthand {
return self.generateAvailableAttrShorthand(attribute: node)
return self.generateAvailableAttrShorthand(atLoc: atLoc, range: range, args: args)
}
}

// E.g.
// @available(macOS, introduced: 10.12, deprecated: 11.2)
// @available(*, unavailable, message: "out of service")
if let generated = self.generateAvailableAttrExtended(attribute: node) {
return [generated]
let attr = self.generateAvailableAttrExtended(atLoc: atLoc, range: range, args: args)

if let attr {
return [attr]
} else {
return []
}
return []
}

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

func generateAvailableAttrShorthand(attribute node: AttributeSyntax) -> [BridgedAvailableAttr] {
let atLoc = self.generateSourceLoc(node.atSign)
let range = self.generateAttrSourceRange(node)
let specs = self.generateAvailabilitySpecList(
args: node.arguments!.cast(AvailabilityArgumentListSyntax.self),
context: .availableAttr
)
func generateAvailableAttrShorthand(
atLoc: BridgedSourceLoc,
range: BridgedSourceRange,
args: AvailabilityArgumentListSyntax
) -> [BridgedAvailableAttr] {
let specs = self.generateAvailabilitySpecList(args: args, context: .availableAttr)

var result: [BridgedAvailableAttr] = []
for spec in specs {
Expand Down Expand Up @@ -103,8 +97,12 @@ extension ASTGenVisitor {
return result
}

func generateAvailableAttrExtended(attribute node: AttributeSyntax) -> BridgedAvailableAttr? {
var args = node.arguments!.cast(AvailabilityArgumentListSyntax.self)[...]
func generateAvailableAttrExtended(
atLoc: BridgedSourceLoc,
range: BridgedSourceRange,
args: AvailabilityArgumentListSyntax
) -> BridgedAvailableAttr? {
var args = args[...]

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

return BridgedAvailableAttr.createParsed(
self.ctx,
atLoc: self.generateSourceLoc(node.atSign),
range: self.generateAttrSourceRange(node),
atLoc: atLoc,
range: range,
domainString: platformStr.bridged,
domainLoc: platformLoc,
kind: attrKind,
Expand Down Expand Up @@ -274,6 +272,8 @@ extension ASTGenVisitor {

enum AvailabilitySpecListContext {
case availableAttr
case poundAvailable
case poundUnavailable
case macro
}

Expand Down Expand Up @@ -362,6 +362,76 @@ extension ASTGenVisitor {

return result
}

typealias GeneratedPlatformVersion = (platform: BridgedPlatformKind, version: BridgedVersionTuple)

func generate(platformVersionList node: PlatformVersionItemListSyntax) -> [GeneratedPlatformVersion] {
var result: [GeneratedPlatformVersion] = []

for element in node {
let platformVersionNode = element.platformVersion
let platformName = platformVersionNode.platform.rawText
let version = self.generate(versionTuple: platformVersionNode.version)?.bridged ?? BridgedVersionTuple()

// If the name is a platform name, use it.
let platform = BridgedPlatformKind(from: platformName.bridged)
if platform != .none {
result.append((platform: platform, version: version))
continue
}

// If there's matching macro, use it.
let expanded = ctx.availabilityMacroMap.get(
name: platformName.bridged,
version: version
)
if !expanded.isEmpty {
expanded.withElements(ofType: UnsafeRawPointer.self) { buffer in
for ptr in buffer {
let spec = BridgedAvailabilitySpec(raw: UnsafeMutableRawPointer(mutating: ptr))
let platform = spec.platform
guard platform != .none else {
continue
}
result.append((platform: platform, version: spec.version))
}
}
continue
}

// Error.
// TODO: Diagnostics
fatalError("invalid platform name")
}
return result
}

func generate(availabilityCondition node: AvailabilityConditionSyntax) -> BridgedPoundAvailableInfo {
let specListContext: AvailabilitySpecListContext
switch node.availabilityKeyword.rawText {
case "#available":
specListContext = .poundAvailable
case "#unavailable":
specListContext = .poundUnavailable
default:
// TODO: Diagnostics?
fatalError("invalid availabilityKeyword")
}
let specs = self.generateAvailabilitySpecList(
args: node.availabilityArguments,
context: specListContext
)

return .createParsed(
self.ctx,
poundLoc: self.generateSourceLoc(node.availabilityKeyword),
lParenLoc: self.generateSourceLoc(node.leftParen),
specs: specs.lazy.bridgedArray(in: self),
rParenLoc: self.generateSourceLoc(node.rightParen),
isUnavailable: specListContext == .poundUnavailable
)
}

}

/// Parse an argument for '-define-availability' compiler option.
Expand Down
Loading