@@ -453,13 +453,13 @@ std::optional<SemanticAvailableAttr> Decl::getDeprecatedAttr() const {
453453 return attr;
454454
455455 auto deprecatedRange = attr.getDeprecatedRange (ctx);
456- if (deprecatedRange. isKnownUnreachable () )
456+ if (! deprecatedRange)
457457 continue ;
458458
459459 // We treat the declaration as deprecated if it is deprecated on
460460 // all deployment targets.
461461 auto deploymentRange = attr.getDomain ().getDeploymentRange (ctx);
462- if (deploymentRange && deploymentRange->isContainedIn (deprecatedRange))
462+ if (deploymentRange && deploymentRange->isContainedIn (* deprecatedRange))
463463 result.emplace (attr);
464464 }
465465 return result;
@@ -475,13 +475,13 @@ std::optional<SemanticAvailableAttr> Decl::getSoftDeprecatedAttr() const {
475475 continue ;
476476
477477 auto deprecatedRange = attr.getDeprecatedRange (ctx);
478- if (deprecatedRange. isKnownUnreachable () )
478+ if (! deprecatedRange)
479479 continue ;
480480
481481 // We treat the declaration as soft-deprecated if it is deprecated in a
482482 // future version.
483483 auto deploymentRange = attr.getDomain ().getDeploymentRange (ctx);
484- if (!deploymentRange || !deploymentRange->isContainedIn (deprecatedRange))
484+ if (!deploymentRange || !deploymentRange->isContainedIn (* deprecatedRange))
485485 result.emplace (attr);
486486 }
487487 return result;
@@ -705,7 +705,8 @@ AvailabilityRange AvailabilityInference::annotatedAvailableRangeForAttr(
705705 }
706706
707707 if (bestAvailAttr)
708- return bestAvailAttr->getIntroducedRange (ctx);
708+ return bestAvailAttr->getIntroducedRange (ctx).value_or (
709+ AvailabilityRange::alwaysAvailable ());
709710
710711 return AvailabilityRange::alwaysAvailable ();
711712}
@@ -737,8 +738,10 @@ Decl::getAvailableAttrForPlatformIntroduction(bool checkExtension) const {
737738}
738739
739740AvailabilityRange AvailabilityInference::availableRange (const Decl *D) {
741+ // ALLANXXX
740742 if (auto attr = D->getAvailableAttrForPlatformIntroduction ())
741- return attr->getIntroducedRange (D->getASTContext ());
743+ return attr->getIntroducedRange (D->getASTContext ())
744+ .value_or (AvailabilityRange::alwaysAvailable ());
742745
743746 return AvailabilityRange::alwaysAvailable ();
744747}
@@ -854,13 +857,29 @@ std::optional<llvm::VersionTuple> SemanticAvailableAttr::getIntroduced() const {
854857 return std::nullopt ;
855858}
856859
857- AvailabilityRange
860+ std::optional< AvailabilityRange>
858861SemanticAvailableAttr::getIntroducedRange (const ASTContext &Ctx) const {
859862 DEBUG_ASSERT (getDomain ().isActive (Ctx));
860863
861864 auto *attr = getParsedAttr ();
862- if (!attr->getRawIntroduced ().has_value ())
863- return AvailabilityRange::alwaysAvailable ();
865+ if (!attr->getRawIntroduced ().has_value ()) {
866+ // For versioned domains, an "introduced:" version is always required to
867+ // indicate introduction.
868+ if (getDomain ().isVersioned ())
869+ return std::nullopt ;
870+
871+ // For version-less domains, an attribute that does not indicate some other
872+ // kind of unconditional availability constraint implicitly specifies that
873+ // the decl is available in all versions of the domain.
874+ switch (attr->getKind ()) {
875+ case AvailableAttr::Kind::Default:
876+ return AvailabilityRange::alwaysAvailable ();
877+ case AvailableAttr::Kind::Deprecated:
878+ case AvailableAttr::Kind::Unavailable:
879+ case AvailableAttr::Kind::NoAsync:
880+ return std::nullopt ;
881+ }
882+ }
864883
865884 llvm::VersionTuple introducedVersion = getIntroduced ().value ();
866885 AvailabilityDomain unusedDomain;
@@ -878,13 +897,20 @@ std::optional<llvm::VersionTuple> SemanticAvailableAttr::getDeprecated() const {
878897 return std::nullopt ;
879898}
880899
881- AvailabilityRange
900+ std::optional< AvailabilityRange>
882901SemanticAvailableAttr::getDeprecatedRange (const ASTContext &Ctx) const {
883902 DEBUG_ASSERT (getDomain ().isActive (Ctx));
884903
885904 auto *attr = getParsedAttr ();
886- if (!attr->getRawDeprecated ().has_value ())
887- return AvailabilityRange::neverAvailable ();
905+ if (!attr->getRawDeprecated ().has_value ()) {
906+ // Regardless of the whether the domain supports versions or not, an
907+ // unconditional deprecation attribute indicates the decl is always
908+ // deprecated.
909+ if (isUnconditionallyDeprecated ())
910+ return AvailabilityRange::alwaysAvailable ();
911+
912+ return std::nullopt ;
913+ }
888914
889915 llvm::VersionTuple deprecatedVersion = getDeprecated ().value ();
890916 AvailabilityDomain unusedDomain;
@@ -902,13 +928,15 @@ std::optional<llvm::VersionTuple> SemanticAvailableAttr::getObsoleted() const {
902928 return std::nullopt ;
903929}
904930
905- AvailabilityRange
931+ std::optional< AvailabilityRange>
906932SemanticAvailableAttr::getObsoletedRange (const ASTContext &Ctx) const {
907933 DEBUG_ASSERT (getDomain ().isActive (Ctx));
908934
909935 auto *attr = getParsedAttr ();
936+
937+ // Obsoletion always requires a version.
910938 if (!attr->getRawObsoleted ().has_value ())
911- return AvailabilityRange::neverAvailable () ;
939+ return std:: nullopt ;
912940
913941 llvm::VersionTuple obsoletedVersion = getObsoleted ().value ();
914942 AvailabilityDomain unusedDomain;
0 commit comments