Skip to content

Commit 965ee8f

Browse files
authored
Merge pull request #78284 from tshortli/semantic-available-attr
AST: Introduce `SemanticAvailableAttr`
2 parents cbf8d67 + 111661e commit 965ee8f

22 files changed

+401
-261
lines changed

include/swift/AST/Attr.h

Lines changed: 90 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/ASTAllocated.h"
2121
#include "swift/AST/AttrKind.h"
2222
#include "swift/AST/AutoDiff.h"
23+
#include "swift/AST/AvailabilityDomain.h"
2324
#include "swift/AST/ConcreteDeclRef.h"
2425
#include "swift/AST/DeclNameLoc.h"
2526
#include "swift/AST/Identifier.h"
@@ -782,12 +783,6 @@ class AvailableAttr : public DeclAttribute {
782783
/// Indicates where the Obsoleted version was specified.
783784
const SourceRange ObsoletedRange;
784785

785-
/// Whether this is a language-version-specific entity.
786-
bool isLanguageVersionSpecific() const;
787-
788-
/// Whether this is a PackageDescription version specific entity.
789-
bool isPackageDescriptionVersionSpecific() const;
790-
791786
/// Whether this is an unconditionally unavailable entity.
792787
bool isUnconditionallyUnavailable() const;
793788

@@ -831,17 +826,6 @@ class AvailableAttr : public DeclAttribute {
831826
/// Returns true if this attribute is active given the current platform.
832827
bool isActivePlatform(const ASTContext &ctx) const;
833828

834-
/// Returns the active version from the AST context corresponding to
835-
/// the available kind. For example, this will return the effective language
836-
/// version for swift version-specific availability kind, PackageDescription
837-
/// version for PackageDescription version-specific availability.
838-
llvm::VersionTuple getActiveVersion(const ASTContext &ctx) const;
839-
840-
/// Compare this attribute's version information against the platform or
841-
/// language version (assuming the this attribute pertains to the active
842-
/// platform).
843-
AvailableVersionComparison getVersionAvailability(const ASTContext &ctx) const;
844-
845829
/// Create an AvailableAttr that indicates specific availability
846830
/// for all platforms.
847831
static AvailableAttr *
@@ -3190,6 +3174,95 @@ class ParsedDeclAttributes {
31903174
}
31913175
};
31923176

3177+
/// A wrapper for `AvailableAttr` that is enriched with additional semantic
3178+
/// informaton, like its corresponding `AvailabilityDomain`.
3179+
class SemanticAvailableAttr final {
3180+
const AvailableAttr *attr;
3181+
const AvailabilityDomain domain;
3182+
3183+
public:
3184+
SemanticAvailableAttr(const AvailableAttr *attr, AvailabilityDomain domain)
3185+
: attr(attr), domain(domain) {
3186+
assert(attr);
3187+
}
3188+
3189+
const AvailableAttr *getParsedAttr() const { return attr; }
3190+
const AvailabilityDomain getDomain() const { return domain; }
3191+
3192+
/// Returns the platform kind that the attribute applies to, or
3193+
/// `PlatformKind::none` if the attribute is not platform specific.
3194+
bool isPlatformSpecific() const { return domain.isPlatform(); }
3195+
3196+
/// Returns the platform kind that the attribute applies to, or
3197+
/// `PlatformKind::none` if the attribute is not platform specific.
3198+
PlatformKind getPlatformKind() const { return domain.getPlatformKind(); }
3199+
3200+
/// Whether this attribute has an introduced, deprecated, or obsoleted
3201+
/// version.
3202+
bool isVersionSpecific() const {
3203+
return attr->Introduced || attr->Deprecated || attr->Obsoleted;
3204+
}
3205+
3206+
/// Whether this is a language mode specific attribute.
3207+
bool isSwiftLanguageModeSpecific() const {
3208+
return domain.isSwiftLanguage() && isVersionSpecific();
3209+
}
3210+
3211+
/// Whether this is a PackageDescription version specific attribute.
3212+
bool isPackageDescriptionVersionSpecific() const {
3213+
return domain.isPackageDescription() && isVersionSpecific();
3214+
}
3215+
3216+
/// Returns the active version from the AST context corresponding to
3217+
/// the available kind. For example, this will return the effective language
3218+
/// version for swift version-specific availability kind, PackageDescription
3219+
/// version for PackageDescription version-specific availability.
3220+
llvm::VersionTuple getActiveVersion(const ASTContext &ctx) const;
3221+
3222+
/// Compare this attribute's version information against the platform or
3223+
/// language version (assuming the this attribute pertains to the active
3224+
/// platform).
3225+
AvailableVersionComparison
3226+
getVersionAvailability(const ASTContext &ctx) const;
3227+
3228+
/// Returns true if this attribute is considered active in the current
3229+
/// compilation context.
3230+
bool isActive(ASTContext &ctx) const;
3231+
};
3232+
3233+
/// An iterable range of `SemanticAvailableAttr`s.
3234+
class SemanticAvailableAttributes {
3235+
public:
3236+
class Filter final {
3237+
const Decl *decl;
3238+
bool includeInactive;
3239+
3240+
public:
3241+
Filter(const Decl *decl, bool includeInactive)
3242+
: decl(decl), includeInactive(includeInactive) {}
3243+
3244+
std::optional<SemanticAvailableAttr>
3245+
operator()(const DeclAttribute *attr) const;
3246+
};
3247+
3248+
using Range =
3249+
OptionalTransformRange<iterator_range<DeclAttributes::const_iterator>,
3250+
Filter>;
3251+
3252+
private:
3253+
Range attrRange;
3254+
3255+
public:
3256+
SemanticAvailableAttributes(const DeclAttributes &attrs, const Decl *decl,
3257+
bool includeInactive = false)
3258+
: attrRange(make_range(attrs.begin(), attrs.end()),
3259+
Filter(decl, includeInactive)) {}
3260+
3261+
Range::iterator begin() const { return attrRange.begin(); }
3262+
Range::iterator end() const { return attrRange.end(); }
3263+
bool empty() const { return attrRange.empty(); }
3264+
};
3265+
31933266
class alignas(1 << AttrAlignInBits) TypeAttribute
31943267
: public ASTAllocated<TypeAttribute> {
31953268
protected:

include/swift/AST/Availability.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,8 @@ class AvailabilityInference {
380380
annotatedAvailableRange(const Decl *D);
381381

382382
static AvailabilityRange
383-
annotatedAvailableRangeForAttr(const SpecializeAttr *attr, ASTContext &ctx);
383+
annotatedAvailableRangeForAttr(const Decl *D, const SpecializeAttr *attr,
384+
ASTContext &ctx);
384385

385386
/// For the attribute's introduction version, update the platform and version
386387
/// values to the re-mapped platform's, if using a fallback platform.

include/swift/AST/AvailabilityDomain.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/Basic/LLVM.h"
2323

2424
namespace swift {
25+
class ASTContext;
2526

2627
/// Represents a dimension of availability (e.g. macOS platform or Swift
2728
/// language mode).
@@ -83,10 +84,11 @@ class AvailabilityDomain final {
8384
bool isPackageDescription() const { return kind == Kind::PackageDescription; }
8485

8586
/// Returns the platform kind for this domain if applicable.
86-
PlatformKind getPlatformKind() const {
87-
assert(kind == Kind::Platform);
88-
return platform;
89-
}
87+
PlatformKind getPlatformKind() const { return platform; }
88+
89+
/// Returns true if this domain is considered active in the current
90+
/// compilation context.
91+
bool isActive(ASTContext &ctx) const;
9092

9193
/// Returns the string to use in diagnostics to identify the domain. May
9294
/// return an empty string.

include/swift/AST/Decl.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,9 +1395,18 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl>, public Swi
13951395
/// and its DeclContext does not.
13961396
bool isOutermostPrivateOrFilePrivateScope() const;
13971397

1398-
/// Returns the availability domain associated with the given `AvailableAttr`
1399-
/// that is attached to this decl.
1400-
AvailabilityDomain getDomainForAvailableAttr(const AvailableAttr *attr) const;
1398+
/// Returns an iterable list of the valid `AvailableAttr` and
1399+
/// `AvailabilityDomain` pairs. Unless \p includeInactive is true, attributes
1400+
/// that are considered inactive for the compilation context are filtered out.
1401+
SemanticAvailableAttributes
1402+
getSemanticAvailableAttrs(bool includeInactive = true) const;
1403+
1404+
/// Returns the SemanticAvailableAttr associated with the given
1405+
/// `AvailableAttr` that is attached to this decl. Returns `std::nullopt` if a
1406+
/// valid semantic version of the attribute cannot be constructed (e.g. the
1407+
/// domain cannot be resolved).
1408+
std::optional<SemanticAvailableAttr>
1409+
getSemanticAvailableAttr(const AvailableAttr *attr) const;
14011410

14021411
/// Returns the active platform-specific `@available` attribute for this decl.
14031412
/// There may be multiple `@available` attributes that are relevant to the

include/swift/AST/PrintOptions.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,6 @@ struct PrintOptions {
341341
/// Whether to print the internal layout name instead of AnyObject, etc.
342342
bool PrintInternalLayoutName = false;
343343

344-
/// Suppress emitting @available(*, noasync)
345-
bool SuppressNoAsyncAvailabilityAttr = false;
346-
347344
/// Suppress emitting isolated or async deinit, and emit open containing class
348345
/// as public
349346
bool SuppressIsolatedDeinit = false;

lib/APIDigester/ModuleAnalyzerNodes.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,14 +1339,16 @@ std::optional<uint8_t> SDKContext::getFixedBinaryOrder(ValueDecl *VD) const {
13391339
// check for if it has @available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
13401340
static bool isABIPlaceHolder(Decl *D) {
13411341
llvm::SmallSet<PlatformKind, 4> Platforms;
1342-
for (auto *ATT: D->getAttrs()) {
1343-
if (auto *AVA = dyn_cast<AvailableAttr>(ATT)) {
1344-
if (AVA->getPlatform() != PlatformKind::none && AVA->Introduced &&
1345-
AVA->Introduced->getMajor() == 9999) {
1346-
Platforms.insert(AVA->getPlatform());
1347-
}
1342+
for (auto semanticAttr : D->getSemanticAvailableAttrs()) {
1343+
auto attr = semanticAttr.getParsedAttr();
1344+
auto domain = semanticAttr.getDomain();
1345+
if (domain.isPlatform() && attr->Introduced &&
1346+
attr->Introduced->getMajor() == 9999) {
1347+
Platforms.insert(attr->getPlatform());
13481348
}
13491349
}
1350+
1351+
// FIXME: This probably isn't correct anymore, now that visionOS exists
13501352
return Platforms.size() == 4;
13511353
}
13521354

@@ -1361,11 +1363,11 @@ static bool isABIPlaceholderRecursive(Decl *D) {
13611363
StringRef SDKContext::getPlatformIntroVersion(Decl *D, PlatformKind Kind) {
13621364
if (!D)
13631365
return StringRef();
1364-
for (auto *ATT: D->getAttrs()) {
1365-
if (auto *AVA = dyn_cast<AvailableAttr>(ATT)) {
1366-
if (AVA->getPlatform() == Kind && AVA->Introduced) {
1367-
return buffer(AVA->Introduced->getAsString());
1368-
}
1366+
for (auto semanticAttr : D->getSemanticAvailableAttrs()) {
1367+
auto attr = semanticAttr.getParsedAttr();
1368+
auto domain = semanticAttr.getDomain();
1369+
if (domain.getPlatformKind() == Kind && attr->Introduced) {
1370+
return buffer(attr->Introduced->getAsString());
13691371
}
13701372
}
13711373
return StringRef();
@@ -1374,11 +1376,12 @@ StringRef SDKContext::getPlatformIntroVersion(Decl *D, PlatformKind Kind) {
13741376
StringRef SDKContext::getLanguageIntroVersion(Decl *D) {
13751377
if (!D)
13761378
return StringRef();
1377-
for (auto *ATT: D->getAttrs()) {
1378-
if (auto *AVA = dyn_cast<AvailableAttr>(ATT)) {
1379-
if (AVA->isLanguageVersionSpecific() && AVA->Introduced) {
1380-
return buffer(AVA->Introduced->getAsString());
1381-
}
1379+
for (auto semanticAttr : D->getSemanticAvailableAttrs()) {
1380+
auto attr = semanticAttr.getParsedAttr();
1381+
auto domain = semanticAttr.getDomain();
1382+
1383+
if (domain.isSwiftLanguage() && attr->Introduced) {
1384+
return buffer(attr->Introduced->getAsString());
13821385
}
13831386
}
13841387
return getLanguageIntroVersion(D->getDeclContext()->getAsDecl());

0 commit comments

Comments
 (0)