18
18
#ifndef SWIFT_AST_AVAILABILITY_DOMAIN_H
19
19
#define SWIFT_AST_AVAILABILITY_DOMAIN_H
20
20
21
+ #include " swift/AST/ASTAllocated.h"
22
+ #include " swift/AST/Identifier.h"
21
23
#include " swift/AST/PlatformKind.h"
22
24
#include " swift/Basic/LLVM.h"
23
25
#include " llvm/ADT/FoldingSet.h"
26
28
27
29
namespace swift {
28
30
class ASTContext ;
31
+ class CustomAvailabilityDomain ;
29
32
class DeclContext ;
33
+ class ModuleDecl ;
30
34
31
35
// / Represents a dimension of availability (e.g. macOS platform or Swift
32
36
// / language mode).
@@ -48,6 +52,10 @@ class AvailabilityDomain final {
48
52
49
53
// / Represents availability for a specific operating system platform.
50
54
Platform,
55
+
56
+ // / Represents availability for an arbitrary domain that is defined at
57
+ // / compile time by a module.
58
+ Custom,
51
59
};
52
60
53
61
private:
@@ -86,13 +94,10 @@ class AvailabilityDomain final {
86
94
PlatformKind getPlatform () { return platform; }
87
95
};
88
96
89
- // / This will eventually be a class storing information about externally
90
- // / defined availability domains.
91
- using ExternalDomain = void ;
92
-
93
97
using InlineDomainPtr =
94
98
llvm::PointerEmbeddedInt<uint32_t , InlineDomain::ReprBits>;
95
- using Storage = llvm::PointerUnion<ExternalDomain *, InlineDomainPtr>;
99
+ using Storage =
100
+ llvm::PointerUnion<CustomAvailabilityDomain *, InlineDomainPtr>;
96
101
Storage storage;
97
102
98
103
AvailabilityDomain (Kind kind)
@@ -103,6 +108,8 @@ class AvailabilityDomain final {
103
108
AvailabilityDomain (PlatformKind platform)
104
109
: storage(InlineDomain(Kind::Platform, platform).asInteger()) {};
105
110
111
+ AvailabilityDomain (CustomAvailabilityDomain *domain) : storage(domain) {};
112
+
106
113
AvailabilityDomain (Storage storage) : storage(storage) {};
107
114
108
115
static AvailabilityDomain fromOpaque (void *opaque) {
@@ -118,6 +125,11 @@ class AvailabilityDomain final {
118
125
: std::nullopt ;
119
126
}
120
127
128
+ CustomAvailabilityDomain *getCustomDomain () const {
129
+ assert (isCustom ());
130
+ return storage.get <CustomAvailabilityDomain *>();
131
+ }
132
+
121
133
public:
122
134
AvailabilityDomain () {}
123
135
@@ -141,6 +153,10 @@ class AvailabilityDomain final {
141
153
return AvailabilityDomain (Kind::Embedded);
142
154
}
143
155
156
+ static AvailabilityDomain forCustom (CustomAvailabilityDomain *domain) {
157
+ return AvailabilityDomain (domain);
158
+ }
159
+
144
160
// / Returns the built-in availability domain identified by the given string.
145
161
static std::optional<AvailabilityDomain>
146
162
builtinDomainForString (StringRef string, const DeclContext *declContext);
@@ -149,7 +165,7 @@ class AvailabilityDomain final {
149
165
if (auto inlineDomain = getInlineDomain ())
150
166
return inlineDomain->getKind ();
151
167
152
- llvm_unreachable ( " unimplemented " ) ;
168
+ return Kind::Custom ;
153
169
}
154
170
155
171
bool isUniversal () const { return getKind () == Kind::Universal; }
@@ -164,6 +180,8 @@ class AvailabilityDomain final {
164
180
165
181
bool isEmbedded () const { return getKind () == Kind::Embedded; }
166
182
183
+ bool isCustom () const { return getKind () == Kind::Custom; }
184
+
167
185
// / Returns the platform kind for this domain if applicable.
168
186
PlatformKind getPlatformKind () const {
169
187
if (auto inlineDomain = getInlineDomain ())
@@ -172,6 +190,10 @@ class AvailabilityDomain final {
172
190
return PlatformKind::none;
173
191
}
174
192
193
+ // / Returns true if availability for this domain can be specified in terms of
194
+ // / version ranges.
195
+ bool isVersioned () const ;
196
+
175
197
// / Returns true if this domain is considered active in the current
176
198
// / compilation context.
177
199
bool isActive (const ASTContext &ctx) const ;
@@ -183,6 +205,9 @@ class AvailabilityDomain final {
183
205
// / Returns the string to use when printing an `@available` attribute.
184
206
llvm::StringRef getNameForAttributePrinting () const ;
185
207
208
+ // / Returns the module that the domain belongs to, if it is a custom domain.
209
+ ModuleDecl *getModule () const ;
210
+
186
211
// / Returns true if availability in `other` is a subset of availability in
187
212
// / this domain. The set of all availability domains form a lattice where the
188
213
// / universal domain (`*`) is the bottom element.
@@ -196,28 +221,39 @@ class AvailabilityDomain final {
196
221
return !(*this == other);
197
222
}
198
223
199
- // / A total, stable ordering on domains.
200
- bool operator <(const AvailabilityDomain &other) const {
201
- if (getKind () != other.getKind ())
202
- return getKind () < other.getKind ();
203
-
204
- switch (getKind ()) {
205
- case Kind::Universal:
206
- case Kind::SwiftLanguage:
207
- case Kind::PackageDescription:
208
- case Kind::Embedded:
209
- // These availability domains are singletons.
210
- return false ;
211
- case Kind::Platform:
212
- return getPlatformKind () < other.getPlatformKind ();
213
- }
214
- }
215
-
216
224
void Profile (llvm::FoldingSetNodeID &ID) const {
217
225
ID.AddPointer (getOpaqueValue ());
218
226
}
219
227
};
220
228
229
+ // / Represents an availability domain that has been defined in a module.
230
+ class CustomAvailabilityDomain : public ASTAllocated <CustomAvailabilityDomain> {
231
+ public:
232
+ enum class Kind {
233
+ // / A domain that is known to be enabled at compile time.
234
+ Enabled,
235
+ // / A domain that is known to be disabled at compile time.
236
+ Disabled,
237
+ // / A domain with an enablement state that must be queried at runtime.
238
+ Dynamic,
239
+ };
240
+
241
+ private:
242
+ Identifier name;
243
+ Kind kind;
244
+ ModuleDecl *mod;
245
+
246
+ CustomAvailabilityDomain (Identifier name, ModuleDecl *mod, Kind kind);
247
+
248
+ public:
249
+ static CustomAvailabilityDomain *create (const ASTContext &ctx, StringRef name,
250
+ ModuleDecl *mod, Kind kind);
251
+
252
+ Identifier getName () const { return name; }
253
+ Kind getKind () const { return kind; }
254
+ ModuleDecl *getModule () const { return mod; }
255
+ };
256
+
221
257
} // end namespace swift
222
258
223
259
namespace llvm {
@@ -249,6 +285,10 @@ struct DenseMapInfo<AvailabilityDomain> {
249
285
static inline AvailabilityDomain getTombstoneKey () {
250
286
return DenseMapInfo<AvailabilityDomain::Storage>::getTombstoneKey ();
251
287
}
288
+ static inline unsigned getHashValue (AvailabilityDomain domain) {
289
+ return DenseMapInfo<AvailabilityDomain::Storage>::getHashValue (
290
+ domain.storage );
291
+ }
252
292
static bool isEqual (const AvailabilityDomain LHS,
253
293
const AvailabilityDomain RHS) {
254
294
return LHS == RHS;
0 commit comments