@@ -711,18 +711,13 @@ Decl::getSemanticUnavailableAttr(bool ignoreAppExtensions) const {
711711 std::nullopt );
712712}
713713
714- bool Decl::isUnreachableAtRuntime () const {
714+ static bool isDeclCompletelyUnavailable ( const Decl *decl) {
715715 // Don't trust unavailability on declarations from clang modules.
716- if (isa<ClangModuleUnit>(getDeclContext ()->getModuleScopeContext ()))
716+ if (isa<ClangModuleUnit>(decl-> getDeclContext ()->getModuleScopeContext ()))
717717 return false ;
718718
719- if (auto *parent =
720- AvailabilityInference::parentDeclForInferredAvailability (this )) {
721- if (parent->isUnreachableAtRuntime ())
722- return true ;
723- }
724-
725- auto *unavailableAttr = getUnavailableAttr (/* ignoreAppExtensions=*/ true );
719+ auto *unavailableAttr =
720+ decl->getUnavailableAttr (/* ignoreAppExtensions=*/ true );
726721 if (!unavailableAttr)
727722 return false ;
728723
@@ -733,27 +728,48 @@ bool Decl::isUnreachableAtRuntime() const {
733728 if (!unavailableAttr->isUnconditionallyUnavailable ())
734729 return false ;
735730
736- // getUnavailableAttr() can return an @available attribute that makes its
737- // declaration unavailable conditionally due to deployment target. Only
738- // stub or skip a declaration that is unavailable regardless of deployment
739- // target.
740- if (!unavailableAttr->isUnconditionallyUnavailable ())
741- return false ;
742-
743- // Universally unavailable declarations are always unreachable.
731+ // Universally unavailable declarations are always completely unavailable.
744732 if (unavailableAttr->getPlatform () == PlatformKind::none)
745733 return true ;
746734
747735 // FIXME: Support zippered frameworks (rdar://125371621)
748736 // If we have a target variant (e.g. we're building a zippered macOS
749737 // framework) then the decl is only unreachable if it is unavailable for both
750738 // the primary target and the target variant.
751- if (getASTContext ().LangOpts .TargetVariant .has_value ())
739+ if (decl-> getASTContext ().LangOpts .TargetVariant .has_value ())
752740 return false ;
753741
754742 return true ;
755743}
756744
745+ SemanticDeclAvailability
746+ SemanticDeclAvailabilityRequest::evaluate (Evaluator &evaluator,
747+ const Decl *decl) const {
748+ auto inherited = SemanticDeclAvailability::PotentiallyAvailable;
749+ if (auto *parent =
750+ AvailabilityInference::parentDeclForInferredAvailability (decl)) {
751+ inherited = evaluateOrDefault (
752+ evaluator, SemanticDeclAvailabilityRequest{parent}, inherited);
753+ }
754+
755+ if (inherited == SemanticDeclAvailability::CompletelyUnavailable ||
756+ isDeclCompletelyUnavailable (decl))
757+ return SemanticDeclAvailability::CompletelyUnavailable;
758+
759+ if (inherited == SemanticDeclAvailability::ConditionallyUnavailable ||
760+ decl->isUnavailable ())
761+ return SemanticDeclAvailability::ConditionallyUnavailable;
762+
763+ return SemanticDeclAvailability::PotentiallyAvailable;
764+ }
765+
766+ bool Decl::isUnreachableAtRuntime () const {
767+ auto availability = evaluateOrDefault (
768+ getASTContext ().evaluator , SemanticDeclAvailabilityRequest{this },
769+ SemanticDeclAvailability::PotentiallyAvailable);
770+ return availability == SemanticDeclAvailability::CompletelyUnavailable;
771+ }
772+
757773static UnavailableDeclOptimization
758774getEffectiveUnavailableDeclOptimization (ASTContext &ctx) {
759775 if (ctx.LangOpts .UnavailableDeclOptimizationMode .has_value ())
0 commit comments