@@ -3560,7 +3560,7 @@ bool diagnoseExplicitUnavailability(
3560
3560
}
3561
3561
3562
3562
namespace {
3563
- class ExprAvailabilityWalker : public ASTWalker {
3563
+ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
3564
3564
// / Models how member references will translate to accessor usage. This is
3565
3565
// / used to diagnose the availability of individual accessors that may be
3566
3566
// / called by the expression being checked.
@@ -3595,11 +3595,6 @@ class ExprAvailabilityWalker : public ASTWalker {
3595
3595
explicit ExprAvailabilityWalker (const ExportContext &Where)
3596
3596
: Context(Where.getDeclContext()->getASTContext()), Where(Where) {}
3597
3597
3598
- MacroWalking getMacroWalkingBehavior () const override {
3599
- // Expanded source should be type checked and diagnosed separately.
3600
- return MacroWalking::Arguments;
3601
- }
3602
-
3603
3598
PreWalkAction walkToArgumentPre (const Argument &Arg) override {
3604
3599
// Arguments should be walked in their own member access context which
3605
3600
// starts out read-only by default.
@@ -3720,10 +3715,8 @@ class ExprAvailabilityWalker : public ASTWalker {
3720
3715
CE->getResultType (), E->getLoc (), Where);
3721
3716
}
3722
3717
if (AbstractClosureExpr *closure = dyn_cast<AbstractClosureExpr>(E)) {
3723
- if (shouldWalkIntoClosure (closure)) {
3724
- walkAbstractClosure (closure);
3725
- return Action::SkipChildren (E);
3726
- }
3718
+ walkAbstractClosure (closure);
3719
+ return Action::SkipChildren (E);
3727
3720
}
3728
3721
3729
3722
if (auto CE = dyn_cast<ExplicitCastExpr>(E)) {
@@ -3789,13 +3782,22 @@ class ExprAvailabilityWalker : public ASTWalker {
3789
3782
}
3790
3783
3791
3784
PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
3792
-
3793
- // We end up here when checking the output of the result builder transform,
3794
- // which includes closures that are not "separately typechecked" and yet
3795
- // contain statements and declarations. We need to walk them recursively,
3796
- // since these availability for these statements is not diagnosed from
3797
- // typeCheckStmt() as usual.
3798
- diagnoseStmtAvailability (S, Where.getDeclContext (), /* walkRecursively=*/ true );
3785
+ // We need to recursively call diagnoseExprAvailability for any
3786
+ // sub-expressions in the statement since the availability context may
3787
+ // differ, e.g for things like `guard #available(...)`.
3788
+ class StmtRecurseWalker : public BaseDiagnosticWalker {
3789
+ DeclContext *DC;
3790
+
3791
+ public:
3792
+ StmtRecurseWalker (DeclContext *DC) : DC(DC) {}
3793
+
3794
+ PreWalkResult<Expr *> walkToExprPre (Expr *E) override {
3795
+ diagnoseExprAvailability (E, DC);
3796
+ return Action::SkipNode (E);
3797
+ }
3798
+ };
3799
+ StmtRecurseWalker W (Where.getDeclContext ());
3800
+ S->walk (W);
3799
3801
return Action::SkipNode (S);
3800
3802
}
3801
3803
@@ -3942,10 +3944,6 @@ class ExprAvailabilityWalker : public ASTWalker {
3942
3944
walkInContext (E->getSubExpr (), accessContext);
3943
3945
}
3944
3946
3945
- bool shouldWalkIntoClosure (AbstractClosureExpr *closure) const {
3946
- return true ;
3947
- }
3948
-
3949
3947
// / Walk an abstract closure expression, checking for availability
3950
3948
void walkAbstractClosure (AbstractClosureExpr *closure) {
3951
3949
// Do the walk with the closure set as the decl context of the 'where'
@@ -4395,26 +4393,29 @@ void swift::diagnoseExprAvailability(const Expr *E, DeclContext *DC) {
4395
4393
namespace {
4396
4394
4397
4395
class StmtAvailabilityWalker : public BaseDiagnosticWalker {
4396
+ const Stmt *TopLevelStmt;
4398
4397
DeclContext *DC;
4399
- bool WalkRecursively;
4400
4398
4401
4399
public:
4402
- explicit StmtAvailabilityWalker (DeclContext *dc, bool walkRecursively )
4403
- : DC(dc ), WalkRecursively(walkRecursively ) {}
4400
+ explicit StmtAvailabilityWalker (const Stmt *S, DeclContext *dc )
4401
+ : TopLevelStmt(S ), DC(dc ) {}
4404
4402
4405
4403
PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
4406
- if (!WalkRecursively && isa<BraceStmt>(S))
4407
- return Action::SkipNode (S);
4408
-
4409
- return Action::Continue (S);
4404
+ // `diagnoseStmtAvailability` is called for every statement, so we don't
4405
+ // want to walk into any nested statements.
4406
+ return Action::VisitNodeIf (S == TopLevelStmt, S);
4410
4407
}
4411
4408
4412
4409
PreWalkResult<Expr *> walkToExprPre (Expr *E) override {
4413
- if (WalkRecursively)
4414
- diagnoseExprAvailability (E, DC);
4410
+ // Handled by ExprAvailabilityWalker.
4415
4411
return Action::SkipNode (E);
4416
4412
}
4417
4413
4414
+ PreWalkAction walkToDeclPre (Decl *D) override {
4415
+ // Handled by DeclAvailabilityChecker.
4416
+ return Action::SkipNode ();
4417
+ }
4418
+
4418
4419
PreWalkAction walkToTypeReprPre (TypeRepr *T) override {
4419
4420
auto where = ExportContext::forFunctionBody (DC, T->getStartLoc ());
4420
4421
diagnoseTypeReprAvailability (T, where);
@@ -4433,13 +4434,8 @@ class StmtAvailabilityWalker : public BaseDiagnosticWalker {
4433
4434
};
4434
4435
}
4435
4436
4436
- void swift::diagnoseStmtAvailability (const Stmt *S, DeclContext *DC,
4437
- bool walkRecursively) {
4438
- // We'll visit the individual statements when we check them.
4439
- if (!walkRecursively && isa<BraceStmt>(S))
4440
- return ;
4441
-
4442
- StmtAvailabilityWalker walker (DC, walkRecursively);
4437
+ void swift::diagnoseStmtAvailability (const Stmt *S, DeclContext *DC) {
4438
+ StmtAvailabilityWalker walker (S, DC);
4443
4439
const_cast <Stmt*>(S)->walk (walker);
4444
4440
}
4445
4441
0 commit comments