authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-01 15:42:21-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-02 13:27:35-07:00
logabfee127353cbdadab4282b61056222cdfbec2d4
treeabcb5e07640b1cf3b426dbbfc7b115bf536ea20e
parent24c432608f6b07020fa0b18fc9c868ad6abd9b15

AstGen: pass more compile error tests

* Implement "initializing array with struct syntax" * Implement "'_' used as an identifier without @\"_\" syntax" * Fix source location of "missing parameter name" * Update test cases where appropriate

2 files changed, 50 insertions(+), 26 deletions(-)

src/AstGen.zig+36-19
...@@ -1313,22 +1313,23 @@ fn structInitExpr(...@@ -1313,22 +1313,23 @@ fn structInitExpr(
1313 const astgen = gz.astgen;1313 const astgen = gz.astgen;
1314 const tree = astgen.tree;1314 const tree = astgen.tree;
13151315
1316 if (struct_init.ast.fields.len == 0) {1316 if (struct_init.ast.type_expr == 0) {
1317 if (struct_init.ast.type_expr == 0) {1317 if (struct_init.ast.fields.len == 0) {
1318 return rvalue(gz, rl, .empty_struct, node);1318 return rvalue(gz, rl, .empty_struct, node);
1319 }1319 }
1320 array: {1320 } else array: {
1321 const node_tags = tree.nodes.items(.tag);1321 const node_tags = tree.nodes.items(.tag);
1322 const main_tokens = tree.nodes.items(.main_token);1322 const main_tokens = tree.nodes.items(.main_token);
1323 const array_type: ast.full.ArrayType = switch (node_tags[struct_init.ast.type_expr]) {1323 const array_type: ast.full.ArrayType = switch (node_tags[struct_init.ast.type_expr]) {
1324 .array_type => tree.arrayType(struct_init.ast.type_expr),1324 .array_type => tree.arrayType(struct_init.ast.type_expr),
1325 .array_type_sentinel => tree.arrayTypeSentinel(struct_init.ast.type_expr),1325 .array_type_sentinel => tree.arrayTypeSentinel(struct_init.ast.type_expr),
1326 else => break :array,1326 else => break :array,
1327 };1327 };
1328 const is_inferred_array_len = node_tags[array_type.ast.elem_count] == .identifier and
1328 // This intentionally does not support `@"_"` syntax.1329 // This intentionally does not support `@"_"` syntax.
1329 if (node_tags[array_type.ast.elem_count] == .identifier and1330 mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_");
1330 mem.eql(u8, tree.tokenSlice(main_tokens[array_type.ast.elem_count]), "_"))1331 if (struct_init.ast.fields.len == 0) {
1331 {1332 if (is_inferred_array_len) {
1332 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);1333 const elem_type = try typeExpr(gz, scope, array_type.ast.elem_type);
1333 const array_type_inst = if (array_type.ast.sentinel == 0) blk: {1334 const array_type_inst = if (array_type.ast.sentinel == 0) blk: {
1334 break :blk try gz.addBin(.array_type, .zero_usize, elem_type);1335 break :blk try gz.addBin(.array_type, .zero_usize, elem_type);
...@@ -1339,11 +1340,18 @@ fn structInitExpr(...@@ -1339,11 +1340,18 @@ fn structInitExpr(
1339 const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node);1340 const result = try gz.addUnNode(.struct_init_empty, array_type_inst, node);
1340 return rvalue(gz, rl, result, node);1341 return rvalue(gz, rl, result, node);
1341 }1342 }
1343 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1344 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
1345 return rvalue(gz, rl, result, node);
1346 } else {
1347 return astgen.failNode(
1348 struct_init.ast.type_expr,
1349 "initializing array with struct syntax",
1350 .{},
1351 );
1342 }1352 }
1343 const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr);
1344 const result = try gz.addUnNode(.struct_init_empty, ty_inst, node);
1345 return rvalue(gz, rl, result, node);
1346 }1353 }
1354
1347 switch (rl) {1355 switch (rl) {
1348 .discard => {1356 .discard => {
1349 if (struct_init.ast.type_expr != 0)1357 if (struct_init.ast.type_expr != 0)
...@@ -2266,6 +2274,10 @@ fn varDecl(...@@ -2266,6 +2274,10 @@ fn varDecl(
2266 const token_tags = tree.tokens.items(.tag);2274 const token_tags = tree.tokens.items(.tag);
22672275
2268 const name_token = var_decl.ast.mut_token + 1;2276 const name_token = var_decl.ast.mut_token + 1;
2277 const ident_name_raw = tree.tokenSlice(name_token);
2278 if (mem.eql(u8, ident_name_raw, "_")) {
2279 return astgen.failTok(name_token, "'_' used as an identifier without @\"_\" syntax", .{});
2280 }
2269 const ident_name = try astgen.identAsString(name_token);2281 const ident_name = try astgen.identAsString(name_token);
22702282
2271 // Local variables shadowing detection, including function parameters.2283 // Local variables shadowing detection, including function parameters.
...@@ -3003,7 +3015,11 @@ fn fnDecl(...@@ -3003,7 +3015,11 @@ fn fnDecl(
3003 var it = fn_proto.iterate(tree.*);3015 var it = fn_proto.iterate(tree.*);
3004 while (it.next()) |param| : (i += 1) {3016 while (it.next()) |param| : (i += 1) {
3005 const name_token = param.name_token orelse {3017 const name_token = param.name_token orelse {
3006 return astgen.failNode(param.type_expr, "missing parameter name", .{});3018 if (param.anytype_ellipsis3) |tok| {
3019 return astgen.failTok(tok, "missing parameter name", .{});
3020 } else {
3021 return astgen.failNode(param.type_expr, "missing parameter name", .{});
3022 }
3007 };3023 };
3008 if (param.type_expr != 0)3024 if (param.type_expr != 0)
3009 _ = try typeExpr(&fn_gz, params_scope, param.type_expr);3025 _ = try typeExpr(&fn_gz, params_scope, param.type_expr);
...@@ -6197,10 +6213,11 @@ fn identifier(...@@ -6197,10 +6213,11 @@ fn identifier(
6197 const main_tokens = tree.nodes.items(.main_token);6213 const main_tokens = tree.nodes.items(.main_token);
61986214
6199 const ident_token = main_tokens[ident];6215 const ident_token = main_tokens[ident];
6200 const ident_name = try astgen.identifierTokenString(ident_token);6216 const ident_name_raw = tree.tokenSlice(ident_token);
6201 if (mem.eql(u8, ident_name, "_")) {6217 if (mem.eql(u8, ident_name_raw, "_")) {
6202 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});6218 return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{});
6203 }6219 }
6220 const ident_name = try astgen.identifierTokenString(ident_token);
62046221
6205 if (simple_types.get(ident_name)) |zir_const_ref| {6222 if (simple_types.get(ident_name)) |zir_const_ref| {
6206 return rvalue(gz, rl, zir_const_ref, ident);6223 return rvalue(gz, rl, zir_const_ref, ident);
test/compile_errors.zig+14-7
...@@ -2130,8 +2130,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -2130,8 +2130,7 @@ pub fn addCases(ctx: *TestContext) !void {
2130 \\ _ = x;2130 \\ _ = x;
2131 \\}2131 \\}
2132 , &[_][]const u8{2132 , &[_][]const u8{
2133 "tmp.zig:3:13: error: structs and unions, not enums, support field alignment",2133 "tmp.zig:3:7: error: expected ',', found 'align'",
2134 "tmp.zig:1:16: note: consider 'union(enum)' here",
2135 });2134 });
21362135
2137 ctx.objErrStage1("bad alignment type",2136 ctx.objErrStage1("bad alignment type",
...@@ -3765,8 +3764,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -3765,8 +3764,7 @@ pub fn addCases(ctx: *TestContext) !void {
3765 \\ return _;3764 \\ return _;
3766 \\}3765 \\}
3767 , &[_][]const u8{3766 , &[_][]const u8{
3768 "tmp.zig:2:5: error: '_' used as an identifier without @\"_\" syntax",3767 "tmp.zig:2:9: error: '_' used as an identifier without @\"_\" syntax",
3769 "tmp.zig:3:12: error: '_' used as an identifier without @\"_\" syntax",
3770 });3768 });
37713769
3772 ctx.objErrStage1("`_` should not be usable inside for",3770 ctx.objErrStage1("`_` should not be usable inside for",
...@@ -4908,7 +4906,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -4908,7 +4906,7 @@ pub fn addCases(ctx: *TestContext) !void {
4908 \\export fn entry() void { a(); }4906 \\export fn entry() void { a(); }
4909 , &[_][]const u8{4907 , &[_][]const u8{
4910 "tmp.zig:2:1: error: redeclaration of 'a'",4908 "tmp.zig:2:1: error: redeclaration of 'a'",
4911 "tmp.zig:1:1: error: other declaration here",4909 "tmp.zig:1:1: note: other declaration here",
4912 });4910 });
49134911
4914 ctx.objErrStage1("unreachable with return",4912 ctx.objErrStage1("unreachable with return",
...@@ -5218,6 +5216,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -5218,6 +5216,7 @@ pub fn addCases(ctx: *TestContext) !void {
5218 \\ .z = 4,5216 \\ .z = 4,
5219 \\ .y = 2,5217 \\ .y = 2,
5220 \\ };5218 \\ };
5219 \\ _ = a;
5221 \\}5220 \\}
5222 , &[_][]const u8{5221 , &[_][]const u8{
5223 "tmp.zig:9:17: error: missing field: 'x'",5222 "tmp.zig:9:17: error: missing field: 'x'",
...@@ -7549,13 +7548,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -7549,13 +7548,15 @@ pub fn addCases(ctx: *TestContext) !void {
7549 \\ };7548 \\ };
7550 \\7549 \\
7551 \\ for ([_]Mode { Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast }) |mode| {7550 \\ for ([_]Mode { Mode.Debug, Mode.ReleaseSafe, Mode.ReleaseFast }) |mode| {
7551 \\ _ = mode;
7552 \\ inline for (tests) |test_case| {7552 \\ inline for (tests) |test_case| {
7553 \\ const foo = test_case.filename ++ ".zig";7553 \\ const foo = test_case.filename ++ ".zig";
7554 \\ _ = foo;
7554 \\ }7555 \\ }
7555 \\ }7556 \\ }
7556 \\}7557 \\}
7557 , &[_][]const u8{7558 , &[_][]const u8{
7558 "tmp.zig:37:29: error: cannot store runtime value in compile time variable",7559 "tmp.zig:38:29: error: cannot store runtime value in compile time variable",
7559 });7560 });
75607561
7561 ctx.objErrStage1("invalid legacy unicode escape",7562 ctx.objErrStage1("invalid legacy unicode escape",
...@@ -7980,6 +7981,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -7980,6 +7981,7 @@ pub fn addCases(ctx: *TestContext) !void {
7980 \\};7981 \\};
7981 \\export fn foo() void {7982 \\export fn foo() void {
7982 \\ const fieldOffset = @offsetOf(Empty, "val",);7983 \\ const fieldOffset = @offsetOf(Empty, "val",);
7984 \\ _ = fieldOffset;
7983 \\}7985 \\}
7984 , &[_][]const u8{7986 , &[_][]const u8{
7985 "tmp.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset",7987 "tmp.zig:5:42: error: zero-bit field 'val' in struct 'Empty' has no offset",
...@@ -7991,6 +7993,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -7991,6 +7993,7 @@ pub fn addCases(ctx: *TestContext) !void {
7991 \\};7993 \\};
7992 \\export fn foo() void {7994 \\export fn foo() void {
7993 \\ const fieldOffset = @bitOffsetOf(Empty, "val",);7995 \\ const fieldOffset = @bitOffsetOf(Empty, "val",);
7996 \\ _ = fieldOffset;
7994 \\}7997 \\}
7995 , &[_][]const u8{7998 , &[_][]const u8{
7996 "tmp.zig:5:45: error: zero-bit field 'val' in struct 'Empty' has no offset",7999 "tmp.zig:5:45: error: zero-bit field 'val' in struct 'Empty' has no offset",
...@@ -8004,6 +8007,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -8004,6 +8007,7 @@ pub fn addCases(ctx: *TestContext) !void {
8004 \\comptime {8007 \\comptime {
8005 \\ var foo = Foo {.Baz = {}};8008 \\ var foo = Foo {.Baz = {}};
8006 \\ const bar_val = foo.Bar;8009 \\ const bar_val = foo.Bar;
8010 \\ _ = bar_val;
8007 \\}8011 \\}
8008 , &[_][]const u8{8012 , &[_][]const u8{
8009 "tmp.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set",8013 "tmp.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set",
...@@ -8119,6 +8123,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -8119,6 +8123,7 @@ pub fn addCases(ctx: *TestContext) !void {
8119 \\ var x: *const i32 = &w;8123 \\ var x: *const i32 = &w;
8120 \\ var y: *[1]i32 = x;8124 \\ var y: *[1]i32 = x;
8121 \\ y[0] += 1;8125 \\ y[0] += 1;
8126 \\ _ = byte;
8122 \\}8127 \\}
8123 , &[_][]const u8{8128 , &[_][]const u8{
8124 "tmp.zig:4:22: error: expected type '*[1]i32', found '*const i32'",8129 "tmp.zig:4:22: error: expected type '*[1]i32', found '*const i32'",
...@@ -8145,6 +8150,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -8145,6 +8150,7 @@ pub fn addCases(ctx: *TestContext) !void {
8145 \\export fn f2() void {8150 \\export fn f2() void {
8146 \\ var x: anyerror!i32 = error.Bad;8151 \\ var x: anyerror!i32 = error.Bad;
8147 \\ for ("hello") |_| returns() else unreachable;8152 \\ for ("hello") |_| returns() else unreachable;
8153 \\ _ = x;
8148 \\}8154 \\}
8149 , &[_][]const u8{8155 , &[_][]const u8{
8150 "tmp.zig:5:30: error: expression value is ignored",8156 "tmp.zig:5:30: error: expression value is ignored",
...@@ -8154,6 +8160,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -8154,6 +8160,7 @@ pub fn addCases(ctx: *TestContext) !void {
8154 ctx.objErrStage1("aligned variable of zero-bit type",8160 ctx.objErrStage1("aligned variable of zero-bit type",
8155 \\export fn f() void {8161 \\export fn f() void {
8156 \\ var s: struct {} align(4) = undefined;8162 \\ var s: struct {} align(4) = undefined;
8163 \\ _ = s;
8157 \\}8164 \\}
8158 , &[_][]const u8{8165 , &[_][]const u8{
8159 "tmp.zig:2:5: error: variable 's' of zero-bit type 'struct:2:12' has no in-memory representation, it cannot be aligned",8166 "tmp.zig:2:5: error: variable 's' of zero-bit type 'struct:2:12' has no in-memory representation, it cannot be aligned",
...@@ -8637,7 +8644,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -8637,7 +8644,7 @@ pub fn addCases(ctx: *TestContext) !void {
8637 });8644 });
86388645
8639 ctx.objErrStage1("issue #5221: invalid struct init type referenced by @typeInfo and passed into function",8646 ctx.objErrStage1("issue #5221: invalid struct init type referenced by @typeInfo and passed into function",
8640 \\fn ignore(comptime param: anytype) void {}8647 \\fn ignore(comptime param: anytype) void {_ = param;}
8641 \\8648 \\
8642 \\export fn foo() void {8649 \\export fn foo() void {
8643 \\ const MyStruct = struct {8650 \\ const MyStruct = struct {