diff options
| author | Yong He <yonghe@outlook.com> | 2022-06-01 17:37:07 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-01 17:37:07 -0700 |
| commit | 17e3b88b541ed7f45d575f0f9caaa808cd0a6619 (patch) | |
| tree | efacd5d4bf6381a5adf8055daa28f91ddc048a76 /source/slang/slang-check-expr.cpp | |
| parent | fa10f7dc23f8b93c0f9ef3fb5477871a20aaa974 (diff) | |
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 <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-check-expr.cpp')
| -rw-r--r-- | source/slang/slang-check-expr.cpp | 62 |
1 files changed, 62 insertions, 0 deletions
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<FuncType>(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<ErrorType>(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<InvokeExpr>(expr->base)) + { + getSink()->diagnose(expr, Diagnostics::tryClauseMustApplyToInvokeExpr); + return expr; + } + auto base = as<InvokeExpr>(expr->base); + if (auto callee = as<DeclRefExpr>(base->functionExpr)) + { + if (auto funcCallee = as<FuncDecl>(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; |
