Commit b971c7d0ff

Vexu <git@vexu.eu>
2020-01-15 19:40:56
update tests and translate-c
1 parent 6fd0ddd
Changed files (5)
src-self-hosted/translate_c.zig
@@ -440,7 +440,6 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
             .PrivateExtern => return failDecl(c, fn_decl_loc, fn_name, "unsupported storage class: private extern", .{}),
             .Auto => unreachable, // Not legal on functions
             .Register => unreachable, // Not legal on functions
-            else => unreachable,
         },
     };
 
@@ -953,6 +952,19 @@ fn transEnumDecl(c: *Context, enum_decl: *const ZigClangEnumDecl) Error!?*ast.No
             tld_node.semicolon_token = try appendToken(c, .Semicolon, ";");
             try addTopLevelDecl(c, field_name, &tld_node.base);
         }
+        // make non exhaustive
+        const field_node = try c.a().create(ast.Node.ContainerField);
+        field_node.* = .{
+            .doc_comments = null,
+            .comptime_token = null,
+            .name_token = try appendIdentifier(c, "_"),
+            .type_expr = null,
+            .value_expr = null,
+            .align_expr = null,
+        };
+
+        try container_node.fields_and_decls.push(&field_node.base);
+        _ = try appendToken(c, .Comma, ",");
         container_node.rbrace_token = try appendToken(c, .RBrace, "}");
 
         break :blk &container_node.base;
@@ -1231,18 +1243,6 @@ fn transBinaryOperator(
             op_id = .BitOr;
             op_token = try appendToken(rp.c, .Pipe, "|");
         },
-        .Assign,
-        .MulAssign,
-        .DivAssign,
-        .RemAssign,
-        .AddAssign,
-        .SubAssign,
-        .ShlAssign,
-        .ShrAssign,
-        .AndAssign,
-        .XorAssign,
-        .OrAssign,
-        => unreachable,
         else => unreachable,
     }
 
@@ -1678,7 +1678,6 @@ fn transStringLiteral(
             "TODO: support string literal kind {}",
             .{kind},
         ),
-        else => unreachable,
     }
 }
 
test/stage1/behavior/cast.zig
@@ -618,7 +618,6 @@ test "peer resolution of string literals" {
                 .b => "two",
                 .c => "three",
                 .d => "four",
-                else => unreachable,
             };
             expect(mem.eql(u8, cmd, "two"));
         }
