Skip to content

Commit 15fcbc1

Browse files
committed
[TypeChecker] Factor out StmtChecker::typeCheckASTNode()
For type checking single element in brace statements.
1 parent 0210755 commit 15fcbc1

File tree

1 file changed

+54
-46
lines changed

1 file changed

+54
-46
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 54 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
408408
S->walk(ContextualizeClosures(DC));
409409
return HadError;
410410
}
411+
412+
void typeCheckASTNode(ASTNode &node);
411413

412414
//===--------------------------------------------------------------------===//
413415
// Visit Methods.
@@ -1538,6 +1540,57 @@ void TypeChecker::checkIgnoredExpr(Expr *E) {
15381540
.highlight(valueE->getSourceRange());
15391541
}
15401542

1543+
void StmtChecker::typeCheckASTNode(ASTNode &node) {
1544+
// Type check the expression
1545+
if (auto *E = node.dyn_cast<Expr *>()) {
1546+
auto &ctx = DC->getASTContext();
1547+
1548+
TypeCheckExprOptions options = TypeCheckExprFlags::IsExprStmt;
1549+
bool isDiscarded =
1550+
(!ctx.LangOpts.Playground && !ctx.LangOpts.DebuggerSupport);
1551+
if (isDiscarded)
1552+
options |= TypeCheckExprFlags::IsDiscarded;
1553+
if (TargetTypeCheckLoc.isValid())
1554+
options |= TypeCheckExprFlags::AllowUnresolvedTypeVariables;
1555+
1556+
auto resultTy =
1557+
TypeChecker::typeCheckExpression(E, DC, Type(), CTP_Unused, options);
1558+
1559+
// If a closure expression is unused, the user might have intended to write
1560+
// "do { ... }".
1561+
auto *CE = dyn_cast<ClosureExpr>(E);
1562+
if (CE || isa<CaptureListExpr>(E)) {
1563+
ctx.Diags.diagnose(E->getLoc(), diag::expression_unused_closure);
1564+
1565+
if (CE && CE->hasAnonymousClosureVars() &&
1566+
CE->getParameters()->size() == 0) {
1567+
ctx.Diags.diagnose(CE->getStartLoc(), diag::brace_stmt_suggest_do)
1568+
.fixItInsert(CE->getStartLoc(), "do ");
1569+
}
1570+
} else if (isDiscarded && resultTy) {
1571+
TypeChecker::checkIgnoredExpr(E);
1572+
}
1573+
1574+
node = E;
1575+
return;
1576+
}
1577+
1578+
// Type check the statement.
1579+
if (auto *S = node.dyn_cast<Stmt *>()) {
1580+
typeCheckStmt(S);
1581+
node = S;
1582+
return;
1583+
}
1584+
1585+
// Type check the declaration.
1586+
if (auto *D = node.dyn_cast<Decl *>()) {
1587+
TypeChecker::typeCheckDecl(D);
1588+
return;
1589+
}
1590+
1591+
llvm_unreachable("Type checking null ASTNode");
1592+
}
1593+
15411594
Stmt *StmtChecker::visitBraceStmt(BraceStmt *BS) {
15421595
const SourceManager &SM = getASTContext().SourceMgr;
15431596

@@ -1569,52 +1622,7 @@ Stmt *StmtChecker::visitBraceStmt(BraceStmt *BS) {
15691622
continue;
15701623
}
15711624

1572-
if (auto *SubExpr = elem.dyn_cast<Expr*>()) {
1573-
// Type check the expression.
1574-
TypeCheckExprOptions options = TypeCheckExprFlags::IsExprStmt;
1575-
bool isDiscarded = (!getASTContext().LangOpts.Playground &&
1576-
!getASTContext().LangOpts.DebuggerSupport);
1577-
if (isDiscarded)
1578-
options |= TypeCheckExprFlags::IsDiscarded;
1579-
1580-
if (TargetTypeCheckLoc.isValid()) {
1581-
assert(DiagnosticSuppression::isEnabled(getASTContext().Diags) &&
1582-
"Diagnosing and AllowUnresolvedTypeVariables don't seem to mix");
1583-
options |= TypeCheckExprFlags::AllowUnresolvedTypeVariables;
1584-
}
1585-
1586-
auto resultTy =
1587-
TypeChecker::typeCheckExpression(SubExpr, DC, Type(),
1588-
CTP_Unused, options);
1589-
1590-
// If a closure expression is unused, the user might have intended
1591-
// to write "do { ... }".
1592-
auto *CE = dyn_cast<ClosureExpr>(SubExpr);
1593-
if (CE || isa<CaptureListExpr>(SubExpr)) {
1594-
getASTContext().Diags.diagnose(SubExpr->getLoc(),
1595-
diag::expression_unused_closure);
1596-
1597-
if (CE && CE->hasAnonymousClosureVars() &&
1598-
CE->getParameters()->size() == 0) {
1599-
getASTContext().Diags.diagnose(CE->getStartLoc(),
1600-
diag::brace_stmt_suggest_do)
1601-
.fixItInsert(CE->getStartLoc(), "do ");
1602-
}
1603-
} else if (isDiscarded && resultTy)
1604-
TypeChecker::checkIgnoredExpr(SubExpr);
1605-
1606-
elem = SubExpr;
1607-
continue;
1608-
}
1609-
1610-
if (auto *SubStmt = elem.dyn_cast<Stmt*>()) {
1611-
typeCheckStmt(SubStmt);
1612-
elem = SubStmt;
1613-
continue;
1614-
}
1615-
1616-
Decl *SubDecl = elem.get<Decl *>();
1617-
TypeChecker::typeCheckDecl(SubDecl);
1625+
typeCheckASTNode(elem);
16181626
}
16191627

16201628
return BS;

0 commit comments

Comments
 (0)