From 17e3b88b541ed7f45d575f0f9caaa808cd0a6619 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 1 Jun 2022 17:37:07 -0700 Subject: New language feature: basic error handling. (#2253) * New language feature: basic error handling. * Fix. * Fix `tryCall` encoding according to code review. Co-authored-by: Yong He --- source/slang/slang-check-expr.cpp | 62 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'source/slang/slang-check-expr.cpp') diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index 317ab6a1a..4b29de1bf 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -1337,6 +1337,15 @@ namespace Slang // if this is still an invoke expression, test arguments passed to inout/out parameter are LValues if(auto funcType = as(invoke->functionExpr->type)) { + if (!funcType->errorType->equals(m_astBuilder->getVoidType())) + { + // If the callee throws, make sure we are inside a try clause. + if (m_enclosingTryClauseType == TryClauseType::None) + { + getSink()->diagnose(invoke, Diagnostics::mustUseTryClauseToCallAThrowFunc); + } + } + Index paramCount = funcType->getParamCount(); for (Index pp = 0; pp < paramCount; ++pp) { @@ -1529,6 +1538,59 @@ namespace Slang return CheckInvokeExprWithCheckedOperands(expr); } + Expr* SemanticsExprVisitor::visitTryExpr(TryExpr* expr) + { + auto prevTryClauseType = expr->tryClauseType; + m_enclosingTryClauseType = expr->tryClauseType; + expr->base = CheckTerm(expr->base); + m_enclosingTryClauseType = prevTryClauseType; + expr->type = expr->base->type; + if (as(expr->type)) + return expr; + + auto parentFunc = this->m_parentFunc; + // TODO: check if the try clause is caught. + // For now we assume all `try`s are not caught (because we don't have catch yet). + if (!parentFunc) + { + getSink()->diagnose(expr, Diagnostics::uncaughtTryCallInNonThrowFunc); + return expr; + } + if (parentFunc->errorType->equals(m_astBuilder->getVoidType())) + { + getSink()->diagnose(expr, Diagnostics::uncaughtTryCallInNonThrowFunc); + return expr; + } + if (!as(expr->base)) + { + getSink()->diagnose(expr, Diagnostics::tryClauseMustApplyToInvokeExpr); + return expr; + } + auto base = as(expr->base); + if (auto callee = as(base->functionExpr)) + { + if (auto funcCallee = as(callee->declRef.getDecl())) + { + if (funcCallee->errorType->equals(m_astBuilder->getVoidType())) + { + getSink()->diagnose(expr, Diagnostics::tryInvokeCalleeShouldThrow, callee->declRef); + } + if (!parentFunc->errorType->equals(funcCallee->errorType)) + { + getSink()->diagnose( + expr, + Diagnostics::errorTypeOfCalleeIncompatibleWithCaller, + callee->declRef, + funcCallee->errorType, + parentFunc->errorType); + } + return expr; + } + } + getSink()->diagnose(expr, Diagnostics::calleeOfTryCallMustBeFunc); + return expr; + } + Expr* SemanticsVisitor::MaybeDereference(Expr* inExpr) { Expr* expr = inExpr; -- cgit v1.2.3