Skip to content

Commit 735000f

Browse files
committed
AST: Flatten the representation of AvailabilitySpec.
Push all of the members up into the AvailabilitySpec superclass in preparation for removing the subclasses. NFC.
1 parent 3142803 commit 735000f

File tree

2 files changed

+94
-133
lines changed

2 files changed

+94
-133
lines changed

include/swift/AST/AvailabilitySpec.h

+80-54
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define SWIFT_AST_AVAILABILITY_SPEC_H
1919

2020
#include "swift/AST/ASTAllocated.h"
21+
#include "swift/AST/AvailabilityDomain.h"
2122
#include "swift/AST/Identifier.h"
2223
#include "swift/AST/PlatformKind.h"
2324
#include "swift/Basic/SourceLoc.h"
@@ -27,9 +28,6 @@
2728

2829
namespace swift {
2930
class ASTContext;
30-
class AvailabilityDomain;
31-
32-
enum class VersionComparison { GreaterThanEqual };
3331

3432
enum class AvailabilitySpecKind {
3533
/// A platform-version constraint of the form "PlatformName X.Y.Z"
@@ -49,70 +47,94 @@ enum class AvailabilitySpecKind {
4947
/// The root class for specifications of API availability in availability
5048
/// queries.
5149
class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
50+
protected:
5251
AvailabilitySpecKind Kind;
5352

53+
std::optional<AvailabilityDomain> Domain;
54+
55+
/// The range of the entire spec, including the version if there is one.
56+
SourceRange SrcRange;
57+
58+
/// The version (may be empty if there was no version specified).
59+
llvm::VersionTuple Version;
60+
61+
/// If there is a version specified, this is its start location within the
62+
/// overall source range.
63+
SourceLoc VersionStartLoc;
64+
65+
// Location of the availability macro expanded to create this spec.
66+
SourceLoc MacroLoc;
67+
5468
public:
55-
AvailabilitySpec(AvailabilitySpecKind Kind) : Kind(Kind) {}
69+
AvailabilitySpec(AvailabilitySpecKind Kind,
70+
std::optional<AvailabilityDomain> Domain,
71+
SourceRange SrcRange, llvm::VersionTuple Version,
72+
SourceLoc VersionStartLoc)
73+
: Kind(Kind), Domain(Domain), SrcRange(SrcRange), Version(Version),
74+
VersionStartLoc(VersionStartLoc) {}
5675

5776
AvailabilitySpecKind getKind() const { return Kind; }
5877

59-
SourceRange getSourceRange() const;
78+
SourceRange getSourceRange() const { return SrcRange; }
6079

61-
std::optional<AvailabilityDomain> getDomain() const;
80+
std::optional<AvailabilityDomain> getDomain() const { return Domain; }
6281

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

84+
// The platform version to compare against.
6585
llvm::VersionTuple getVersion() const;
6686

67-
SourceRange getVersionSrcRange() const;
87+
SourceRange getVersionSrcRange() const {
88+
if (!VersionStartLoc)
89+
return SourceRange();
90+
return SourceRange(VersionStartLoc, SrcRange.End);
91+
}
92+
93+
// Location of the macro expanded to create this spec.
94+
SourceLoc getMacroLoc() const { return MacroLoc; }
95+
void setMacroLoc(SourceLoc loc) { MacroLoc = loc; }
6896
};
6997

7098
/// An availability specification that guards execution based on the
7199
/// run-time platform and version, e.g., OS X >= 10.10.
72100
class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec {
73-
PlatformKind Platform;
74-
SourceLoc PlatformLoc;
75-
76-
llvm::VersionTuple Version;
77-
78-
SourceRange VersionSrcRange;
79-
80-
// Location of the macro expanded to create this spec.
81-
SourceLoc MacroLoc;
101+
static std::optional<AvailabilityDomain>
102+
getDomainForPlatform(PlatformKind Platform) {
103+
if (Platform != PlatformKind::none)
104+
return AvailabilityDomain::forPlatform(Platform);
105+
return std::nullopt;
106+
}
82107

83108
public:
84109
PlatformVersionConstraintAvailabilitySpec(PlatformKind Platform,
85110
SourceLoc PlatformLoc,
86111
llvm::VersionTuple Version,
87112
SourceRange VersionSrcRange)
88-
: AvailabilitySpec(AvailabilitySpecKind::PlatformVersionConstraint),
89-
Platform(Platform), PlatformLoc(PlatformLoc), Version(Version),
90-
VersionSrcRange(VersionSrcRange) {}
113+
: AvailabilitySpec(AvailabilitySpecKind::PlatformVersionConstraint,
114+
getDomainForPlatform(Platform),
115+
SourceRange(PlatformLoc, VersionSrcRange.End), Version,
116+
VersionSrcRange.Start) {}
91117

92118
/// The required platform.
93-
PlatformKind getPlatform() const { return Platform; }
94-
SourceLoc getPlatformLoc() const { return PlatformLoc; }
119+
PlatformKind getPlatform() const {
120+
if (auto domain = getDomain())
121+
return domain->getPlatformKind();
122+
return PlatformKind::none;
123+
}
124+
SourceLoc getPlatformLoc() const { return getSourceRange().Start; }
95125

96126
/// Returns true when the constraint is for a platform that was not
97127
/// recognized. This enables better recovery during parsing but should never
98128
/// be true after parsing is completed.
99-
bool isUnrecognizedPlatform() const { return Platform == PlatformKind::none; }
100-
101-
// The platform version to compare against.
102-
llvm::VersionTuple getVersion() const;
103-
SourceRange getVersionSrcRange() const { return VersionSrcRange; }
129+
bool isUnrecognizedPlatform() const {
130+
return getPlatform() == PlatformKind::none;
131+
}
104132

105133
// The version to be used in codegen for version comparisons at run time.
106134
// This is required to support beta versions of macOS Big Sur that
107135
// report 10.16 at run time.
108136
llvm::VersionTuple getRuntimeVersion() const;
109137

110-
SourceRange getSourceRange() const;
111-
112-
// Location of the macro expanded to create this spec.
113-
SourceLoc getMacroLoc() const { return MacroLoc; }
114-
void setMacroLoc(SourceLoc loc) { MacroLoc = loc; }
115-
116138
void print(raw_ostream &OS, unsigned Indent) const;
117139

118140
static bool classof(const AvailabilitySpec *Spec) {
@@ -130,31 +152,37 @@ class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec {
130152
/// An availability specification that guards execution based on the
131153
/// compile-time platform agnostic version, e.g., swift >= 3.0.1,
132154
/// package-description >= 4.0.
133-
class PlatformAgnosticVersionConstraintAvailabilitySpec : public AvailabilitySpec {
134-
SourceLoc PlatformAgnosticNameLoc;
135-
136-
llvm::VersionTuple Version;
137-
SourceRange VersionSrcRange;
155+
class PlatformAgnosticVersionConstraintAvailabilitySpec
156+
: public AvailabilitySpec {
157+
158+
static AvailabilityDomain getDomainForSpecKind(AvailabilitySpecKind Kind) {
159+
switch (Kind) {
160+
case AvailabilitySpecKind::PlatformVersionConstraint:
161+
case AvailabilitySpecKind::OtherPlatform:
162+
llvm_unreachable("unexpected spec kind");
163+
case AvailabilitySpecKind::LanguageVersionConstraint:
164+
return AvailabilityDomain::forSwiftLanguage();
165+
case AvailabilitySpecKind::PackageDescriptionVersionConstraint:
166+
return AvailabilityDomain::forPackageDescription();
167+
}
168+
}
138169

139170
public:
140171
PlatformAgnosticVersionConstraintAvailabilitySpec(
141172
AvailabilitySpecKind AvailabilitySpecKind,
142173
SourceLoc PlatformAgnosticNameLoc, llvm::VersionTuple Version,
143174
SourceRange VersionSrcRange)
144-
: AvailabilitySpec(AvailabilitySpecKind),
145-
PlatformAgnosticNameLoc(PlatformAgnosticNameLoc), Version(Version),
146-
VersionSrcRange(VersionSrcRange) {
175+
: AvailabilitySpec(
176+
AvailabilitySpecKind, getDomainForSpecKind(AvailabilitySpecKind),
177+
SourceRange(PlatformAgnosticNameLoc, VersionSrcRange.End), Version,
178+
VersionSrcRange.Start) {
147179
assert(AvailabilitySpecKind == AvailabilitySpecKind::LanguageVersionConstraint ||
148180
AvailabilitySpecKind == AvailabilitySpecKind::PackageDescriptionVersionConstraint);
149181
}
150182

151-
SourceLoc getPlatformAgnosticNameLoc() const { return PlatformAgnosticNameLoc; }
152-
153-
// The platform version to compare against.
154-
llvm::VersionTuple getVersion() const { return Version; }
155-
SourceRange getVersionSrcRange() const { return VersionSrcRange; }
156-
157-
SourceRange getSourceRange() const;
183+
SourceLoc getPlatformAgnosticNameLoc() const {
184+
return getSourceRange().Start;
185+
}
158186

159187
bool isLanguageVersionSpecific() const {
160188
return getKind() == AvailabilitySpecKind::LanguageVersionConstraint;
@@ -185,16 +213,14 @@ class PlatformAgnosticVersionConstraintAvailabilitySpec : public AvailabilitySpe
185213
/// that we still do compile-time availability checking with '*', so the
186214
/// compiler will still catch references to potentially unavailable symbols.
187215
class OtherPlatformAvailabilitySpec : public AvailabilitySpec {
188-
SourceLoc StarLoc;
189-
190216
public:
191217
OtherPlatformAvailabilitySpec(SourceLoc StarLoc)
192-
: AvailabilitySpec(AvailabilitySpecKind::OtherPlatform),
193-
StarLoc(StarLoc) {}
194-
195-
SourceLoc getStarLoc() const { return StarLoc; }
218+
: AvailabilitySpec(AvailabilitySpecKind::OtherPlatform, std::nullopt,
219+
StarLoc,
220+
/*Version=*/{},
221+
/*VersionStartLoc=*/{}) {}
196222

197-
SourceRange getSourceRange() const { return SourceRange(StarLoc, StarLoc); }
223+
SourceLoc getStarLoc() const { return getSourceRange().Start; }
198224

199225
void print(raw_ostream &OS, unsigned Indent) const;
200226

lib/AST/AvailabilitySpec.cpp

+14-79
Original file line numberDiff line numberDiff line change
@@ -21,37 +21,6 @@
2121

2222
using namespace swift;
2323

24-
SourceRange AvailabilitySpec::getSourceRange() const {
25-
switch (getKind()) {
26-
case AvailabilitySpecKind::PlatformVersionConstraint:
27-
return cast<PlatformVersionConstraintAvailabilitySpec>(this)->getSourceRange();
28-
29-
case AvailabilitySpecKind::LanguageVersionConstraint:
30-
case AvailabilitySpecKind::PackageDescriptionVersionConstraint:
31-
return cast<PlatformAgnosticVersionConstraintAvailabilitySpec>(this)->getSourceRange();
32-
33-
case AvailabilitySpecKind::OtherPlatform:
34-
return cast<OtherPlatformAvailabilitySpec>(this)->getSourceRange();
35-
}
36-
llvm_unreachable("bad AvailabilitySpecKind");
37-
}
38-
39-
std::optional<AvailabilityDomain> AvailabilitySpec::getDomain() const {
40-
switch (getKind()) {
41-
case AvailabilitySpecKind::PlatformVersionConstraint: {
42-
auto spec = cast<PlatformVersionConstraintAvailabilitySpec>(this);
43-
return AvailabilityDomain::forPlatform(spec->getPlatform());
44-
}
45-
case AvailabilitySpecKind::LanguageVersionConstraint:
46-
return AvailabilityDomain::forSwiftLanguage();
47-
case AvailabilitySpecKind::PackageDescriptionVersionConstraint:
48-
return AvailabilityDomain::forPackageDescription();
49-
case AvailabilitySpecKind::OtherPlatform:
50-
return std::nullopt;
51-
}
52-
llvm_unreachable("bad AvailabilitySpecKind");
53-
}
54-
5524
std::optional<PlatformKind> AvailabilitySpec::getPlatform() const {
5625
switch (getKind()) {
5726
case AvailabilitySpecKind::PlatformVersionConstraint: {
@@ -70,38 +39,24 @@ llvm::VersionTuple AvailabilitySpec::getVersion() const {
7039
switch (getKind()) {
7140
case AvailabilitySpecKind::PlatformVersionConstraint: {
7241
auto spec = cast<PlatformVersionConstraintAvailabilitySpec>(this);
73-
return spec->getVersion();
42+
// For macOS Big Sur, we canonicalize 10.16 to 11.0 for compile-time
43+
// checking since clang canonicalizes availability markup. However, to
44+
// support Beta versions of macOS Big Sur where the OS
45+
// reports 10.16 at run time, we need to compare against 10.16,
46+
//
47+
// This means for:
48+
//
49+
// if #available(macOS 10.16, *) { ... }
50+
//
51+
// we need to store the uncanonicalized version for codegen and canonicalize
52+
// it as necessary for compile-time checks.
53+
return canonicalizePlatformVersion(spec->getPlatform(), Version);
7454
}
7555
case AvailabilitySpecKind::LanguageVersionConstraint:
76-
case AvailabilitySpecKind::PackageDescriptionVersionConstraint: {
77-
auto spec = cast<PlatformAgnosticVersionConstraintAvailabilitySpec>(this);
78-
return spec->getVersion();
79-
}
80-
case AvailabilitySpecKind::OtherPlatform:
81-
return llvm::VersionTuple();
82-
}
83-
llvm_unreachable("bad AvailabilitySpecKind");
84-
}
85-
86-
SourceRange AvailabilitySpec::getVersionSrcRange() const {
87-
switch (getKind()) {
88-
case AvailabilitySpecKind::PlatformVersionConstraint: {
89-
auto spec = cast<PlatformVersionConstraintAvailabilitySpec>(this);
90-
return spec->getVersionSrcRange();
91-
}
92-
case AvailabilitySpecKind::LanguageVersionConstraint:
93-
case AvailabilitySpecKind::PackageDescriptionVersionConstraint: {
94-
auto spec = cast<PlatformAgnosticVersionConstraintAvailabilitySpec>(this);
95-
return spec->getVersionSrcRange();
96-
}
56+
case AvailabilitySpecKind::PackageDescriptionVersionConstraint:
9757
case AvailabilitySpecKind::OtherPlatform:
98-
return SourceRange();
58+
return Version;
9959
}
100-
llvm_unreachable("bad AvailabilitySpecKind");
101-
}
102-
103-
SourceRange PlatformVersionConstraintAvailabilitySpec::getSourceRange() const {
104-
return SourceRange(PlatformLoc, VersionSrcRange.End);
10560
}
10661

10762
void PlatformVersionConstraintAvailabilitySpec::print(raw_ostream &OS,
@@ -112,26 +67,6 @@ void PlatformVersionConstraintAvailabilitySpec::print(raw_ostream &OS,
11267
<< ')';
11368
}
11469

115-
SourceRange PlatformAgnosticVersionConstraintAvailabilitySpec::getSourceRange() const {
116-
return SourceRange(PlatformAgnosticNameLoc, VersionSrcRange.End);
117-
}
118-
119-
llvm::VersionTuple
120-
PlatformVersionConstraintAvailabilitySpec::getVersion() const {
121-
// For macOS Big Sur, we canonicalize 10.16 to 11.0 for compile-time
122-
// checking since clang canonicalizes availability markup. However, to
123-
// support Beta versions of macOS Big Sur where the OS
124-
// reports 10.16 at run time, we need to compare against 10.16,
125-
//
126-
// This means for:
127-
//
128-
// if #available(macOS 10.16, *) { ... }
129-
//
130-
// we need to store the uncanonicalized version for codegen and canonicalize
131-
// it as necessary for compile-time checks.
132-
return canonicalizePlatformVersion(Platform, Version);
133-
}
134-
13570
llvm::VersionTuple
13671
PlatformVersionConstraintAvailabilitySpec::getRuntimeVersion() const {
13772
return Version;

0 commit comments

Comments
 (0)