summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-check-expr.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2022-06-01 17:37:07 -0700
committerGitHub <noreply@github.com>2022-06-01 17:37:07 -0700
commit17e3b88b541ed7f45d575f0f9caaa808cd0a6619 (patch)
treeefacd5d4bf6381a5adf8055daa28f91ddc048a76 /source/slang/slang-check-expr.cpp
parentfa10f7dc23f8b93c0f9ef3fb5477871a20aaa974 (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.cpp62
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;