summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-stmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-check-stmt.cpp')
-rw-r--r--source/slang/slang-check-stmt.cpp54
1 files changed, 49 insertions, 5 deletions
diff --git a/source/slang/slang-check-stmt.cpp b/source/slang/slang-check-stmt.cpp
index b68465087..729b24d35 100644
--- a/source/slang/slang-check-stmt.cpp
+++ b/source/slang/slang-check-stmt.cpp
@@ -239,6 +239,47 @@ namespace Slang
subContext.checkStmt(stmt->body);
}
+ void SemanticsStmtVisitor::validateCaseStmts(SwitchStmt* stmt, DiagnosticSink* sink)
+ {
+ auto blockStmt = as<BlockStmt>(stmt->body);
+ if (!blockStmt)
+ return;
+
+ auto seqStmt = as<SeqStmt>(blockStmt->body);
+ if (!seqStmt)
+ return;
+
+ bool hasDefaultStmt = false;
+ HashSet<Val*> caseStmtVals;
+ for (auto& sStmt : seqStmt->stmts)
+ {
+ if (auto caseStmt = as<CaseStmt>(sStmt))
+ {
+ // check that all case tags are unique
+ if (caseStmt->exprVal)
+ {
+ // exprVal contains the constant folded expr, that is checked for
+ // uniqueness within the scope of the switch statement.
+ if (!caseStmtVals.add(caseStmt->exprVal))
+ {
+ sink->diagnose(sStmt, Diagnostics::switchDuplicateCases);
+ return;
+ }
+ }
+ }
+ else if (auto defaultStmt = as<DefaultStmt>(sStmt))
+ {
+ // check that there is at most one `default` clause
+ if (hasDefaultStmt)
+ {
+ sink->diagnose(sStmt, Diagnostics::switchMultipleDefault);
+ return;
+ }
+ hasDefaultStmt = true;
+ }
+ }
+ }
+
void SemanticsStmtVisitor::visitSwitchStmt(SwitchStmt* stmt)
{
WithOuterStmt subContext(this, stmt);
@@ -247,16 +288,18 @@ namespace Slang
stmt->condition = CheckExpr(stmt->condition);
subContext.checkStmt(stmt->body);
- // TODO(tfoley): need to check that all case tags are unique
-
- // TODO(tfoley): check that there is at most one `default` clause
+ // check the case value exits within the switch
+ validateCaseStmts(stmt, getSink());
}
void SemanticsStmtVisitor::visitCaseStmt(CaseStmt* stmt)
{
- // TODO(tfoley): Need to coerce to type being switch on,
- // and ensure that value is a compile-time constant
auto expr = CheckExpr(stmt->expr);
+
+ // coerce to type being switch on, and ensure that value is a compile-time constant
+ // The Vals in the AST are pointer-unique, making them easy to check for duplicates
+ // by addeing them to a HashSet.
+ auto exprVal = tryConstantFoldExpr(expr, ConstantFoldingKind::CompileTime, nullptr);
auto switchStmt = FindOuterStmt<SwitchStmt>();
if (!switchStmt)
@@ -270,6 +313,7 @@ namespace Slang
}
stmt->expr = expr;
+ stmt->exprVal = exprVal;
stmt->parentStmt = switchStmt;
}