@@ -541,122 +541,120 @@ std::optional<SemanticAvailableAttr> Decl::getUnavailableAttr() const {
541
541
return std::nullopt;
542
542
}
543
543
544
- static llvm::SmallVector <AvailabilityDomain, 2 >
544
+ static llvm::SmallSetVector <AvailabilityDomain, 2 >
545
545
availabilityDomainsForABICompatibility (const ASTContext &ctx) {
546
- llvm::SmallVector <AvailabilityDomain, 2 > domains;
546
+ llvm::SmallSetVector <AvailabilityDomain, 2 > domains;
547
547
548
548
// Regardless of target platform, binaries built for Embedded do not require
549
549
// compatibility.
550
550
if (ctx.LangOpts .hasFeature (Feature::Embedded))
551
551
return domains;
552
552
553
553
if (auto targetDomain = AvailabilityDomain::forTargetPlatform (ctx))
554
- domains.push_back (targetDomain->getABICompatibilityDomain ());
555
-
554
+ domains.insert (targetDomain->getABICompatibilityDomain ());
555
+
556
556
if (auto variantDomain = AvailabilityDomain::forTargetVariantPlatform (ctx))
557
- domains.push_back (variantDomain->getABICompatibilityDomain ());
557
+ domains.insert (variantDomain->getABICompatibilityDomain ());
558
558
559
559
return domains;
560
560
}
561
561
562
- // / Returns true if \p decl is proven to be unavailable for all platforms that
563
- // / external modules interacting with this module could target. A declaration
564
- // / that is not proven to be unavailable in this way could be reachable at
565
- // / runtime, even if it is unavailable to all code in this module.
566
- static bool isUnavailableForAllABICompatiblePlatforms (const Decl *decl) {
562
+ static bool constraintIndicatesRuntimeUnavailability (
563
+ const AvailabilityConstraint &constraint, const ASTContext &ctx) {
564
+ switch (constraint.getReason ()) {
565
+ case AvailabilityConstraint::Reason::UnconditionallyUnavailable: {
566
+ return true ;
567
+ }
568
+ case AvailabilityConstraint::Reason::UnavailableForDeployment:
569
+ case AvailabilityConstraint::Reason::Obsoleted:
570
+ case AvailabilityConstraint::Reason::PotentiallyUnavailable:
571
+ return false ;
572
+ }
573
+ }
574
+
575
+ // / Computes the `DeclRuntimeAvailability` value for `decl`.
576
+ static DeclRuntimeAvailability getDeclRuntimeAvailability (const Decl *decl) {
567
577
// Don't trust unavailability on declarations from Clang modules.
568
578
if (isa<ClangModuleUnit>(decl->getDeclContext ()->getModuleScopeContext ()))
569
- return false ;
579
+ return DeclRuntimeAvailability::PotentiallyAvailable;
580
+
581
+ // Check whether the decl is unavailable at all.
582
+ if (!decl->isUnavailable ())
583
+ return DeclRuntimeAvailability::PotentiallyAvailable;
570
584
571
585
auto &ctx = decl->getASTContext ();
572
- llvm::SmallVector<AvailabilityDomain, 2 > compatibilityDomains =
573
- availabilityDomainsForABICompatibility (ctx);
574
-
575
- llvm::SmallSet<AvailabilityDomain, 8 > unavailableDescendantDomains;
576
- llvm::SmallSet<AvailabilityDomain, 8 > availableDescendantDomains;
577
-
578
- // Build up the collection of relevant available and unavailable platform
579
- // domains by looking at all the @available attributes. Along the way, we
580
- // may find an attribute that makes the declaration universally unavailable
581
- // in which case platform availability is irrelevant.
582
- for (auto attr : decl->getSemanticAvailableAttrs (/* includeInactive=*/ true )) {
583
- auto domain = attr.getDomain ();
586
+ auto compatibilityDomains = availabilityDomainsForABICompatibility (ctx);
587
+ auto potentiallyAvailableDomains = compatibilityDomains;
588
+
589
+ AvailabilityConstraintFlags flags;
590
+
591
+ // Semantic availability was already computed separately for any enclosing
592
+ // extension.
593
+ flags |= AvailabilityConstraintFlag::SkipEnclosingExtension;
594
+
595
+ // FIXME: [availability] Inactive domains have to be included because iOS
596
+ // availability is considered inactive when compiling a zippered module.
597
+ flags |= AvailabilityConstraintFlag::IncludeAllDomains;
598
+
599
+ auto constraints = getAvailabilityConstraintsForDecl (
600
+ decl, AvailabilityContext::forInliningTarget (ctx), flags);
601
+
602
+ for (auto constraint : constraints) {
603
+ if (!constraintIndicatesRuntimeUnavailability (constraint, ctx))
604
+ continue ;
605
+
606
+ // Check whether the constraint is from a relevant domain.
607
+ auto domain = constraint.getDomain ();
584
608
bool isCompabilityDomainDescendant =
585
609
llvm::find_if (compatibilityDomains,
586
610
[&domain](AvailabilityDomain compatibilityDomain) {
587
611
return compatibilityDomain.contains (domain);
588
612
}) != compatibilityDomains.end ();
589
613
614
+ if (!domain.isActive (ctx) && !isCompabilityDomainDescendant)
615
+ continue ;
616
+
590
617
if (isCompabilityDomainDescendant) {
591
- // Record the whether the descendant domain is marked available
592
- // or unavailable. Unavailability overrides availability.
593
- if (attr.isUnconditionallyUnavailable ()) {
594
- availableDescendantDomains.erase (domain);
595
- unavailableDescendantDomains.insert (domain);
596
- } else if (!unavailableDescendantDomains.contains (domain)) {
597
- availableDescendantDomains.insert (domain);
598
- }
599
- } else if (attr.isActive (ctx)) {
600
- // The declaration is always unavailable if an active attribute from a
601
- // domain outside the compatibility hierarchy indicates unavailability.
602
- if (attr.isUnconditionallyUnavailable ())
603
- return true ;
618
+ // If the decl is still potentially available in some compatibility
619
+ // domain, keep looking at the remaining constraints.
620
+ potentiallyAvailableDomains.remove (domain);
621
+ if (!potentiallyAvailableDomains.empty ())
622
+ continue ;
604
623
}
605
- }
606
624
607
- // If there aren't any compatibility domains to check and we didn't find any
608
- // other active attributes that make the declaration unavailable, then it must
609
- // be available.
610
- if (compatibilityDomains.empty ())
611
- return false ;
612
-
613
- // Verify that the declaration has been marked unavailable in every
614
- // compatibility domain.
615
- for (auto compatibilityDomain : compatibilityDomains) {
616
- if (!unavailableDescendantDomains.contains (compatibilityDomain))
617
- return false ;
625
+ // Either every compatibility domain has been proven unavailable or this
626
+ // constraint proves runtime unavailability on its own.
627
+ return DeclRuntimeAvailability::AlwaysUnavailableABICompatible;
618
628
}
619
-
620
- // Verify that there aren't any explicitly available descendant domains.
621
- if (availableDescendantDomains.size () > 0 )
622
- return false ;
623
629
624
- return true ;
630
+ return DeclRuntimeAvailability::PotentiallyAvailable ;
625
631
}
626
632
627
- SemanticDeclAvailability
628
- SemanticDeclAvailabilityRequest ::evaluate (Evaluator &evaluator,
629
- const Decl *decl) const {
630
- auto inherited = SemanticDeclAvailability ::PotentiallyAvailable;
633
+ DeclRuntimeAvailability
634
+ DeclRuntimeAvailabilityRequest ::evaluate (Evaluator &evaluator,
635
+ const Decl *decl) const {
636
+ auto inherited = DeclRuntimeAvailability ::PotentiallyAvailable;
631
637
if (auto *parent =
632
638
AvailabilityInference::parentDeclForInferredAvailability (decl)) {
633
639
inherited = evaluateOrDefault (
634
- evaluator, SemanticDeclAvailabilityRequest {parent}, inherited);
640
+ evaluator, DeclRuntimeAvailabilityRequest {parent}, inherited);
635
641
}
636
642
637
- if (inherited == SemanticDeclAvailability::CompletelyUnavailable ||
638
- isUnavailableForAllABICompatiblePlatforms (decl))
639
- return SemanticDeclAvailability::CompletelyUnavailable;
640
-
641
- if (inherited == SemanticDeclAvailability::ConditionallyUnavailable ||
642
- decl->isUnavailable ())
643
- return SemanticDeclAvailability::ConditionallyUnavailable;
644
-
645
- return SemanticDeclAvailability::PotentiallyAvailable;
646
- }
643
+ // If the inherited semantic availability is already maximally unavailable
644
+ // then skip computing unavailability for this declaration.
645
+ if (inherited == DeclRuntimeAvailability::AlwaysUnavailableABICompatible)
646
+ return DeclRuntimeAvailability::AlwaysUnavailableABICompatible;
647
647
648
- bool Decl::isSemanticallyUnavailable () const {
649
- auto availability = evaluateOrDefault (
650
- getASTContext ().evaluator , SemanticDeclAvailabilityRequest{this },
651
- SemanticDeclAvailability::PotentiallyAvailable);
652
- return availability != SemanticDeclAvailability::PotentiallyAvailable;
648
+ auto availability = getDeclRuntimeAvailability (decl);
649
+ return std::max (inherited, availability);
653
650
}
654
651
655
652
bool Decl::isUnreachableAtRuntime () const {
656
653
auto availability = evaluateOrDefault (
657
- getASTContext ().evaluator , SemanticDeclAvailabilityRequest{this },
658
- SemanticDeclAvailability::PotentiallyAvailable);
659
- return availability == SemanticDeclAvailability::CompletelyUnavailable;
654
+ getASTContext ().evaluator , DeclRuntimeAvailabilityRequest{this },
655
+ DeclRuntimeAvailability::PotentiallyAvailable);
656
+ return availability ==
657
+ DeclRuntimeAvailability::AlwaysUnavailableABICompatible;
660
658
}
661
659
662
660
static UnavailableDeclOptimization
@@ -859,8 +857,6 @@ std::optional<llvm::VersionTuple> SemanticAvailableAttr::getIntroduced() const {
859
857
860
858
std::optional<AvailabilityRange>
861
859
SemanticAvailableAttr::getIntroducedRange (const ASTContext &Ctx) const {
862
- DEBUG_ASSERT (getDomain ().isActive (Ctx));
863
-
864
860
auto *attr = getParsedAttr ();
865
861
if (!attr->getRawIntroduced ().has_value ()) {
866
862
// For versioned domains, an "introduced:" version is always required to
@@ -899,8 +895,6 @@ std::optional<llvm::VersionTuple> SemanticAvailableAttr::getDeprecated() const {
899
895
900
896
std::optional<AvailabilityRange>
901
897
SemanticAvailableAttr::getDeprecatedRange (const ASTContext &Ctx) const {
902
- DEBUG_ASSERT (getDomain ().isActive (Ctx));
903
-
904
898
auto *attr = getParsedAttr ();
905
899
if (!attr->getRawDeprecated ().has_value ()) {
906
900
// Regardless of the whether the domain supports versions or not, an
@@ -930,8 +924,6 @@ std::optional<llvm::VersionTuple> SemanticAvailableAttr::getObsoleted() const {
930
924
931
925
std::optional<AvailabilityRange>
932
926
SemanticAvailableAttr::getObsoletedRange (const ASTContext &Ctx) const {
933
- DEBUG_ASSERT (getDomain ().isActive (Ctx));
934
-
935
927
auto *attr = getParsedAttr ();
936
928
937
929
// Obsoletion always requires a version.
0 commit comments