test/stage1/behavior/enum.zig
@@ -11,17 +11,41 @@ test "extern enum" {
         };
         fn doTheTest(y: c_int) void {
             var x = i.o;
-            expect(@enumToInt(x) == 2);
-            x = @intToEnum(i, 12);
-            expect(@enumToInt(x) == 12);
-            x = @intToEnum(i, y);
-            expect(@enumToInt(x) == 52);
             switch (x) {
-                .n,
-                .o,
-                .p => unreachable,
+                .n, .p => unreachable,
+                .o => {},
+            }
+        }
+    };
+    S.doTheTest(52);
+    comptime S.doTheTest(52);
+}
+
+test "non-exhaustive enum" {
+    const S = struct {
+        const E = enum(u8) {
+            a,
+            b,
+            _,
+        };
+        fn doTheTest(y: u8) void {
+            var e: E = .b;
+            switch (e) {
+                .a => {},
+                .b => {},
+                _ => {},
+            }
+
+            switch (e) {
+                .a => {},
+                .b => {},
                 else => {},
             }
+            expect(@enumToInt(e) == 1);
+            e = @intToEnum(E, 12);
+            expect(@enumToInt(e) == 12);
+            e = @intToEnum(E, y);
+            expect(@enumToInt(e) == 52);
         }
     };
     S.doTheTest(52);
test/compile_errors.zig
@@ -2,6 +2,28 @@ const tests = @import("tests.zig");
 const builtin = @import("builtin");
 
 pub fn addCases(cases: *tests.CompileErrorContext) void {
+    cases.addTest("non-exhaustive enums",
+        \\const E = enum {
+        \\    a,
+        \\    b,
+        \\    _,
+        \\};
+        \\pub export fn entry() void {
+        \\    var e: E = .b;
+        \\    switch (e) { // error: switch not handling the tag `b`
+        \\        .a => {},
+        \\        _ => {},
+        \\    }
+        \\    switch (e) { // error: switch on non-exhaustive enum must include `else` or `_` prong
+        \\        .a => {},
+        \\        .b => {},
+        \\    }
+        \\}
+    , &[_][]const u8{
+        "tmp.zig:8:5: error: enumeration value 'E.b' not handled in switch",
+        "tmp.zig:12:5: error: switch on non-exhaustive enum must include `else` or `_` prong",
+    });
+
     cases.addTest("@export with empty name string",
         \\pub export fn entry() void { }
         \\comptime {
@@ -139,25 +161,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
         "tmp.zig:2:13: error: pointer type '[*]align(4) u8' requires aligned address",
     });
 
-    cases.add("switch on extern enum missing else prong",
-        \\const i = extern enum {
-        \\    n = 0,
-        \\    o = 2,
-        \\    p = 4,
-        \\    q = 4,
-        \\};
-        \\pub fn main() void {
-        \\    var x = @intToEnum(i, 52);
-        \\    switch (x) {
-        \\        .n,
-        \\        .o,
-        \\        .p => unreachable,
-        \\    }
-        \\}
-    , &[_][]const u8{
-        "tmp.zig:9:5: error: switch on an extern enum must have an else prong",
-    });
-
     cases.add("invalid float literal",
         \\const std = @import("std");
         \\
test/translate_c.zig
@@ -629,6 +629,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
             \\    VAL21 = 6917529027641081853,
             \\    VAL22 = 0,
             \\    VAL23 = -1,
+            \\    _,
             \\};
         });
     }
@@ -990,6 +991,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\pub const FOO = @enumToInt(enum_enum_ty.FOO);
         \\pub const enum_enum_ty = extern enum {
         \\    FOO,
+        \\    _,
         \\};
         \\pub extern var my_enum: enum_enum_ty;
     });
@@ -1106,6 +1108,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    a,
         \\    b,
         \\    c,
+        \\    _,
         \\};
         \\pub const d = enum_unnamed_1;
         \\pub const e = @enumToInt(enum_unnamed_2.e);
@@ -1115,6 +1118,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    e = 0,
         \\    f = 4,
         \\    g = 5,
+        \\    _,
         \\};
         \\pub export var h: enum_unnamed_2 = @intToEnum(enum_unnamed_2, e);
         \\pub const i = @enumToInt(enum_unnamed_3.i);
@@ -1124,6 +1128,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    i,
         \\    j,
         \\    k,
+        \\    _,
         \\};
         \\pub const struct_Baz = extern struct {
         \\    l: enum_unnamed_3,
@@ -1136,6 +1141,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    n,
         \\    o,
         \\    p,
+        \\    _,
         \\};
     ,
         \\pub const Baz = struct_Baz;
@@ -1566,6 +1572,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\const enum_unnamed_1 = extern enum {
         \\    One,
         \\    Two,
+        \\    _,
         \\};
     });
 
@@ -1669,6 +1676,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    A,
         \\    B,
         \\    C,
+        \\    _,
         \\};
         \\pub const SomeTypedef = c_int;
         \\pub export fn and_or_non_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void) c_int {
@@ -1713,6 +1721,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\pub const enum_Bar = extern enum {
         \\    A,
         \\    B,
+        \\    _,
         \\};
         \\pub extern fn func(a: [*c]struct_Foo, b: [*c][*c]enum_Bar) void;
     ,
@@ -1977,6 +1986,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    A,
         \\    B,
         \\    C,
+        \\    _,
         \\};
         \\pub export fn if_none_bool(arg_a: c_int, arg_b: f32, arg_c: ?*c_void, arg_d: enum_SomeEnum) c_int {
         \\    var a = arg_a;
@@ -2418,6 +2428,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    A = 2,
         \\    B = 5,
         \\    @"1" = 6,
+        \\    _,
         \\};
     ,
         \\pub const Foo = enum_Foo;