2121#include " swift/AST/AvailabilityDomain.h"
2222#include " swift/AST/Identifier.h"
2323#include " swift/AST/PlatformKind.h"
24+ #include " swift/Basic/STLExtras.h"
2425#include " swift/Basic/SourceLoc.h"
2526#include " llvm/ADT/DenseMap.h"
2627#include " llvm/ADT/StringMap.h"
28+ #include " llvm/ADT/iterator_range.h"
2729#include " llvm/Support/VersionTuple.h"
2830
2931namespace swift {
@@ -45,6 +47,8 @@ enum class AvailabilitySpecKind {
4547 PackageDescriptionVersionConstraint,
4648};
4749
50+ class SemanticAvailabilitySpec ;
51+
4852// / The root class for specifications of API availability in availability
4953// / queries.
5054class AvailabilitySpec : public ASTAllocated <AvailabilitySpec> {
@@ -109,7 +113,14 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
109113
110114 AvailabilitySpecKind getKind () const { return Kind; }
111115
112- bool isWildcard () { return getKind () == AvailabilitySpecKind::Wildcard; }
116+ bool isWildcard () const {
117+ return getKind () == AvailabilitySpecKind::Wildcard;
118+ }
119+
120+ // / Returns a type-checked representation of the spec, or `std::nullopt` if
121+ // / the spec is invalid.
122+ std::optional<SemanticAvailabilitySpec>
123+ getSemanticAvailabilitySpec (const DeclContext *declContext) const ;
113124
114125 SourceRange getSourceRange () const { return SrcRange; }
115126 SourceLoc getStartLoc () const { return SrcRange.Start ; }
@@ -122,13 +133,8 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
122133 return PlatformKind::none;
123134 }
124135
125- // The platform version to compare against.
126- llvm::VersionTuple getVersion () const ;
127-
128- // The version to be used in codegen for version comparisons at run time.
129- // This is required to support beta versions of macOS Big Sur that
130- // report 10.16 at run time.
131- llvm::VersionTuple getRuntimeVersion () const { return Version; }
136+ // The version tuple that was written in source.
137+ llvm::VersionTuple getRawVersion () const { return Version; }
132138
133139 SourceRange getVersionSrcRange () const {
134140 if (!VersionStartLoc)
@@ -141,6 +147,67 @@ class AvailabilitySpec : public ASTAllocated<AvailabilitySpec> {
141147 void setMacroLoc (SourceLoc loc) { MacroLoc = loc; }
142148};
143149
150+ // / The type-checked representation of `AvailabilitySpec` which guaranatees that
151+ // / the spec has a valid `AvailabilityDomain`.
152+ class SemanticAvailabilitySpec {
153+ const AvailabilitySpec *spec;
154+
155+ public:
156+ SemanticAvailabilitySpec (const AvailabilitySpec *spec) : spec(spec) {
157+ // The domain must be resolved in order to wrap it in a semantic spec.
158+ ASSERT (spec->isWildcard () || spec->getDomain ());
159+ }
160+
161+ const AvailabilitySpec *getParsedSpec () const { return spec; }
162+
163+ AvailabilityDomain getDomain () const {
164+ if (isWildcard ())
165+ return AvailabilityDomain::forUniversal ();
166+ return spec->getDomain ().value ();
167+ }
168+
169+ bool isWildcard () const { return spec->isWildcard (); }
170+
171+ // The platform version to compare against.
172+ llvm::VersionTuple getVersion () const ;
173+
174+ // The version to be used in codegen for version comparisons at run time.
175+ // This is required to support beta versions of macOS Big Sur that
176+ // report 10.16 at run time.
177+ llvm::VersionTuple getRuntimeVersion () const { return spec->getRawVersion (); }
178+ };
179+
180+ // / Wraps an array of availability specs and provides an iterator for their
181+ // / semantic representations.
182+ class SemanticAvailabilitySpecs {
183+ public:
184+ class Filter final {
185+ const DeclContext *declContext;
186+
187+ public:
188+ Filter (const DeclContext *declContext) : declContext(declContext) {}
189+
190+ std::optional<SemanticAvailabilitySpec>
191+ operator ()(const AvailabilitySpec *spec) const ;
192+ };
193+
194+ using Range = OptionalTransformRange<
195+ iterator_range<ArrayRef<AvailabilitySpec *>::const_iterator>, Filter>;
196+
197+ private:
198+ Range specRange;
199+
200+ public:
201+ SemanticAvailabilitySpecs (ArrayRef<AvailabilitySpec *> specs,
202+ const DeclContext *declContext)
203+ : specRange(llvm::make_range(specs.begin(), specs.end()),
204+ Filter (declContext)) {}
205+
206+ Range::iterator begin () const { return specRange.begin (); }
207+ Range::iterator end () const { return specRange.end (); }
208+ bool empty () const { return specRange.empty (); }
209+ };
210+
144211// / Maps of macro name and version to availability specifications.
145212// / Organized as two nested \c DenseMap keyed first on the macro name then
146213// / the macro version. This structure allows to peek at macro names before
0 commit comments