diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index c63a4390b63ca..50ab978ca3907 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -797,6 +797,13 @@ class AvailableAttr : public DeclAttribute { /// resolved successfully. std::optional getCachedDomain() const { return Domain; } + /// Returns true if the `AvailabilityDomain` associated with the attribute + /// has been resolved successfully. + bool hasCachedDomain() const { + // For now, domains are always set on construction of the attribute. + return true; + } + /// Returns the kind of availability the attribute specifies. Kind getKind() const { return static_cast(Bits.AvailableAttr.Kind); } @@ -3189,20 +3196,24 @@ class ParsedDeclAttributes { } }; -/// A wrapper for `AvailableAttr` that is enriched with additional semantic -/// informaton, like its corresponding `AvailabilityDomain`. +/// A wrapper for `AvailableAttr` that enriches it with additional semantic +/// informaton that can only be determined using the `AvailabilityDomain` +/// associated with the attribute. A `SemanticAvailableAttr` can only be +/// constructed with an `AvailableAttr` that has a resolved +/// `AvailabilityDomain`. class SemanticAvailableAttr final { const AvailableAttr *attr; - AvailabilityDomain domain; public: - SemanticAvailableAttr(const AvailableAttr *attr, AvailabilityDomain domain) - : attr(attr), domain(domain) { + SemanticAvailableAttr(const AvailableAttr *attr) : attr(attr) { assert(attr); + assert(attr->hasCachedDomain()); } const AvailableAttr *getParsedAttr() const { return attr; } - const AvailabilityDomain getDomain() const { return domain; } + const AvailabilityDomain getDomain() const { + return attr->getCachedDomain().value(); + } /// The version tuple written in source for the `introduced:` component. std::optional getIntroduced() const { @@ -3640,6 +3651,32 @@ struct EnumTraits { } // end namespace swift +namespace llvm { +using swift::AvailableAttr; +using swift::SemanticAvailableAttr; + +// A SemanticAvailableAttr just wraps an `AvailableAttr *` and is therefore +// "pointer like". +template +struct PointerLikeTypeTraits; +template <> +struct PointerLikeTypeTraits { +public: + static inline void *getAsVoidPointer(SemanticAvailableAttr attr) { + return reinterpret_cast( + const_cast(attr.getParsedAttr())); + } + static inline SemanticAvailableAttr getFromVoidPointer(void *P) { + return SemanticAvailableAttr(static_cast(P)); + } + enum { + NumLowBitsAvailable = + PointerLikeTypeTraits::NumLowBitsAvailable + }; +}; + +} // end namespace llvm + #undef UNIMPLEMENTED_CLONE #endif diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index 8db68125416cb..47cc5ecee1bc6 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -918,7 +918,7 @@ ParsedDeclAttrFilter::operator()(const DeclAttribute *Attr) const { } bool SemanticAvailableAttr::isActive(ASTContext &ctx) const { - return domain.isActive(ctx); + return getDomain().isActive(ctx); } std::optional diff --git a/lib/AST/Availability.cpp b/lib/AST/Availability.cpp index 4aac53bf59671..935d47f345cda 100644 --- a/lib/AST/Availability.cpp +++ b/lib/AST/Availability.cpp @@ -447,9 +447,7 @@ Decl::getSemanticAvailableAttrs(bool includeInactive) const { std::optional Decl::getSemanticAvailableAttr(const AvailableAttr *attr) const { - if (auto domain = attr->getCachedDomain()) - return SemanticAvailableAttr(attr, *domain); - return std::nullopt; + return SemanticAvailableAttr(attr); } std::optional @@ -790,7 +788,7 @@ bool AvailabilityInference::isAvailableAsSPI(const Decl *D) { AvailabilityRange SemanticAvailableAttr::getIntroducedRange(const ASTContext &Ctx) const { - assert(domain.isActive(Ctx)); + assert(getDomain().isActive(Ctx)); auto *attr = getParsedAttr(); if (!attr->Introduced.has_value()) diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 6dd1091331d8c..5f553a2091eba 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -3058,9 +3058,8 @@ class Serializer::DeclSerializer : public DeclVisitor { ENCODE_VER_TUPLE(Obsoleted, theAttr->Obsoleted) assert(theAttr->Rename.empty() || !theAttr->hasCachedRenamedDecl()); - + assert(theAttr->hasCachedDomain()); auto domain = theAttr->getCachedDomain(); - assert(domain); // FIXME: [availability] Serialize domain and kind directly. llvm::SmallString<32> blob;