3737#include " llvm/Support/SaveAndRestore.h"
3838using namespace swift ;
3939
40- ExportContext::ExportContext (DeclContext *DC, FragileFunctionKind kind,
40+ ExportContext::ExportContext (DeclContext *DC,
41+ AvailabilityContext runningOSVersion,
42+ FragileFunctionKind kind,
4143 bool spi, bool exported, bool implicit, bool deprecated,
4244 Optional<PlatformKind> unavailablePlatformKind)
43- : DC(DC), FragileKind(kind) {
45+ : DC(DC), RunningOSVersion(runningOSVersion), FragileKind(kind) {
4446 SPI = spi;
4547 Exported = exported;
4648 Implicit = implicit;
@@ -169,7 +171,10 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
169171
170172 auto *DC = D->getInnermostDeclContext ();
171173 auto fragileKind = DC->getFragileFunctionKind ();
172-
174+ auto runningOSVersion =
175+ (Ctx.LangOpts .DisableAvailabilityChecking
176+ ? AvailabilityContext::alwaysAvailable ()
177+ : TypeChecker::overApproximateAvailabilityAtLocation (D->getEndLoc (), DC));
173178 bool spi = false ;
174179 bool implicit = false ;
175180 bool deprecated = false ;
@@ -185,14 +190,19 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
185190
186191 bool exported = ::isExported (D);
187192
188- return ExportContext (DC, fragileKind, spi, exported, implicit, deprecated,
193+ return ExportContext (DC, runningOSVersion, fragileKind,
194+ spi, exported, implicit, deprecated,
189195 unavailablePlatformKind);
190196}
191197
192- ExportContext ExportContext::forFunctionBody (DeclContext *DC) {
198+ ExportContext ExportContext::forFunctionBody (DeclContext *DC, SourceLoc loc ) {
193199 auto &Ctx = DC->getASTContext ();
194200
195201 auto fragileKind = DC->getFragileFunctionKind ();
202+ auto runningOSVersion =
203+ (Ctx.LangOpts .DisableAvailabilityChecking
204+ ? AvailabilityContext::alwaysAvailable ()
205+ : TypeChecker::overApproximateAvailabilityAtLocation (loc, DC));
196206
197207 bool spi = false ;
198208 bool implicit = false ;
@@ -207,7 +217,8 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC) {
207217
208218 bool exported = false ;
209219
210- return ExportContext (DC, fragileKind, spi, exported, implicit, deprecated,
220+ return ExportContext (DC, runningOSVersion, fragileKind,
221+ spi, exported, implicit, deprecated,
211222 unavailablePlatformKind);
212223}
213224
@@ -915,8 +926,8 @@ TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc,
915926}
916927
917928Optional<UnavailabilityReason>
918- TypeChecker::checkDeclarationAvailability (const Decl *D, SourceLoc referenceLoc,
919- const DeclContext *referenceDC) {
929+ TypeChecker::checkDeclarationAvailability (const Decl *D, ExportContext where) {
930+ auto *referenceDC = where. getDeclContext ();
920931 ASTContext &Context = referenceDC->getASTContext ();
921932 if (Context.LangOpts .DisableAvailabilityChecking ) {
922933 return None;
@@ -929,7 +940,7 @@ TypeChecker::checkDeclarationAvailability(const Decl *D, SourceLoc referenceLoc,
929940 }
930941
931942 AvailabilityContext runningOSOverApprox =
932- overApproximateAvailabilityAtLocation (referenceLoc, referenceDC );
943+ where. getAvailabilityContext ( );
933944
934945 AvailabilityContext safeRangeUnderApprox{
935946 AvailabilityInference::availableRange (D, Context)};
@@ -2073,8 +2084,7 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
20732084 auto *ReferenceDC = Where.getDeclContext ();
20742085 auto &Context = ReferenceDC->getASTContext ();
20752086 if (!Context.LangOpts .DisableAvailabilityChecking ) {
2076- AvailabilityContext RunningOSVersions =
2077- overApproximateAvailabilityAtLocation (ReferenceRange.Start ,ReferenceDC);
2087+ AvailabilityContext RunningOSVersions = Where.getAvailabilityContext ();
20782088 if (RunningOSVersions.isKnownUnreachable ()) {
20792089 // Suppress a deprecation warning if the availability checking machinery
20802090 // thinks the reference program location will not execute on any
@@ -2510,6 +2520,17 @@ class ExprAvailabilityWalker : public ASTWalker {
25102520 return E;
25112521 }
25122522
2523+ std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
2524+ // We end up here when checking the output of the result builder transform,
2525+ // which includes closures that are not "separately typechecked" and yet
2526+ // contain statements and declarations. We need to walk them recursively,
2527+ // since these availability for these statements is not diagnosed from
2528+ // typeCheckStmt() as usual.
2529+ diagnoseStmtAvailability (S, Where.getDeclContext (),
2530+ /* walkRecursively=*/ true );
2531+ return std::make_pair (false , S);
2532+ }
2533+
25132534 bool diagnoseDeclRefAvailability (ConcreteDeclRef declRef, SourceRange R,
25142535 const ApplyExpr *call = nullptr ,
25152536 DeclAvailabilityFlags flags = None) const ;
@@ -2768,11 +2789,11 @@ swift::diagnoseDeclAvailability(const ValueDecl *D,
27682789 && isa<ProtocolDecl>(D))
27692790 return false ;
27702791
2771- auto *DC = Where.getDeclContext ();
2772-
27732792 // Diagnose (and possibly signal) for potential unavailability
2774- auto maybeUnavail = TypeChecker::checkDeclarationAvailability (D, R. Start , DC );
2793+ auto maybeUnavail = TypeChecker::checkDeclarationAvailability (D, Where );
27752794 if (maybeUnavail.hasValue ()) {
2795+ auto *DC = Where.getDeclContext ();
2796+
27762797 if (accessor) {
27772798 bool forInout = Flags.contains (DeclAvailabilityFlag::ForInout);
27782799 TypeChecker::diagnosePotentialAccessorUnavailability (accessor, R, DC,
@@ -2943,7 +2964,7 @@ ExprAvailabilityWalker::diagnoseMemoryLayoutMigration(const ValueDecl *D,
29432964
29442965// / Diagnose uses of unavailable declarations.
29452966void swift::diagnoseExprAvailability (const Expr *E, DeclContext *DC) {
2946- auto where = ExportContext::forFunctionBody (DC);
2967+ auto where = ExportContext::forFunctionBody (DC, E-> getStartLoc () );
29472968 if (where.isImplicit ())
29482969 return ;
29492970 ExprAvailabilityWalker walker (where);
@@ -2953,50 +2974,51 @@ void swift::diagnoseExprAvailability(const Expr *E, DeclContext *DC) {
29532974namespace {
29542975
29552976class StmtAvailabilityWalker : public ASTWalker {
2956- ExportContext Where;
2977+ DeclContext *DC;
2978+ bool WalkRecursively;
29572979
29582980public:
2959- explicit StmtAvailabilityWalker (ExportContext where )
2960- : Where(where ) {}
2981+ explicit StmtAvailabilityWalker (DeclContext *dc, bool walkRecursively )
2982+ : DC(dc), WalkRecursively(walkRecursively ) {}
29612983
2962- // / We'll visit each element of a BraceStmt individually.
29632984 std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
2964- if (isa<BraceStmt>(S))
2985+ if (!WalkRecursively && isa<BraceStmt>(S))
29652986 return std::make_pair (false , S);
29662987
29672988 return std::make_pair (true , S);
29682989 }
29692990
2970- // / We'll visit the expression from performSyntacticExprDiagnostics().
29712991 std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
2992+ if (WalkRecursively)
2993+ diagnoseExprAvailability (E, DC);
29722994 return std::make_pair (false , E);
29732995 }
29742996
29752997 bool walkToTypeReprPre (TypeRepr *T) override {
2976- diagnoseTypeReprAvailability (T, Where);
2998+ auto where = ExportContext::forFunctionBody (DC, T->getStartLoc ());
2999+ diagnoseTypeReprAvailability (T, where);
29773000 return false ;
29783001 }
29793002
29803003 std::pair<bool , Pattern *> walkToPatternPre (Pattern *P) override {
2981- if (auto *IP = dyn_cast<IsPattern>(P))
2982- diagnoseTypeAvailability (IP->getCastType (), P->getLoc (), Where);
3004+ if (auto *IP = dyn_cast<IsPattern>(P)) {
3005+ auto where = ExportContext::forFunctionBody (DC, P->getLoc ());
3006+ diagnoseTypeAvailability (IP->getCastType (), P->getLoc (), where);
3007+ }
29833008
29843009 return std::make_pair (true , P);
29853010 }
29863011};
29873012
29883013}
29893014
2990- void swift::diagnoseStmtAvailability (const Stmt *S, DeclContext *DC) {
3015+ void swift::diagnoseStmtAvailability (const Stmt *S, DeclContext *DC,
3016+ bool walkRecursively) {
29913017 // We'll visit the individual statements when we check them.
2992- if (isa<BraceStmt>(S))
2993- return ;
2994-
2995- auto where = ExportContext::forFunctionBody (DC);
2996- if (where.isImplicit ())
3018+ if (!walkRecursively && isa<BraceStmt>(S))
29973019 return ;
29983020
2999- StmtAvailabilityWalker walker (where );
3021+ StmtAvailabilityWalker walker (DC, walkRecursively );
30003022 const_cast <Stmt*>(S)->walk (walker);
30013023}
30023024
0 commit comments