|
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