Skip to content

Commit 9a339d9

Browse files
committed
[Sema] Clean up diagnoseStmtAvailability a bit
The walker here is really doing 2 completely separate things, split it into 2 walkers. For ExprAvailabilityWalker, we just want to recursively continue walking looking for any sub-expressions to diagnose. For StmtAvailabilityWalker we only want to walk the top-level statement, and are only interested in any TypeReprs it has. This lets us get rid of the special handling for BraceStmt.
1 parent d2b298b commit 9a339d9

File tree

2 files changed

+32
-29
lines changed

2 files changed

+32
-29
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3790,13 +3790,22 @@ class ExprAvailabilityWalker : public ASTWalker {
37903790
}
37913791

37923792
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
3793-
3794-
// We end up here when checking the output of the result builder transform,
3795-
// which includes closures that are not "separately typechecked" and yet
3796-
// contain statements and declarations. We need to walk them recursively,
3797-
// since these availability for these statements is not diagnosed from
3798-
// typeCheckStmt() as usual.
3799-
diagnoseStmtAvailability(S, Where.getDeclContext(), /*walkRecursively=*/true);
3793+
// We need to recursively call diagnoseExprAvailability for any
3794+
// sub-expressions in the statement since the availability context may
3795+
// differ, e.g for things like `guard #available(...)`.
3796+
class StmtRecurseWalker : public BaseDiagnosticWalker {
3797+
DeclContext *DC;
3798+
3799+
public:
3800+
StmtRecurseWalker(DeclContext *DC) : DC(DC) {}
3801+
3802+
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
3803+
diagnoseExprAvailability(E, DC);
3804+
return Action::SkipNode(E);
3805+
}
3806+
};
3807+
StmtRecurseWalker W(Where.getDeclContext());
3808+
S->walk(W);
38003809
return Action::SkipNode(S);
38013810
}
38023811

@@ -4396,26 +4405,29 @@ void swift::diagnoseExprAvailability(const Expr *E, DeclContext *DC) {
43964405
namespace {
43974406

43984407
class StmtAvailabilityWalker : public BaseDiagnosticWalker {
4408+
const Stmt *TopLevelStmt;
43994409
DeclContext *DC;
4400-
bool WalkRecursively;
44014410

44024411
public:
4403-
explicit StmtAvailabilityWalker(DeclContext *dc, bool walkRecursively)
4404-
: DC(dc), WalkRecursively(walkRecursively) {}
4412+
explicit StmtAvailabilityWalker(const Stmt *S, DeclContext *dc)
4413+
: TopLevelStmt(S), DC(dc) {}
44054414

44064415
PreWalkResult<Stmt *> walkToStmtPre(Stmt *S) override {
4407-
if (!WalkRecursively && isa<BraceStmt>(S))
4408-
return Action::SkipNode(S);
4409-
4410-
return Action::Continue(S);
4416+
// `diagnoseStmtAvailability` is called for every statement, so we don't
4417+
// want to walk into any nested statements.
4418+
return Action::VisitNodeIf(S == TopLevelStmt, S);
44114419
}
44124420

44134421
PreWalkResult<Expr *> walkToExprPre(Expr *E) override {
4414-
if (WalkRecursively)
4415-
diagnoseExprAvailability(E, DC);
4422+
// Handled by ExprAvailabilityWalker.
44164423
return Action::SkipNode(E);
44174424
}
44184425

4426+
PreWalkAction walkToDeclPre(Decl *D) override {
4427+
// Handled by DeclAvailabilityChecker.
4428+
return Action::SkipNode();
4429+
}
4430+
44194431
PreWalkAction walkToTypeReprPre(TypeRepr *T) override {
44204432
auto where = ExportContext::forFunctionBody(DC, T->getStartLoc());
44214433
diagnoseTypeReprAvailability(T, where);
@@ -4434,13 +4446,8 @@ class StmtAvailabilityWalker : public BaseDiagnosticWalker {
44344446
};
44354447
}
44364448

4437-
void swift::diagnoseStmtAvailability(const Stmt *S, DeclContext *DC,
4438-
bool walkRecursively) {
4439-
// We'll visit the individual statements when we check them.
4440-
if (!walkRecursively && isa<BraceStmt>(S))
4441-
return;
4442-
4443-
StmtAvailabilityWalker walker(DC, walkRecursively);
4449+
void swift::diagnoseStmtAvailability(const Stmt *S, DeclContext *DC) {
4450+
StmtAvailabilityWalker walker(S, DC);
44444451
const_cast<Stmt*>(S)->walk(walker);
44454452
}
44464453

lib/Sema/TypeCheckAvailability.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,12 +211,8 @@ bool isExported(const Decl *D);
211211
void diagnoseExprAvailability(const Expr *E, DeclContext *DC);
212212

213213
/// Diagnose uses of unavailable declarations in statements (via patterns, etc)
214-
/// but not expressions, unless \p walkRecursively was specified.
215-
///
216-
/// \param walkRecursively Whether nested statements and expressions should
217-
/// be visited, too.
218-
void diagnoseStmtAvailability(const Stmt *S, DeclContext *DC,
219-
bool walkRecursively=false);
214+
/// but not expressions.
215+
void diagnoseStmtAvailability(const Stmt *S, DeclContext *DC);
220216

221217
/// Checks both a TypeRepr and a Type, but avoids emitting duplicate
222218
/// diagnostics by only checking the Type if the TypeRepr succeeded.

0 commit comments

Comments
 (0)