@@ -3560,7 +3560,7 @@ bool diagnoseExplicitUnavailability(
35603560}
35613561
35623562namespace {
3563- class ExprAvailabilityWalker : public ASTWalker {
3563+ class ExprAvailabilityWalker : public BaseDiagnosticWalker {
35643564 // / Models how member references will translate to accessor usage. This is
35653565 // / used to diagnose the availability of individual accessors that may be
35663566 // / called by the expression being checked.
@@ -3595,11 +3595,6 @@ class ExprAvailabilityWalker : public ASTWalker {
35953595 explicit ExprAvailabilityWalker (const ExportContext &Where)
35963596 : Context(Where.getDeclContext()->getASTContext()), Where(Where) {}
35973597
3598- MacroWalking getMacroWalkingBehavior () const override {
3599- // Expanded source should be type checked and diagnosed separately.
3600- return MacroWalking::Arguments;
3601- }
3602-
36033598 PreWalkAction walkToArgumentPre (const Argument &Arg) override {
36043599 // Arguments should be walked in their own member access context which
36053600 // starts out read-only by default.
@@ -3720,10 +3715,8 @@ class ExprAvailabilityWalker : public ASTWalker {
37203715 CE->getResultType (), E->getLoc (), Where);
37213716 }
37223717 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);
37273720 }
37283721
37293722 if (auto CE = dyn_cast<ExplicitCastExpr>(E)) {
@@ -3789,13 +3782,22 @@ class ExprAvailabilityWalker : public ASTWalker {
37893782 }
37903783
37913784 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);
37993801 return Action::SkipNode (S);
38003802 }
38013803
@@ -3942,10 +3944,6 @@ class ExprAvailabilityWalker : public ASTWalker {
39423944 walkInContext (E->getSubExpr (), accessContext);
39433945 }
39443946
3945- bool shouldWalkIntoClosure (AbstractClosureExpr *closure) const {
3946- return true ;
3947- }
3948-
39493947 // / Walk an abstract closure expression, checking for availability
39503948 void walkAbstractClosure (AbstractClosureExpr *closure) {
39513949 // 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) {
43954393namespace {
43964394
43974395class StmtAvailabilityWalker : public BaseDiagnosticWalker {
4396+ const Stmt *TopLevelStmt;
43984397 DeclContext *DC;
4399- bool WalkRecursively;
44004398
44014399public:
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 ) {}
44044402
44054403 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);
44104407 }
44114408
44124409 PreWalkResult<Expr *> walkToExprPre (Expr *E) override {
4413- if (WalkRecursively)
4414- diagnoseExprAvailability (E, DC);
4410+ // Handled by ExprAvailabilityWalker.
44154411 return Action::SkipNode (E);
44164412 }
44174413
4414+ PreWalkAction walkToDeclPre (Decl *D) override {
4415+ // Handled by DeclAvailabilityChecker.
4416+ return Action::SkipNode ();
4417+ }
4418+
44184419 PreWalkAction walkToTypeReprPre (TypeRepr *T) override {
44194420 auto where = ExportContext::forFunctionBody (DC, T->getStartLoc ());
44204421 diagnoseTypeReprAvailability (T, where);
@@ -4433,13 +4434,8 @@ class StmtAvailabilityWalker : public BaseDiagnosticWalker {
44334434};
44344435}
44354436
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);
44434439 const_cast <Stmt*>(S)->walk (walker);
44444440}
44454441
0 commit comments