From 1b82501dd0c74347cda4a2c7fe5a84fd610bb485 Mon Sep 17 00:00:00 2001 From: Julius Ikkala Date: Mon, 7 Apr 2025 06:08:29 +0300 Subject: Add defer statement (#6619) --- source/slang/slang-check-stmt.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'source/slang/slang-check-stmt.cpp') diff --git a/source/slang/slang-check-stmt.cpp b/source/slang/slang-check-stmt.cpp index db6f00d23..c85eb7593 100644 --- a/source/slang/slang-check-stmt.cpp +++ b/source/slang/slang-check-stmt.cpp @@ -119,9 +119,10 @@ void SemanticsStmtVisitor::checkStmt(Stmt* stmt) } template -T* SemanticsStmtVisitor::FindOuterStmt() +T* SemanticsStmtVisitor::FindOuterStmt(Stmt* searchUntil) { - for (auto outerStmtInfo = m_outerStmts; outerStmtInfo; outerStmtInfo = outerStmtInfo->next) + for (auto outerStmtInfo = m_outerStmts; outerStmtInfo && outerStmtInfo->stmt != searchUntil; + outerStmtInfo = outerStmtInfo->next) { auto outerStmt = outerStmtInfo->stmt; auto found = as(outerStmt); @@ -178,6 +179,14 @@ void SemanticsStmtVisitor::visitBreakStmt(BreakStmt* stmt) getSink()->diagnose(stmt, Diagnostics::breakOutsideLoop); } } + + // If there is a defer statement before the breakable statement, it's + // illegal. + if (FindOuterStmt(targetStmt)) + { + getSink()->diagnose(stmt, Diagnostics::breakInsideDefer); + } + stmt->parentStmt = targetStmt; } @@ -188,6 +197,11 @@ void SemanticsStmtVisitor::visitContinueStmt(ContinueStmt* stmt) { getSink()->diagnose(stmt, Diagnostics::continueOutsideLoop); } + + if (FindOuterStmt(outer)) + { + getSink()->diagnose(stmt, Diagnostics::continueInsideDefer); + } stmt->parentStmt = outer; } @@ -497,6 +511,11 @@ void SemanticsStmtVisitor::visitReturnStmt(ReturnStmt* stmt) } } } + + if (FindOuterStmt()) + { + getSink()->diagnose(stmt, Diagnostics::returnInsideDefer); + } } void SemanticsStmtVisitor::visitWhileStmt(WhileStmt* stmt) @@ -508,6 +527,12 @@ void SemanticsStmtVisitor::visitWhileStmt(WhileStmt* stmt) checkLoopInDifferentiableFunc(stmt); } +void SemanticsStmtVisitor::visitDeferStmt(DeferStmt* stmt) +{ + WithOuterStmt subContext(this, stmt); + subContext.checkStmt(stmt->statement); +} + void SemanticsStmtVisitor::visitExpressionStmt(ExpressionStmt* stmt) { stmt->expression = CheckExpr(stmt->expression); -- cgit v1.2.3