aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-03-31 18:38:26 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-03-31 18:39:34 -0700
commite8143f6cbe3d1bdaeda5cd5af13447f6639b80ad (patch)
tree954e032848a0abb638e1e0af45dc4ec3114e8f3e
parentcec766f73c298d287c20d1bd830c159958fe177d (diff)
downloadzig-e8143f6cbe3d1bdaeda5cd5af13447f6639b80ad.tar.gz
zig-e8143f6cbe3d1bdaeda5cd5af13447f6639b80ad.zip
stage2: compile error for duplicate switch value on sparse
-rw-r--r--BRANCH_TODO13
-rw-r--r--src/Sema.zig17
-rw-r--r--test/stage2/cbe.zig16
3 files changed, 27 insertions, 19 deletions
diff --git a/BRANCH_TODO b/BRANCH_TODO
index 72b1ed6719..a80a7dca34 100644
--- a/BRANCH_TODO
+++ b/BRANCH_TODO
@@ -36,16 +36,3 @@ Performance optimizations to look into:
* look into not emitting redundant dbg stmts to TZIR
* make decl references in ZIR be u32 indexes to the Decl dependencies array hash map
instead of duplicating *Decl entries in zir.Code.
-
-
- for (inst.positionals.items) |item| {
- const resolved = try sema.resolveInst(item);
- const casted = try sema.coerce(block, operand.ty, resolved);
- const val = try sema.resolveConstValue(block, item_src, casted);
-
- if (try seen_values.fetchPut(val, item.src)) |prev| {
- return sema.mod.fail(&block.base, item.src, "duplicate switch value", .{});
- // TODO notes "previous value here" prev.value
- }
- }
-
diff --git a/src/Sema.zig b/src/Sema.zig
index f53bc295f3..4d97506e3c 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -62,8 +62,6 @@ const LazySrcLoc = Module.LazySrcLoc;
const RangeSet = @import("RangeSet.zig");
const AstGen = @import("AstGen.zig");
-const ValueSrcMap = std.HashMap(Value, LazySrcLoc, Value.hash, Value.eql, std.hash_map.DefaultMaxLoadPercentage);
-
pub fn root(sema: *Sema, root_block: *Scope.Block) !zir.Inst.Index {
const inst_data = sema.code.instructions.items(.data)[0].pl_node;
const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
@@ -2557,7 +2555,7 @@ fn analyzeSwitch(
var extra_index: usize = special.end;
{
- var scalar_i: usize = 0;
+ var scalar_i: u32 = 0;
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
const item_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
@@ -2571,11 +2569,12 @@ fn analyzeSwitch(
&seen_values,
item_ref,
src_node_offset,
+ .{ .scalar = scalar_i },
);
}
}
{
- var multi_i: usize = 0;
+ var multi_i: u32 = 0;
while (multi_i < multi_cases_len) : (multi_i += 1) {
const items_len = sema.code.extra[extra_index];
extra_index += 1;
@@ -2586,12 +2585,13 @@ fn analyzeSwitch(
const items = sema.code.refSlice(extra_index, items_len);
extra_index += items_len + body_len;
- for (items) |item_ref| {
+ for (items) |item_ref, item_i| {
try sema.validateSwitchItemSparse(
block,
&seen_values,
item_ref,
src_node_offset,
+ .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
);
}
@@ -2981,14 +2981,19 @@ fn validateSwitchItemBool(
}
}
+const ValueSrcMap = std.HashMap(Value, AstGen.SwitchProngSrc, Value.hash, Value.eql, std.hash_map.DefaultMaxLoadPercentage);
+
fn validateSwitchItemSparse(
sema: *Sema,
block: *Scope.Block,
seen_values: *ValueSrcMap,
item_ref: zir.Inst.Ref,
src_node_offset: i32,
+ switch_prong_src: AstGen.SwitchProngSrc,
) InnerError!void {
- @panic("TODO");
+ const item_val = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
+ const entry = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return;
+ return sema.validateSwitchDupe(block, entry.value, switch_prong_src, src_node_offset);
}
fn validateSwitchNoRange(
diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig
index fa8195f48a..2b0976c9f8 100644
--- a/test/stage2/cbe.zig
+++ b/test/stage2/cbe.zig
@@ -359,6 +359,22 @@ pub fn addCases(ctx: *TestContext) !void {
, &.{
":6:9: error: duplicate switch value",
});
+
+ // Sparse (no range capable) switch expression has duplicate case value.
+ case.addError(
+ \\export fn main() c_int {
+ \\ const A: type = i32;
+ \\ const b: c_int = switch (A) {
+ \\ i32 => 1,
+ \\ bool => 2,
+ \\ f64, i32 => 3,
+ \\ else => 4,
+ \\ };
+ \\}
+ , &.{
+ ":6:14: error: duplicate switch value",
+ ":4:9: note: previous value here",
+ });
}
//{
// var case = ctx.exeFromCompiledC("optionals", .{});