1818#ifndef SWIFT_AST_AVAILABILITY_DOMAIN_H
1919#define SWIFT_AST_AVAILABILITY_DOMAIN_H
2020
21+ #include " swift/AST/ASTAllocated.h"
22+ #include " swift/AST/Identifier.h"
2123#include " swift/AST/PlatformKind.h"
2224#include " swift/Basic/LLVM.h"
2325#include " llvm/ADT/FoldingSet.h"
2628
2729namespace swift {
2830class ASTContext ;
31+ class CustomAvailabilityDomain ;
2932class DeclContext ;
33+ class ModuleDecl ;
3034
3135// / Represents a dimension of availability (e.g. macOS platform or Swift
3236// / language mode).
@@ -48,6 +52,10 @@ class AvailabilityDomain final {
4852
4953 // / Represents availability for a specific operating system platform.
5054 Platform,
55+
56+ // / Represents availability for an arbitrary domain that is defined at
57+ // / compile time by a module.
58+ Custom,
5159 };
5260
5361private:
@@ -86,13 +94,10 @@ class AvailabilityDomain final {
8694 PlatformKind getPlatform () { return platform; }
8795 };
8896
89- // / This will eventually be a class storing information about externally
90- // / defined availability domains.
91- using ExternalDomain = void ;
92-
9397 using InlineDomainPtr =
9498 llvm::PointerEmbeddedInt<uint32_t , InlineDomain::ReprBits>;
95- using Storage = llvm::PointerUnion<ExternalDomain *, InlineDomainPtr>;
99+ using Storage =
100+ llvm::PointerUnion<CustomAvailabilityDomain *, InlineDomainPtr>;
96101 Storage storage;
97102
98103 AvailabilityDomain (Kind kind)
@@ -103,6 +108,8 @@ class AvailabilityDomain final {
103108 AvailabilityDomain (PlatformKind platform)
104109 : storage(InlineDomain(Kind::Platform, platform).asInteger()) {};
105110
111+ AvailabilityDomain (CustomAvailabilityDomain *domain) : storage(domain) {};
112+
106113 AvailabilityDomain (Storage storage) : storage(storage) {};
107114
108115 static AvailabilityDomain fromOpaque (void *opaque) {
@@ -118,6 +125,11 @@ class AvailabilityDomain final {
118125 : std::nullopt ;
119126 }
120127
128+ CustomAvailabilityDomain *getCustomDomain () const {
129+ assert (isCustom ());
130+ return storage.get <CustomAvailabilityDomain *>();
131+ }
132+
121133public:
122134 AvailabilityDomain () {}
123135
@@ -141,6 +153,10 @@ class AvailabilityDomain final {
141153 return AvailabilityDomain (Kind::Embedded);
142154 }
143155
156+ static AvailabilityDomain forCustom (CustomAvailabilityDomain *domain) {
157+ return AvailabilityDomain (domain);
158+ }
159+
144160 // / Returns the built-in availability domain identified by the given string.
145161 static std::optional<AvailabilityDomain>
146162 builtinDomainForString (StringRef string, const DeclContext *declContext);
@@ -149,7 +165,7 @@ class AvailabilityDomain final {
149165 if (auto inlineDomain = getInlineDomain ())
150166 return inlineDomain->getKind ();
151167
152- llvm_unreachable ( " unimplemented " ) ;
168+ return Kind::Custom ;
153169 }
154170
155171 bool isUniversal () const { return getKind () == Kind::Universal; }
@@ -164,6 +180,8 @@ class AvailabilityDomain final {
164180
165181 bool isEmbedded () const { return getKind () == Kind::Embedded; }
166182
183+ bool isCustom () const { return getKind () == Kind::Custom; }
184+
167185 // / Returns the platform kind for this domain if applicable.
168186 PlatformKind getPlatformKind () const {
169187 if (auto inlineDomain = getInlineDomain ())
@@ -172,6 +190,10 @@ class AvailabilityDomain final {
172190 return PlatformKind::none;
173191 }
174192
193+ // / Returns true if availability for this domain can be specified in terms of
194+ // / version ranges.
195+ bool isVersioned () const ;
196+
175197 // / Returns true if this domain is considered active in the current
176198 // / compilation context.
177199 bool isActive (const ASTContext &ctx) const ;
@@ -183,6 +205,9 @@ class AvailabilityDomain final {
183205 // / Returns the string to use when printing an `@available` attribute.
184206 llvm::StringRef getNameForAttributePrinting () const ;
185207
208+ // / Returns the module that the domain belongs to, if it is a custom domain.
209+ ModuleDecl *getModule () const ;
210+
186211 // / Returns true if availability in `other` is a subset of availability in
187212 // / this domain. The set of all availability domains form a lattice where the
188213 // / universal domain (`*`) is the bottom element.
@@ -196,28 +221,39 @@ class AvailabilityDomain final {
196221 return !(*this == other);
197222 }
198223
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-
216224 void Profile (llvm::FoldingSetNodeID &ID) const {
217225 ID.AddPointer (getOpaqueValue ());
218226 }
219227};
220228
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+
221257} // end namespace swift
222258
223259namespace llvm {
@@ -249,6 +285,10 @@ struct DenseMapInfo<AvailabilityDomain> {
249285 static inline AvailabilityDomain getTombstoneKey () {
250286 return DenseMapInfo<AvailabilityDomain::Storage>::getTombstoneKey ();
251287 }
288+ static inline unsigned getHashValue (AvailabilityDomain domain) {
289+ return DenseMapInfo<AvailabilityDomain::Storage>::getHashValue (
290+ domain.storage );
291+ }
252292 static bool isEqual (const AvailabilityDomain LHS,
253293 const AvailabilityDomain RHS) {
254294 return LHS == RHS;
0 commit comments