@@ -145,6 +145,25 @@ void AvailabilityInference::applyInferredAvailableAttrs(
145145 }
146146}
147147
148+ // / Returns the decl that should be considered the parent decl of the given decl
149+ // / when looking for inherited availability annotations.
150+ static Decl *parentDeclForAvailability (const Decl *D) {
151+ if (auto *AD = dyn_cast<AccessorDecl>(D))
152+ return AD->getStorage ();
153+
154+ if (auto *ED = dyn_cast<ExtensionDecl>(D)) {
155+ if (auto *NTD = ED->getExtendedNominal ())
156+ return NTD;
157+ }
158+
159+ // Clang decls may be inaccurately parented rdar://53956555
160+ if (D->hasClangNode ())
161+ return nullptr ;
162+
163+ // Availability is inherited from the enclosing context.
164+ return D->getDeclContext ()->getInnermostDeclarationDeclContext ();
165+ }
166+
148167// / Returns true if the introduced version in \p newAttr should be used instead
149168// / of the introduced version in \p prevAttr when both are attached to the same
150169// / declaration and refer to the active platform.
@@ -165,8 +184,9 @@ static bool isBetterThan(const AvailableAttr *newAttr,
165184 prevAttr->Platform );
166185}
167186
168- Optional<AvailabilityContext>
169- AvailabilityInference::annotatedAvailableRange (const Decl *D, ASTContext &Ctx) {
187+ const AvailableAttr *
188+ AvailabilityInference::attrForAnnotatedAvailableRange (const Decl *D,
189+ ASTContext &Ctx) {
170190 const AvailableAttr *bestAvailAttr = nullptr ;
171191
172192 for (auto Attr : D->getAttrs ()) {
@@ -182,6 +202,30 @@ AvailabilityInference::annotatedAvailableRange(const Decl *D, ASTContext &Ctx) {
182202 bestAvailAttr = AvailAttr;
183203 }
184204
205+ return bestAvailAttr;
206+ }
207+
208+ Optional<AvailableAttrDeclPair>
209+ SemanticAvailableRangeAttrRequest::evaluate (Evaluator &evaluator,
210+ const Decl *decl) const {
211+ if (auto attr = AvailabilityInference::attrForAnnotatedAvailableRange (
212+ decl, decl->getASTContext ()))
213+ return std::make_pair (attr, decl);
214+
215+ if (auto *parent = parentDeclForAvailability (decl))
216+ return parent->getSemanticAvailableRangeAttr ();
217+
218+ return None;
219+ }
220+
221+ Optional<AvailableAttrDeclPair> Decl::getSemanticAvailableRangeAttr () const {
222+ auto &eval = getASTContext ().evaluator ;
223+ return evaluateOrDefault (eval, SemanticAvailableRangeAttrRequest{this }, None);
224+ }
225+
226+ Optional<AvailabilityContext>
227+ AvailabilityInference::annotatedAvailableRange (const Decl *D, ASTContext &Ctx) {
228+ auto bestAvailAttr = attrForAnnotatedAvailableRange (D, Ctx);
185229 if (!bestAvailAttr)
186230 return None;
187231
@@ -195,39 +239,22 @@ bool Decl::isAvailableAsSPI() const {
195239 .isAvailableAsSPI ();
196240}
197241
198- bool IsSemanticallyUnavailableRequest::evaluate (Evaluator &evaluator,
199- const Decl *decl) const {
242+ Optional<AvailableAttrDeclPair>
243+ SemanticUnavailableAttrRequest::evaluate (Evaluator &evaluator,
244+ const Decl *decl) const {
200245 // Directly marked unavailable.
201- if (AvailableAttr::isUnavailable ( decl))
202- return true ;
246+ if (auto attr = decl-> getAttrs (). getUnavailable ( decl-> getASTContext () ))
247+ return std::make_pair (attr, decl) ;
203248
204- // If this is an extension, it's semantically unavailable if its nominal is,
205- // as there is no way to reference or construct the type.
206- if (auto *ext = dyn_cast<ExtensionDecl>(decl)) {
207- if (auto *nom = ext->getExtendedNominal ()) {
208- if (nom->isSemanticallyUnavailable ())
209- return true ;
210- }
211- }
249+ if (auto *parent = parentDeclForAvailability (decl))
250+ return parent->getSemanticUnavailableAttr ();
212251
213- // If the parent decl is semantically unavailable, then this decl is too.
214- // For local contexts, this means it's a local decl in e.g an unavailable
215- // function, which cannot be accessed. For non-local contexts, this is a
216- // nested type or a member with an unavailable parent, which cannot be
217- // referenced.
218- // Similar to `AvailableAttr::isUnavailable`, don't apply this logic to
219- // Clang decls, as they may be inaccurately parented.
220- if (!decl->hasClangNode ()) {
221- auto *DC = decl->getDeclContext ();
222- if (auto *parentDecl = DC->getInnermostDeclarationDeclContext ())
223- return parentDecl->isSemanticallyUnavailable ();
224- }
225- return false ;
252+ return None;
226253}
227254
228- bool Decl::isSemanticallyUnavailable () const {
255+ Optional<AvailableAttrDeclPair> Decl::getSemanticUnavailableAttr () const {
229256 auto &eval = getASTContext ().evaluator ;
230- return evaluateOrDefault (eval, IsSemanticallyUnavailableRequest {this }, false );
257+ return evaluateOrDefault (eval, SemanticUnavailableAttrRequest {this }, None );
231258}
232259
233260bool UnavailabilityReason::requiresDeploymentTargetOrEarlier (
0 commit comments