@@ -194,30 +194,7 @@ class VersionRange {
194194 }
195195};
196196
197- // / Records the reason a declaration is potentially unavailable.
198- class UnavailabilityReason {
199- private:
200- VersionRange RequiredDeploymentRange;
201-
202- explicit UnavailabilityReason (const VersionRange RequiredDeploymentRange)
203- : RequiredDeploymentRange(RequiredDeploymentRange) {}
204-
205- public:
206- static UnavailabilityReason requiresVersionRange (const VersionRange Range) {
207- return UnavailabilityReason (Range);
208- }
209-
210- const VersionRange &getRequiredOSVersionRange () const {
211- return RequiredDeploymentRange;
212- }
213-
214- // / Returns true if the required OS version range's lower endpoint is at or
215- // / below the deployment target of the given ASTContext.
216- bool requiresDeploymentTargetOrEarlier (ASTContext &Ctx) const ;
217- };
218-
219- // / Represents everything that a particular chunk of code may assume about its
220- // / runtime environment.
197+ // / Represents a version range in which something is available.
221198// /
222199// / The AvailabilityContext structure forms a [lattice][], which allows it to
223200// / have meaningful union and intersection operations ("join" and "meet"),
@@ -229,14 +206,10 @@ class UnavailabilityReason {
229206// / NOTE: Generally you should use the utilities on \c AvailabilityInference
230207// / to create an \c AvailabilityContext, rather than creating one directly.
231208class AvailabilityContext {
232- VersionRange OSVersion;
233- std::optional<bool > SPI;
209+ VersionRange Range;
234210
235211public:
236- // / Creates a context that requires certain versions of the target OS.
237- explicit AvailabilityContext (VersionRange OSVersion,
238- std::optional<bool > SPI = std::nullopt )
239- : OSVersion(OSVersion), SPI(SPI) {}
212+ explicit AvailabilityContext (VersionRange Range) : Range(Range) {}
240213
241214 // / Creates a context that imposes the constraints of the ASTContext's
242215 // / deployment target.
@@ -264,21 +237,34 @@ class AvailabilityContext {
264237 return AvailabilityContext (VersionRange::empty ());
265238 }
266239
267- // / Returns the range of possible OS versions required by this context.
268- VersionRange getOSVersion () const { return OSVersion; }
240+ // / Returns the range of possible versions required by this context.
241+ VersionRange getRawVersionRange () const { return Range; }
242+
243+ // / Returns true if there is a version tuple for this context.
244+ bool hasMinimumVersion () const { return Range.hasLowerEndpoint (); }
245+
246+ // / Returns the minimum version required by this context. This convenience
247+ // / is meant for debugging, diagnostics, serialization, etc. Use of the set
248+ // / algebra operations on `AvailabilityContext` should be preferred over
249+ // / direct comparison of raw versions.
250+ // /
251+ // / Only call when `hasMinimumVersion()` returns true.
252+ llvm::VersionTuple getRawMinimumVersion () const {
253+ return Range.getLowerEndpoint ();
254+ }
269255
270256 // / Returns true if \p other makes stronger guarantees than this context.
271257 // /
272258 // / That is, `a.isContainedIn(b)` implies `a.union(b) == b`.
273259 bool isContainedIn (const AvailabilityContext &other) const {
274- return OSVersion .isContainedIn (other.OSVersion );
260+ return Range .isContainedIn (other.Range );
275261 }
276262
277263 // / Returns true if \p other is a strict subset of this context.
278264 // /
279265 // / That is, `a.isSupersetOf(b)` implies `a != b` and `a.union(b) == a`.
280266 bool isSupersetOf (const AvailabilityContext &other) const {
281- return OSVersion .isSupersetOf (other.OSVersion );
267+ return Range .isSupersetOf (other.Range );
282268 }
283269
284270 // / Returns true if this context has constraints that make it impossible to
@@ -287,13 +273,13 @@ class AvailabilityContext {
287273 // / For example, the else branch of a `#available` check for iOS 8.0 when the
288274 // / containing function already requires iOS 9.
289275 bool isKnownUnreachable () const {
290- return OSVersion .isEmpty ();
276+ return Range .isEmpty ();
291277 }
292278
293279 // / Returns true if there are no constraints on this context; that is,
294280 // / nothing can be assumed.
295281 bool isAlwaysAvailable () const {
296- return OSVersion .isAll ();
282+ return Range .isAll ();
297283 }
298284
299285 // / Produces an under-approximation of the intersection of the two
@@ -306,7 +292,7 @@ class AvailabilityContext {
306292 // / As an example, this is used when figuring out the required availability
307293 // / for a type that references multiple nominal decls.
308294 void intersectWith (const AvailabilityContext &other) {
309- OSVersion .intersectWith (other.getOSVersion () );
295+ Range .intersectWith (other.Range );
310296 }
311297
312298 // / Produces an over-approximation of the intersection of the two
@@ -317,7 +303,7 @@ class AvailabilityContext {
317303 // /
318304 // / As an example, this is used for the true branch of `#available`.
319305 void constrainWith (const AvailabilityContext &other) {
320- OSVersion .constrainWith (other.getOSVersion () );
306+ Range .constrainWith (other.Range );
321307 }
322308
323309 // / Produces an over-approximation of the union of two availability contexts.
@@ -329,15 +315,19 @@ class AvailabilityContext {
329315 // / As an example, this is used for the else branch of a conditional with
330316 // / multiple `#available` checks.
331317 void unionWith (const AvailabilityContext &other) {
332- OSVersion .unionWith (other.getOSVersion () );
318+ Range .unionWith (other.Range );
333319 }
334320
335- bool isAvailableAsSPI () const { return SPI && *SPI; }
336-
337321 // / Returns a representation of this range as a string for debugging purposes.
338322 std::string getAsString () const {
339- return " AvailabilityContext(" + OSVersion.getAsString () +
340- (isAvailableAsSPI () ? " , spi" : " " ) + " )" ;
323+ return " AvailabilityContext(" + getVersionString () + " )" ;
324+ }
325+
326+ // / Returns a representation of the raw version range as a string for
327+ // / debugging purposes.
328+ std::string getVersionString () const {
329+ assert (Range.hasLowerEndpoint ());
330+ return Range.getLowerEndpoint ().getAsString ();
341331 }
342332};
343333
@@ -358,9 +348,12 @@ class AvailabilityInference {
358348 static AvailabilityContext inferForType (Type t);
359349
360350 // / Returns the context where a declaration is available
361- // / We assume a declaration without an annotation is always available.
351+ // / We assume a declaration without an annotation is always available.
362352 static AvailabilityContext availableRange (const Decl *D, ASTContext &C);
363353
354+ // / Returns true is the declaration is `@_spi_available`.
355+ static bool isAvailableAsSPI (const Decl *D, ASTContext &C);
356+
364357 // / Returns the availability context for a declaration with the given
365358 // / @available attribute.
366359 // /
0 commit comments