|
23 | 23 | #include "swift/AST/PlatformKind.h" |
24 | 24 | #include "swift/Basic/Assertions.h" |
25 | 25 | #include "swift/Basic/LLVM.h" |
| 26 | +#include "swift/Basic/SourceLoc.h" |
26 | 27 | #include "llvm/ADT/FoldingSet.h" |
27 | 28 | #include "llvm/ADT/PointerEmbeddedInt.h" |
28 | 29 | #include "llvm/ADT/PointerUnion.h" |
@@ -294,42 +295,65 @@ class CustomAvailabilityDomain : public ASTAllocated<CustomAvailabilityDomain> { |
294 | 295 | class AvailabilityDomainOrIdentifier { |
295 | 296 | friend struct llvm::PointerLikeTypeTraits<AvailabilityDomainOrIdentifier>; |
296 | 297 |
|
297 | | - using Storage = llvm::PointerUnion<AvailabilityDomain, Identifier>; |
| 298 | + using DomainOrIdentifier = llvm::PointerUnion<AvailabilityDomain, Identifier>; |
| 299 | + |
| 300 | + /// Stores an extra bit representing whether the domain has been resolved. |
| 301 | + using Storage = llvm::PointerIntPair<DomainOrIdentifier, 1, bool>; |
298 | 302 | Storage storage; |
299 | 303 |
|
300 | 304 | AvailabilityDomainOrIdentifier(Storage storage) : storage(storage) {} |
301 | 305 |
|
| 306 | + static AvailabilityDomainOrIdentifier fromOpaque(void *opaque) { |
| 307 | + return AvailabilityDomainOrIdentifier(Storage::getFromOpaqueValue(opaque)); |
| 308 | + } |
| 309 | + |
| 310 | + std::optional<AvailabilityDomain> |
| 311 | + lookUpInDeclContext(SourceLoc loc, const DeclContext *declContext) const; |
| 312 | + |
302 | 313 | public: |
303 | 314 | AvailabilityDomainOrIdentifier(Identifier identifier) |
304 | 315 | : storage(identifier) {}; |
305 | 316 | AvailabilityDomainOrIdentifier(AvailabilityDomain domain) |
306 | 317 | : storage(domain) {}; |
307 | 318 |
|
308 | | - static AvailabilityDomainOrIdentifier fromOpaque(void *opaque) { |
309 | | - return AvailabilityDomainOrIdentifier(Storage::getFromOpaqueValue(opaque)); |
| 319 | + bool isDomain() const { |
| 320 | + return storage.getPointer().is<AvailabilityDomain>(); |
310 | 321 | } |
311 | | - |
312 | | - bool isDomain() const { return storage.is<AvailabilityDomain>(); } |
313 | | - bool isIdentifier() const { return storage.is<Identifier>(); } |
| 322 | + bool isIdentifier() const { return storage.getPointer().is<Identifier>(); } |
314 | 323 |
|
315 | 324 | /// Overwrites the existing domain or identifier with the given domain. |
316 | 325 | void setDomain(AvailabilityDomain domain) { storage = Storage(domain); } |
317 | 326 |
|
318 | 327 | /// Returns the resolved domain, or `std::nullopt` if there isn't one. |
319 | 328 | std::optional<AvailabilityDomain> getAsDomain() const { |
320 | 329 | if (isDomain()) |
321 | | - return storage.get<AvailabilityDomain>(); |
| 330 | + return storage.getPointer().get<AvailabilityDomain>(); |
322 | 331 | return std::nullopt; |
323 | 332 | } |
324 | 333 |
|
325 | 334 | /// Returns the unresolved identifier, or `std::nullopt` if the domain has |
326 | 335 | /// been resolved. |
327 | 336 | std::optional<Identifier> getAsIdentifier() const { |
328 | 337 | if (isIdentifier()) |
329 | | - return storage.get<Identifier>(); |
| 338 | + return storage.getPointer().get<Identifier>(); |
330 | 339 | return std::nullopt; |
331 | 340 | } |
332 | 341 |
|
| 342 | + std::optional<AvailabilityDomain> |
| 343 | + resolveInDeclContext(SourceLoc loc, const DeclContext *declContext) { |
| 344 | + // Return the domain directly if already resolved. |
| 345 | + if (storage.getInt() || isDomain()) |
| 346 | + return getAsDomain(); |
| 347 | + |
| 348 | + // Look up the domain and cache the result. |
| 349 | + auto result = lookUpInDeclContext(loc, declContext); |
| 350 | + if (result) |
| 351 | + storage.setPointer(*result); |
| 352 | + storage.setInt(true); |
| 353 | + |
| 354 | + return result; |
| 355 | + } |
| 356 | + |
333 | 357 | /// Creates a new `AvailabilityDomainOrIdentifier`, defensively copying |
334 | 358 | /// members of the original into the given `ASTContext` in case it is |
335 | 359 | /// different than the context that the original was created for. |
|
0 commit comments