37
37
#include " llvm/Support/SaveAndRestore.h"
38
38
using namespace swift ;
39
39
40
- ExportContext::ExportContext (DeclContext *DC, FragileFunctionKind kind,
40
+ ExportContext::ExportContext (DeclContext *DC,
41
+ AvailabilityContext runningOSVersion,
42
+ FragileFunctionKind kind,
41
43
bool spi, bool exported, bool implicit, bool deprecated,
42
44
Optional<PlatformKind> unavailablePlatformKind)
43
- : DC(DC), FragileKind(kind) {
45
+ : DC(DC), RunningOSVersion(runningOSVersion), FragileKind(kind) {
44
46
SPI = spi;
45
47
Exported = exported;
46
48
Implicit = implicit;
@@ -169,7 +171,10 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
169
171
170
172
auto *DC = D->getInnermostDeclContext ();
171
173
auto fragileKind = DC->getFragileFunctionKind ();
172
-
174
+ auto runningOSVersion =
175
+ (Ctx.LangOpts .DisableAvailabilityChecking
176
+ ? AvailabilityContext::alwaysAvailable ()
177
+ : TypeChecker::overApproximateAvailabilityAtLocation (D->getEndLoc (), DC));
173
178
bool spi = false ;
174
179
bool implicit = false ;
175
180
bool deprecated = false ;
@@ -185,14 +190,19 @@ ExportContext ExportContext::forDeclSignature(Decl *D) {
185
190
186
191
bool exported = ::isExported (D);
187
192
188
- return ExportContext (DC, fragileKind, spi, exported, implicit, deprecated,
193
+ return ExportContext (DC, runningOSVersion, fragileKind,
194
+ spi, exported, implicit, deprecated,
189
195
unavailablePlatformKind);
190
196
}
191
197
192
- ExportContext ExportContext::forFunctionBody (DeclContext *DC) {
198
+ ExportContext ExportContext::forFunctionBody (DeclContext *DC, SourceLoc loc ) {
193
199
auto &Ctx = DC->getASTContext ();
194
200
195
201
auto fragileKind = DC->getFragileFunctionKind ();
202
+ auto runningOSVersion =
203
+ (Ctx.LangOpts .DisableAvailabilityChecking
204
+ ? AvailabilityContext::alwaysAvailable ()
205
+ : TypeChecker::overApproximateAvailabilityAtLocation (loc, DC));
196
206
197
207
bool spi = false ;
198
208
bool implicit = false ;
@@ -207,7 +217,8 @@ ExportContext ExportContext::forFunctionBody(DeclContext *DC) {
207
217
208
218
bool exported = false ;
209
219
210
- return ExportContext (DC, fragileKind, spi, exported, implicit, deprecated,
220
+ return ExportContext (DC, runningOSVersion, fragileKind,
221
+ spi, exported, implicit, deprecated,
211
222
unavailablePlatformKind);
212
223
}
213
224
@@ -915,8 +926,8 @@ TypeChecker::overApproximateAvailabilityAtLocation(SourceLoc loc,
915
926
}
916
927
917
928
Optional<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 ();
920
931
ASTContext &Context = referenceDC->getASTContext ();
921
932
if (Context.LangOpts .DisableAvailabilityChecking ) {
922
933
return None;
@@ -929,7 +940,7 @@ TypeChecker::checkDeclarationAvailability(const Decl *D, SourceLoc referenceLoc,
929
940
}
930
941
931
942
AvailabilityContext runningOSOverApprox =
932
- overApproximateAvailabilityAtLocation (referenceLoc, referenceDC );
943
+ where. getAvailabilityContext ( );
933
944
934
945
AvailabilityContext safeRangeUnderApprox{
935
946
AvailabilityInference::availableRange (D, Context)};
@@ -2073,8 +2084,7 @@ void TypeChecker::diagnoseIfDeprecated(SourceRange ReferenceRange,
2073
2084
auto *ReferenceDC = Where.getDeclContext ();
2074
2085
auto &Context = ReferenceDC->getASTContext ();
2075
2086
if (!Context.LangOpts .DisableAvailabilityChecking ) {
2076
- AvailabilityContext RunningOSVersions =
2077
- overApproximateAvailabilityAtLocation (ReferenceRange.Start ,ReferenceDC);
2087
+ AvailabilityContext RunningOSVersions = Where.getAvailabilityContext ();
2078
2088
if (RunningOSVersions.isKnownUnreachable ()) {
2079
2089
// Suppress a deprecation warning if the availability checking machinery
2080
2090
// thinks the reference program location will not execute on any
@@ -2510,6 +2520,17 @@ class ExprAvailabilityWalker : public ASTWalker {
2510
2520
return E;
2511
2521
}
2512
2522
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
+
2513
2534
bool diagnoseDeclRefAvailability (ConcreteDeclRef declRef, SourceRange R,
2514
2535
const ApplyExpr *call = nullptr ,
2515
2536
DeclAvailabilityFlags flags = None) const ;
@@ -2768,11 +2789,11 @@ swift::diagnoseDeclAvailability(const ValueDecl *D,
2768
2789
&& isa<ProtocolDecl>(D))
2769
2790
return false ;
2770
2791
2771
- auto *DC = Where.getDeclContext ();
2772
-
2773
2792
// Diagnose (and possibly signal) for potential unavailability
2774
- auto maybeUnavail = TypeChecker::checkDeclarationAvailability (D, R. Start , DC );
2793
+ auto maybeUnavail = TypeChecker::checkDeclarationAvailability (D, Where );
2775
2794
if (maybeUnavail.hasValue ()) {
2795
+ auto *DC = Where.getDeclContext ();
2796
+
2776
2797
if (accessor) {
2777
2798
bool forInout = Flags.contains (DeclAvailabilityFlag::ForInout);
2778
2799
TypeChecker::diagnosePotentialAccessorUnavailability (accessor, R, DC,
@@ -2943,7 +2964,7 @@ ExprAvailabilityWalker::diagnoseMemoryLayoutMigration(const ValueDecl *D,
2943
2964
2944
2965
// / Diagnose uses of unavailable declarations.
2945
2966
void swift::diagnoseExprAvailability (const Expr *E, DeclContext *DC) {
2946
- auto where = ExportContext::forFunctionBody (DC);
2967
+ auto where = ExportContext::forFunctionBody (DC, E-> getStartLoc () );
2947
2968
if (where.isImplicit ())
2948
2969
return ;
2949
2970
ExprAvailabilityWalker walker (where);
@@ -2953,50 +2974,51 @@ void swift::diagnoseExprAvailability(const Expr *E, DeclContext *DC) {
2953
2974
namespace {
2954
2975
2955
2976
class StmtAvailabilityWalker : public ASTWalker {
2956
- ExportContext Where;
2977
+ DeclContext *DC;
2978
+ bool WalkRecursively;
2957
2979
2958
2980
public:
2959
- explicit StmtAvailabilityWalker (ExportContext where )
2960
- : Where(where ) {}
2981
+ explicit StmtAvailabilityWalker (DeclContext *dc, bool walkRecursively )
2982
+ : DC(dc), WalkRecursively(walkRecursively ) {}
2961
2983
2962
- // / We'll visit each element of a BraceStmt individually.
2963
2984
std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
2964
- if (isa<BraceStmt>(S))
2985
+ if (!WalkRecursively && isa<BraceStmt>(S))
2965
2986
return std::make_pair (false , S);
2966
2987
2967
2988
return std::make_pair (true , S);
2968
2989
}
2969
2990
2970
- // / We'll visit the expression from performSyntacticExprDiagnostics().
2971
2991
std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
2992
+ if (WalkRecursively)
2993
+ diagnoseExprAvailability (E, DC);
2972
2994
return std::make_pair (false , E);
2973
2995
}
2974
2996
2975
2997
bool walkToTypeReprPre (TypeRepr *T) override {
2976
- diagnoseTypeReprAvailability (T, Where);
2998
+ auto where = ExportContext::forFunctionBody (DC, T->getStartLoc ());
2999
+ diagnoseTypeReprAvailability (T, where);
2977
3000
return false ;
2978
3001
}
2979
3002
2980
3003
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
+ }
2983
3008
2984
3009
return std::make_pair (true , P);
2985
3010
}
2986
3011
};
2987
3012
2988
3013
}
2989
3014
2990
- void swift::diagnoseStmtAvailability (const Stmt *S, DeclContext *DC) {
3015
+ void swift::diagnoseStmtAvailability (const Stmt *S, DeclContext *DC,
3016
+ bool walkRecursively) {
2991
3017
// 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))
2997
3019
return ;
2998
3020
2999
- StmtAvailabilityWalker walker (where );
3021
+ StmtAvailabilityWalker walker (DC, walkRecursively );
3000
3022
const_cast <Stmt*>(S)->walk (walker);
3001
3023
}
3002
3024
0 commit comments