@@ -453,13 +453,13 @@ std::optional<SemanticAvailableAttr> Decl::getDeprecatedAttr() const {
453
453
return attr;
454
454
455
455
auto deprecatedRange = attr.getDeprecatedRange (ctx);
456
- if (deprecatedRange. isKnownUnreachable () )
456
+ if (! deprecatedRange)
457
457
continue ;
458
458
459
459
// We treat the declaration as deprecated if it is deprecated on
460
460
// all deployment targets.
461
461
auto deploymentRange = attr.getDomain ().getDeploymentRange (ctx);
462
- if (deploymentRange && deploymentRange->isContainedIn (deprecatedRange))
462
+ if (deploymentRange && deploymentRange->isContainedIn (* deprecatedRange))
463
463
result.emplace (attr);
464
464
}
465
465
return result;
@@ -475,13 +475,13 @@ std::optional<SemanticAvailableAttr> Decl::getSoftDeprecatedAttr() const {
475
475
continue ;
476
476
477
477
auto deprecatedRange = attr.getDeprecatedRange (ctx);
478
- if (deprecatedRange. isKnownUnreachable () )
478
+ if (! deprecatedRange)
479
479
continue ;
480
480
481
481
// We treat the declaration as soft-deprecated if it is deprecated in a
482
482
// future version.
483
483
auto deploymentRange = attr.getDomain ().getDeploymentRange (ctx);
484
- if (!deploymentRange || !deploymentRange->isContainedIn (deprecatedRange))
484
+ if (!deploymentRange || !deploymentRange->isContainedIn (* deprecatedRange))
485
485
result.emplace (attr);
486
486
}
487
487
return result;
@@ -705,7 +705,8 @@ AvailabilityRange AvailabilityInference::annotatedAvailableRangeForAttr(
705
705
}
706
706
707
707
if (bestAvailAttr)
708
- return bestAvailAttr->getIntroducedRange (ctx);
708
+ return bestAvailAttr->getIntroducedRange (ctx).value_or (
709
+ AvailabilityRange::alwaysAvailable ());
709
710
710
711
return AvailabilityRange::alwaysAvailable ();
711
712
}
@@ -737,8 +738,10 @@ Decl::getAvailableAttrForPlatformIntroduction(bool checkExtension) const {
737
738
}
738
739
739
740
AvailabilityRange AvailabilityInference::availableRange (const Decl *D) {
741
+ // ALLANXXX
740
742
if (auto attr = D->getAvailableAttrForPlatformIntroduction ())
741
- return attr->getIntroducedRange (D->getASTContext ());
743
+ return attr->getIntroducedRange (D->getASTContext ())
744
+ .value_or (AvailabilityRange::alwaysAvailable ());
742
745
743
746
return AvailabilityRange::alwaysAvailable ();
744
747
}
@@ -854,13 +857,29 @@ std::optional<llvm::VersionTuple> SemanticAvailableAttr::getIntroduced() const {
854
857
return std::nullopt ;
855
858
}
856
859
857
- AvailabilityRange
860
+ std::optional< AvailabilityRange>
858
861
SemanticAvailableAttr::getIntroducedRange (const ASTContext &Ctx) const {
859
862
DEBUG_ASSERT (getDomain ().isActive (Ctx));
860
863
861
864
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
+ }
864
883
865
884
llvm::VersionTuple introducedVersion = getIntroduced ().value ();
866
885
AvailabilityDomain unusedDomain;
@@ -878,13 +897,20 @@ std::optional<llvm::VersionTuple> SemanticAvailableAttr::getDeprecated() const {
878
897
return std::nullopt ;
879
898
}
880
899
881
- AvailabilityRange
900
+ std::optional< AvailabilityRange>
882
901
SemanticAvailableAttr::getDeprecatedRange (const ASTContext &Ctx) const {
883
902
DEBUG_ASSERT (getDomain ().isActive (Ctx));
884
903
885
904
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
+ }
888
914
889
915
llvm::VersionTuple deprecatedVersion = getDeprecated ().value ();
890
916
AvailabilityDomain unusedDomain;
@@ -902,13 +928,15 @@ std::optional<llvm::VersionTuple> SemanticAvailableAttr::getObsoleted() const {
902
928
return std::nullopt ;
903
929
}
904
930
905
- AvailabilityRange
931
+ std::optional< AvailabilityRange>
906
932
SemanticAvailableAttr::getObsoletedRange (const ASTContext &Ctx) const {
907
933
DEBUG_ASSERT (getDomain ().isActive (Ctx));
908
934
909
935
auto *attr = getParsedAttr ();
936
+
937
+ // Obsoletion always requires a version.
910
938
if (!attr->getRawObsoleted ().has_value ())
911
- return AvailabilityRange::neverAvailable () ;
939
+ return std:: nullopt ;
912
940
913
941
llvm::VersionTuple obsoletedVersion = getObsoleted ().value ();
914
942
AvailabilityDomain unusedDomain;
0 commit comments