aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-25 06:34:22 +0200
committerlemon <lsof@mailbox.org>2022-08-25 06:34:22 +0200
commita39378db8ce05f8ab45b5ae0f3252c0a5322fd70 (patch)
tree06471804911a038529bb00e9b9cd0edee0dee3eb
parenta004d0f4033dab74a237d598c493228a7d107014 (diff)
switch check
-rw-r--r--src/parse.cff23
-rw-r--r--src/set.hff6
-rw-r--r--vgcore.7962bin0 -> 6991872 bytes
3 files changed, 29 insertions, 0 deletions
diff --git a/src/parse.cff b/src/parse.cff
index d0c3da7..2611906 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -2176,6 +2176,13 @@ fn pstiswitch(P *Parser, loc Loc, ex Expr) Stmt {
let cs Vec<ISwitchCase> = {};
let f Block = {};
let elsep = #f;
+
+ let seen Map<i64, Loc, struct {
+ fn hash(x i64) u32 { return x; }
+ fn eq(a i64, b i64) bool { return a == b;}
+ }> = {};
+ defer seen->clear();
+
while !lexmatch(P, &tok, '}') {
lexexpect(P, :kw_case);
if lexmatch(P, &tok, :kw_else) {
@@ -2196,6 +2203,10 @@ fn pstiswitch(P *Parser, loc Loc, ex Expr) Stmt {
if !typematchestarg(ex.ty, e.ty) {
err(P, e.loc, "bad case expression (%t, expected %t)", e.ty, ex.ty);
}
+ if seen->get(e.u.IntLit.i) {
+ err(P, e.loc, "duplicate case expression (previously seen at %l)", *seen->get(e.u.IntLit.i));
+ }
+ seen->put(e.u.IntLit.i, e.loc);
es->push(e);
if !lexmatch(P, #null, ',') {
lexexpect(P, ';');
@@ -2214,6 +2225,12 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt {
let f Block = {};
let elsep = #f;
+ let seen Map<int, Loc, struct {
+ fn hash(x int) u32 { return x; }
+ fn eq(a int, b int) bool { return a == b;}
+ }> = {};
+ defer seen->clear();
+
while !lexmatch(P, &tok, '}') {
let c EUSwitchCase = {};
lexexpect(P, :kw_case);
@@ -2231,6 +2248,12 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt {
fatal(P, tok.loc, "%t has no such variant %qT", test.ty, tok);
}
c.variant = c.fld - test.ty.u.Agg.flds.#ptr;
+
+ if seen->get(c.variant) {
+ err(P, tok.loc, "duplicate case expression (previously seen at %l)", *seen->get(c.variant));
+ }
+ seen->put(c.variant, tok.loc);
+
if c.fld.ty != #null and lexmatch(P, &tok, '*') {
if !islvalue(test) {
fatal(P, tok.loc, "cannot capture by pointer, test expression is not lvalue");
diff --git a/src/set.hff b/src/set.hff
index 6a03e52..212d578 100644
--- a/src/set.hff
+++ b/src/set.hff
@@ -74,6 +74,12 @@ struct Set<T, Traits> {
fn put(self *Set, x T) void {
self->intern(x);
}
+
+ fn clear(self *Set) void {
+ self.buf->clear();
+ free(self.set);
+ *self = {};
+ }
}
defmacro set_each(v, Set, &body) [
diff --git a/vgcore.7962 b/vgcore.7962
new file mode 100644
index 0000000..3f25c9e
--- /dev/null
+++ b/vgcore.7962
Binary files differ