authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-26 11:26:35-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-07-26 11:26:35-07:00
log0ffcf19e3d19ddd8c5f89d6ac8ff5a1d77666279
tree9ff618d76c1731de0cfaaa921c9f701607e8c24e
parenta0d3a87ce15a9f68047dc900109f5b76184d046f
parenta463dc7d6c3bb560903d11cb9e34668e89c374d6
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12237 from Vexu/stage2-compile-errors

Stage2 improve errors for builtin function options structs

13 files changed, 381 insertions(+), 148 deletions(-)

lib/std/zig/Ast.zig+8
...@@ -297,6 +297,12 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {...@@ -297,6 +297,12 @@ pub fn renderError(tree: Ast, parse_error: Error, stream: anytype) !void {
297 .unattached_doc_comment => {297 .unattached_doc_comment => {
298 return stream.writeAll("unattached documentation comment");298 return stream.writeAll("unattached documentation comment");
299 },299 },
300 .test_doc_comment => {
301 return stream.writeAll("documentation comments cannot be attached to tests");
302 },
303 .comptime_doc_comment => {
304 return stream.writeAll("documentation comments cannot be attached to comptime blocks");
305 },
300 .varargs_nonfinal => {306 .varargs_nonfinal => {
301 return stream.writeAll("function prototype has parameter after varargs");307 return stream.writeAll("function prototype has parameter after varargs");
302 },308 },
...@@ -2539,6 +2545,8 @@ pub const Error = struct {...@@ -2539,6 +2545,8 @@ pub const Error = struct {
2539 invalid_bit_range,2545 invalid_bit_range,
2540 same_line_doc_comment,2546 same_line_doc_comment,
2541 unattached_doc_comment,2547 unattached_doc_comment,
2548 test_doc_comment,
2549 comptime_doc_comment,
2542 varargs_nonfinal,2550 varargs_nonfinal,
2543 expected_continue_expr,2551 expected_continue_expr,
2544 expected_semi_after_decl,2552 expected_semi_after_decl,
lib/std/zig/parse.zig+6
...@@ -259,6 +259,9 @@ const Parser = struct {...@@ -259,6 +259,9 @@ const Parser = struct {
259259
260 switch (p.token_tags[p.tok_i]) {260 switch (p.token_tags[p.tok_i]) {
261 .keyword_test => {261 .keyword_test => {
262 if (doc_comment) |some| {
263 try p.warnMsg(.{ .tag = .test_doc_comment, .token = some });
264 }
262 const test_decl_node = try p.expectTestDeclRecoverable();265 const test_decl_node = try p.expectTestDeclRecoverable();
263 if (test_decl_node != 0) {266 if (test_decl_node != 0) {
264 if (field_state == .seen) {267 if (field_state == .seen) {
...@@ -317,6 +320,9 @@ const Parser = struct {...@@ -317,6 +320,9 @@ const Parser = struct {
317 }320 }
318 },321 },
319 .l_brace => {322 .l_brace => {
323 if (doc_comment) |some| {
324 try p.warnMsg(.{ .tag = .test_doc_comment, .token = some });
325 }
320 const comptime_token = p.nextToken();326 const comptime_token = p.nextToken();
321 const block = p.parseBlock() catch |err| switch (err) {327 const block = p.parseBlock() catch |err| switch (err) {
322 error.OutOfMemory => return error.OutOfMemory,328 error.OutOfMemory => return error.OutOfMemory,
lib/std/zig/parser_test.zig-12
...@@ -184,15 +184,6 @@ test "zig fmt: file ends in comment after var decl" {...@@ -184,15 +184,6 @@ test "zig fmt: file ends in comment after var decl" {
184 );184 );
185}185}
186186
187test "zig fmt: doc comments on test" {
188 try testCanonical(
189 \\/// hello
190 \\/// world
191 \\test "" {}
192 \\
193 );
194}
195
196test "zig fmt: if statment" {187test "zig fmt: if statment" {
197 try testCanonical(188 try testCanonical(
198 \\test "" {189 \\test "" {
...@@ -2700,9 +2691,6 @@ test "zig fmt: comments in statements" {...@@ -2700,9 +2691,6 @@ test "zig fmt: comments in statements" {
27002691
2701test "zig fmt: comments before test decl" {2692test "zig fmt: comments before test decl" {
2702 try testCanonical(2693 try testCanonical(
2703 \\/// top level doc comment
2704 \\test "hi" {}
2705 \\
2706 \\// top level normal comment2694 \\// top level normal comment
2707 \\test "hi" {}2695 \\test "hi" {}
2708 \\2696 \\
lib/std/zig/system/darwin.zig+1-1
...@@ -87,6 +87,6 @@ pub const DarwinSDK = struct {...@@ -87,6 +87,6 @@ pub const DarwinSDK = struct {
87 }87 }
88};88};
8989
90test "" {90test {
91 _ = macos;91 _ = macos;
92}92}
src/AstGen.zig+37-1
...@@ -3497,6 +3497,12 @@ fn fnDecl(...@@ -3497,6 +3497,12 @@ fn fnDecl(
34973497
3498 const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: {3498 const lib_name: u32 = if (fn_proto.lib_name) |lib_name_token| blk: {
3499 const lib_name_str = try astgen.strLitAsString(lib_name_token);3499 const lib_name_str = try astgen.strLitAsString(lib_name_token);
3500 const lib_name_slice = astgen.string_bytes.items[lib_name_str.index..][0..lib_name_str.len];
3501 if (mem.indexOfScalar(u8, lib_name_slice, 0) != null) {
3502 return astgen.failTok(lib_name_token, "library name cannot contain null bytes", .{});
3503 } else if (lib_name_str.len == 0) {
3504 return astgen.failTok(lib_name_token, "library name cannot be empty", .{});
3505 }
3500 break :blk lib_name_str.index;3506 break :blk lib_name_str.index;
3501 } else 0;3507 } else 0;
35023508
...@@ -3750,6 +3756,12 @@ fn globalVarDecl(...@@ -3750,6 +3756,12 @@ fn globalVarDecl(
37503756
3751 const lib_name: u32 = if (var_decl.lib_name) |lib_name_token| blk: {3757 const lib_name: u32 = if (var_decl.lib_name) |lib_name_token| blk: {
3752 const lib_name_str = try astgen.strLitAsString(lib_name_token);3758 const lib_name_str = try astgen.strLitAsString(lib_name_token);
3759 const lib_name_slice = astgen.string_bytes.items[lib_name_str.index..][0..lib_name_str.len];
3760 if (mem.indexOfScalar(u8, lib_name_slice, 0) != null) {
3761 return astgen.failTok(lib_name_token, "library name cannot contain null bytes", .{});
3762 } else if (lib_name_str.len == 0) {
3763 return astgen.failTok(lib_name_token, "library name cannot be empty", .{});
3764 }
3753 break :blk lib_name_str.index;3765 break :blk lib_name_str.index;
3754 } else 0;3766 } else 0;
37553767
...@@ -7239,6 +7251,12 @@ fn builtinCall(...@@ -7239,6 +7251,12 @@ fn builtinCall(
7239 }7251 }
7240 const str_lit_token = main_tokens[operand_node];7252 const str_lit_token = main_tokens[operand_node];
7241 const str = try astgen.strLitAsString(str_lit_token);7253 const str = try astgen.strLitAsString(str_lit_token);
7254 const str_slice = astgen.string_bytes.items[str.index..][0..str.len];
7255 if (mem.indexOfScalar(u8, str_slice, 0) != null) {
7256 return astgen.failTok(str_lit_token, "import path cannot contain null bytes", .{});
7257 } else if (str.len == 0) {
7258 return astgen.failTok(str_lit_token, "import path cannot be empty", .{});
7259 }
7242 const result = try gz.addStrTok(.import, str.index, str_lit_token);7260 const result = try gz.addStrTok(.import, str.index, str_lit_token);
7243 const gop = try astgen.imports.getOrPut(astgen.gpa, str.index);7261 const gop = try astgen.imports.getOrPut(astgen.gpa, str.index);
7244 if (!gop.found_existing) {7262 if (!gop.found_existing) {
...@@ -9260,6 +9278,11 @@ fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]co...@@ -9260,6 +9278,11 @@ fn identifierTokenString(astgen: *AstGen, token: Ast.TokenIndex) InnerError![]co
9260 var buf: ArrayListUnmanaged(u8) = .{};9278 var buf: ArrayListUnmanaged(u8) = .{};
9261 defer buf.deinit(astgen.gpa);9279 defer buf.deinit(astgen.gpa);
9262 try astgen.parseStrLit(token, &buf, ident_name, 1);9280 try astgen.parseStrLit(token, &buf, ident_name, 1);
9281 if (mem.indexOfScalar(u8, buf.items, 0) != null) {
9282 return astgen.failTok(token, "identifier cannot contain null bytes", .{});
9283 } else if (buf.items.len == 0) {
9284 return astgen.failTok(token, "identifier cannot be empty", .{});
9285 }
9263 const duped = try astgen.arena.dupe(u8, buf.items);9286 const duped = try astgen.arena.dupe(u8, buf.items);
9264 return duped;9287 return duped;
9265}9288}
...@@ -9279,7 +9302,14 @@ fn appendIdentStr(...@@ -9279,7 +9302,14 @@ fn appendIdentStr(
9279 if (!mem.startsWith(u8, ident_name, "@")) {9302 if (!mem.startsWith(u8, ident_name, "@")) {
9280 return buf.appendSlice(astgen.gpa, ident_name);9303 return buf.appendSlice(astgen.gpa, ident_name);
9281 } else {9304 } else {
9282 return astgen.parseStrLit(token, buf, ident_name, 1);9305 const start = buf.items.len;
9306 try astgen.parseStrLit(token, buf, ident_name, 1);
9307 const slice = buf.items[start..];
9308 if (mem.indexOfScalar(u8, slice, 0) != null) {
9309 return astgen.failTok(token, "identifier cannot contain null bytes", .{});
9310 } else if (slice.len == 0) {
9311 return astgen.failTok(token, "identifier cannot be empty", .{});
9312 }
9283 }9313 }
9284}9314}
92859315
...@@ -9723,6 +9753,12 @@ fn testNameString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !u32 {...@@ -9723,6 +9753,12 @@ fn testNameString(astgen: *AstGen, str_lit_token: Ast.TokenIndex) !u32 {
9723 const token_bytes = astgen.tree.tokenSlice(str_lit_token);9753 const token_bytes = astgen.tree.tokenSlice(str_lit_token);
9724 try string_bytes.append(gpa, 0); // Indicates this is a test.9754 try string_bytes.append(gpa, 0); // Indicates this is a test.
9725 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);9755 try astgen.parseStrLit(str_lit_token, string_bytes, token_bytes, 0);
9756 const slice = string_bytes.items[str_index + 1 ..];
9757 if (mem.indexOfScalar(u8, slice, 0) != null) {
9758 return astgen.failTok(str_lit_token, "test name cannot contain null bytes", .{});
9759 } else if (slice.len == 0) {
9760 return astgen.failTok(str_lit_token, "empty test name must be omitted", .{});
9761 }
9726 try string_bytes.append(gpa, 0);9762 try string_bytes.append(gpa, 0);
9727 return str_index;9763 return str_index;
9728}9764}
src/Module.zig+57-3
...@@ -5939,10 +5939,11 @@ pub fn argSrc(...@@ -5939,10 +5939,11 @@ pub fn argSrc(
5939 call_node_offset: i32,5939 call_node_offset: i32,
5940 gpa: Allocator,5940 gpa: Allocator,
5941 decl: *Decl,5941 decl: *Decl,
5942 arg_i: usize,5942 start_arg_i: usize,
5943 bound_arg_src: ?LazySrcLoc,5943 bound_arg_src: ?LazySrcLoc,
5944) LazySrcLoc {5944) LazySrcLoc {
5945 if (arg_i == 0 and bound_arg_src != null) return bound_arg_src.?;5945 if (start_arg_i == 0 and bound_arg_src != null) return bound_arg_src.?;
5946 const arg_i = start_arg_i - @boolToInt(bound_arg_src != null);
5946 @setCold(true);5947 @setCold(true);
5947 const tree = decl.getFileScope().getTree(gpa) catch |err| {5948 const tree = decl.getFileScope().getTree(gpa) catch |err| {
5948 // In this case we emit a warning + a less precise source location.5949 // In this case we emit a warning + a less precise source location.
...@@ -5957,6 +5958,12 @@ pub fn argSrc(...@@ -5957,6 +5958,12 @@ pub fn argSrc(
5957 const full = switch (node_tags[node]) {5958 const full = switch (node_tags[node]) {
5958 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&args, node),5959 .call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&args, node),
5959 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),5960 .call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
5961 .builtin_call => {
5962 const node_datas = tree.nodes.items(.data);
5963 const call_args_node = tree.extra_data[node_datas[node].rhs - 1];
5964 const call_args_offset = decl.nodeIndexToRelative(call_args_node);
5965 return initSrc(call_args_offset, gpa, decl, arg_i);
5966 },
5960 else => unreachable,5967 else => unreachable,
5961 };5968 };
5962 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(full.ast.params[arg_i]));5969 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(full.ast.params[arg_i]));
...@@ -5989,7 +5996,7 @@ pub fn initSrc(...@@ -5989,7 +5996,7 @@ pub fn initSrc(
5989 .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(&buf, node).ast.fields,5996 .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(&buf, node).ast.fields,
5990 .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node).ast.fields,5997 .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(node).ast.fields,
5991 .struct_init, .struct_init_comma => tree.structInit(node).ast.fields,5998 .struct_init, .struct_init_comma => tree.structInit(node).ast.fields,
5992 else => unreachable,5999 else => return LazySrcLoc.nodeOffset(init_node_offset),
5993 };6000 };
5994 switch (node_tags[node]) {6001 switch (node_tags[node]) {
5995 .array_init_one,6002 .array_init_one,
...@@ -6014,6 +6021,53 @@ pub fn initSrc(...@@ -6014,6 +6021,53 @@ pub fn initSrc(
6014 }6021 }
6015}6022}
60166023
6024pub fn optionsSrc(gpa: Allocator, decl: *Decl, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc {
6025 @setCold(true);
6026 const tree = decl.getFileScope().getTree(gpa) catch |err| {
6027 // In this case we emit a warning + a less precise source location.
6028 log.warn("unable to load {s}: {s}", .{
6029 decl.getFileScope().sub_file_path, @errorName(err),
6030 });
6031 return LazySrcLoc.nodeOffset(0);
6032 };
6033
6034 const o_i: struct { off: i32, i: u8 } = switch (base_src) {
6035 .node_offset_builtin_call_arg0 => |n| .{ .off = n, .i = 0 },
6036 .node_offset_builtin_call_arg1 => |n| .{ .off = n, .i = 1 },
6037 else => unreachable,
6038 };
6039
6040 const node = decl.relativeToNodeIndex(o_i.off);
6041 const node_datas = tree.nodes.items(.data);
6042 const node_tags = tree.nodes.items(.tag);
6043 const arg_node = switch (node_tags[node]) {
6044 .builtin_call_two, .builtin_call_two_comma => switch (o_i.i) {
6045 0 => node_datas[node].lhs,
6046 1 => node_datas[node].rhs,
6047 else => unreachable,
6048 },
6049 .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + o_i.i],
6050 else => unreachable,
6051 };
6052 var buf: [2]std.zig.Ast.Node.Index = undefined;
6053 const init_nodes = switch (node_tags[arg_node]) {
6054 .struct_init_one, .struct_init_one_comma => tree.structInitOne(buf[0..1], arg_node).ast.fields,
6055 .struct_init_dot_two, .struct_init_dot_two_comma => tree.structInitDotTwo(&buf, arg_node).ast.fields,
6056 .struct_init_dot, .struct_init_dot_comma => tree.structInitDot(arg_node).ast.fields,
6057 .struct_init, .struct_init_comma => tree.structInit(arg_node).ast.fields,
6058 else => return base_src,
6059 };
6060 for (init_nodes) |init_node| {
6061 // . IDENTIFIER = init_node
6062 const name_token = tree.firstToken(init_node) - 2;
6063 const name = tree.tokenSlice(name_token);
6064 if (std.mem.eql(u8, name, wanted)) {
6065 return LazySrcLoc{ .node_offset_initializer = decl.nodeIndexToRelative(init_node) };
6066 }
6067 }
6068 return base_src;
6069}
6070
6017/// Called from `performAllTheWork`, after all AstGen workers have finished,6071/// Called from `performAllTheWork`, after all AstGen workers have finished,
6018/// and before the main semantic analysis loop begins.6072/// and before the main semantic analysis loop begins.
6019pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {6073pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {
src/Sema.zig+219-126
...@@ -4909,7 +4909,13 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -4909,7 +4909,13 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
4909 return sema.fail(block, src, "TODO: implement exporting with field access", .{});4909 return sema.fail(block, src, "TODO: implement exporting with field access", .{});
4910 }4910 }
4911 const decl_index = try sema.lookupIdentifier(block, operand_src, decl_name);4911 const decl_index = try sema.lookupIdentifier(block, operand_src, decl_name);
4912 const options = try sema.resolveExportOptions(block, options_src, extra.options);4912 const options = sema.resolveExportOptions(block, .unneeded, extra.options) catch |err| switch (err) {
4913 error.NeededSourceLocation => {
4914 _ = try sema.resolveExportOptions(block, options_src, extra.options);
4915 return error.AnalysisFail;
4916 },
4917 else => |e| return e,
4918 };
4913 try sema.analyzeExport(block, src, options, decl_index);4919 try sema.analyzeExport(block, src, options, decl_index);
4914}4920}
49154921
...@@ -4923,7 +4929,13 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -4923,7 +4929,13 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
4923 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };4929 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
4924 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };4930 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
4925 const operand = try sema.resolveInstConst(block, operand_src, extra.operand, "export target must be comptime known");4931 const operand = try sema.resolveInstConst(block, operand_src, extra.operand, "export target must be comptime known");
4926 const options = try sema.resolveExportOptions(block, options_src, extra.options);4932 const options = sema.resolveExportOptions(block, .unneeded, extra.options) catch |err| switch (err) {
4933 error.NeededSourceLocation => {
4934 _ = try sema.resolveExportOptions(block, options_src, extra.options);
4935 return error.AnalysisFail;
4936 },
4937 else => |e| return e,
4938 };
4927 const decl_index = switch (operand.val.tag()) {4939 const decl_index = switch (operand.val.tag()) {
4928 .function => operand.val.castTag(.function).?.data.owner_decl,4940 .function => operand.val.castTag(.function).?.data.owner_decl,
4929 else => return sema.fail(block, operand_src, "TODO implement exporting arbitrary Value objects", .{}), // TODO put this Value into an anonymous Decl and then export it.4941 else => return sema.fail(block, operand_src, "TODO implement exporting arbitrary Value objects", .{}), // TODO put this Value into an anonymous Decl and then export it.
...@@ -17029,6 +17041,11 @@ fn checkVectorizableBinaryOperands(...@@ -17029,6 +17041,11 @@ fn checkVectorizableBinaryOperands(
17029 }17041 }
17030}17042}
1703117043
17044fn maybeOptionsSrc(sema: *Sema, block: *Block, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc {
17045 if (base_src == .unneeded) return .unneeded;
17046 return Module.optionsSrc(sema.gpa, sema.mod.declPtr(block.src_decl), base_src, wanted);
17047}
17048
17032fn resolveExportOptions(17049fn resolveExportOptions(
17033 sema: *Sema,17050 sema: *Sema,
17034 block: *Block,17051 block: *Block,
...@@ -17039,34 +17056,39 @@ fn resolveExportOptions(...@@ -17039,34 +17056,39 @@ fn resolveExportOptions(
17039 const air_ref = try sema.resolveInst(zir_ref);17056 const air_ref = try sema.resolveInst(zir_ref);
17040 const options = try sema.coerce(block, export_options_ty, air_ref, src);17057 const options = try sema.coerce(block, export_options_ty, air_ref, src);
1704117058
17042 const name_operand = try sema.fieldVal(block, src, options, "name", src);17059 const name_src = sema.maybeOptionsSrc(block, src, "name");
17043 const name_val = try sema.resolveConstValue(block, src, name_operand, "name of exported value must be comptime known");17060 const linkage_src = sema.maybeOptionsSrc(block, src, "linkage");
17061 const section_src = sema.maybeOptionsSrc(block, src, "section");
17062 const visibility_src = sema.maybeOptionsSrc(block, src, "visibility");
17063
17064 const name_operand = try sema.fieldVal(block, src, options, "name", name_src);
17065 const name_val = try sema.resolveConstValue(block, name_src, name_operand, "name of exported value must be comptime known");
17044 const name_ty = Type.initTag(.const_slice_u8);17066 const name_ty = Type.initTag(.const_slice_u8);
17045 const name = try name_val.toAllocatedBytes(name_ty, sema.arena, sema.mod);17067 const name = try name_val.toAllocatedBytes(name_ty, sema.arena, sema.mod);
1704617068
17047 const linkage_operand = try sema.fieldVal(block, src, options, "linkage", src);17069 const linkage_operand = try sema.fieldVal(block, src, options, "linkage", linkage_src);
17048 const linkage_val = try sema.resolveConstValue(block, src, linkage_operand, "linkage of exported value must be comptime known");17070 const linkage_val = try sema.resolveConstValue(block, linkage_src, linkage_operand, "linkage of exported value must be comptime known");
17049 const linkage = linkage_val.toEnum(std.builtin.GlobalLinkage);17071 const linkage = linkage_val.toEnum(std.builtin.GlobalLinkage);
1705017072
17051 const section = try sema.fieldVal(block, src, options, "section", src);17073 const section = try sema.fieldVal(block, src, options, "section", section_src);
17052 const section_val = try sema.resolveConstValue(block, src, section, "linksection of exported value must be comptime known");17074 const section_val = try sema.resolveConstValue(block, section_src, section, "linksection of exported value must be comptime known");
1705317075
17054 const visibility_operand = try sema.fieldVal(block, src, options, "visibility", src);17076 const visibility_operand = try sema.fieldVal(block, src, options, "visibility", visibility_src);
17055 const visibility_val = try sema.resolveConstValue(block, src, visibility_operand, "visibility of exported value must be comptime known");17077 const visibility_val = try sema.resolveConstValue(block, visibility_src, visibility_operand, "visibility of exported value must be comptime known");
17056 const visibility = visibility_val.toEnum(std.builtin.SymbolVisibility);17078 const visibility = visibility_val.toEnum(std.builtin.SymbolVisibility);
1705717079
17058 if (name.len < 1) {17080 if (name.len < 1) {
17059 return sema.fail(block, src, "exported symbol name cannot be empty", .{});17081 return sema.fail(block, name_src, "exported symbol name cannot be empty", .{});
17060 }17082 }
1706117083
17062 if (visibility != .default and linkage == .Internal) {17084 if (visibility != .default and linkage == .Internal) {
17063 return sema.fail(block, src, "symbol '{s}' exported with internal linkage has non-default visibility {s}", .{17085 return sema.fail(block, visibility_src, "symbol '{s}' exported with internal linkage has non-default visibility {s}", .{
17064 name, @tagName(visibility),17086 name, @tagName(visibility),
17065 });17087 });
17066 }17088 }
1706717089
17068 if (!section_val.isNull()) {17090 if (!section_val.isNull()) {
17069 return sema.fail(block, src, "TODO: implement exporting with linksection", .{});17091 return sema.fail(block, section_src, "TODO: implement exporting with linksection", .{});
17070 }17092 }
1707117093
17072 return std.builtin.ExportOptions{17094 return std.builtin.ExportOptions{
...@@ -17805,80 +17827,113 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air....@@ -17805,80 +17827,113 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
17805 });17827 });
17806}17828}
1780717829
17808fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {17830fn resolveCallOptions(
17809 const tracy = trace(@src());17831 sema: *Sema,
17810 defer tracy.end();17832 block: *Block,
1781117833 src: LazySrcLoc,
17812 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;17834 zir_ref: Zir.Inst.Ref,
17813 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };17835 is_comptime: bool,
17814 const func_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };17836 is_nosuspend: bool,
17815 const args_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };17837 func: Air.Inst.Ref,
17816 const call_src = inst_data.src();17838 func_src: LazySrcLoc,
1781717839) CompileError!std.builtin.CallOptions.Modifier {
17818 const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;17840 const call_options_ty = try sema.getBuiltinType(block, src, "CallOptions");
17819 var func = try sema.resolveInst(extra.callee);17841 const air_ref = try sema.resolveInst(zir_ref);
17820 const options = try sema.resolveInst(extra.options);17842 const options = try sema.coerce(block, call_options_ty, air_ref, src);
17821 const args = try sema.resolveInst(extra.args);
17822
17823 const wanted_modifier: std.builtin.CallOptions.Modifier = modifier: {
17824 const call_options_ty = try sema.getBuiltinType(block, options_src, "CallOptions");
17825 const coerced_options = try sema.coerce(block, call_options_ty, options, options_src);
1782617843
17827 const modifier = try sema.fieldVal(block, options_src, coerced_options, "modifier", options_src);17844 const modifier_src = sema.maybeOptionsSrc(block, src, "modifier");
17828 const modifier_val = try sema.resolveConstValue(block, options_src, modifier, "call modifier must be comptime known");17845 const stack_src = sema.maybeOptionsSrc(block, src, "stack");
1782917846
17830 const stack = try sema.fieldVal(block, options_src, coerced_options, "stack", options_src);17847 const modifier = try sema.fieldVal(block, src, options, "modifier", modifier_src);
17831 const stack_val = try sema.resolveConstValue(block, options_src, stack, "call stack value must be comptime known");17848 const modifier_val = try sema.resolveConstValue(block, modifier_src, modifier, "call modifier must be comptime known");
17849 const wanted_modifier = modifier_val.toEnum(std.builtin.CallOptions.Modifier);
1783217850
17833 if (!stack_val.isNull()) {17851 const stack = try sema.fieldVal(block, src, options, "stack", stack_src);
17834 return sema.fail(block, options_src, "TODO: implement @call with stack", .{});17852 const stack_val = try sema.resolveConstValue(block, stack_src, stack, "call stack value must be comptime known");
17835 }
17836 break :modifier modifier_val.toEnum(std.builtin.CallOptions.Modifier);
17837 };
1783817853
17839 const is_comptime = extra.flags.is_comptime or block.is_comptime;17854 if (!stack_val.isNull()) {
17855 return sema.fail(block, stack_src, "TODO: implement @call with stack", .{});
17856 }
1784017857
17841 const modifier: std.builtin.CallOptions.Modifier = switch (wanted_modifier) {17858 switch (wanted_modifier) {
17842 // These can be upgraded to comptime or nosuspend calls.17859 // These can be upgraded to comptime or nosuspend calls.
17843 .auto, .never_tail, .no_async => m: {17860 .auto, .never_tail, .no_async => {
17844 if (is_comptime) {17861 if (is_comptime) {
17845 if (wanted_modifier == .never_tail) {17862 if (wanted_modifier == .never_tail) {
17846 return sema.fail(block, options_src, "unable to perform 'never_tail' call at compile-time", .{});17863 return sema.fail(block, modifier_src, "unable to perform 'never_tail' call at compile-time", .{});
17847 }17864 }
17848 break :m .compile_time;17865 return .compile_time;
17849 }17866 }
17850 if (extra.flags.is_nosuspend) {17867 if (is_nosuspend) {
17851 break :m .no_async;17868 return .no_async;
17852 }17869 }
17853 break :m wanted_modifier;17870 return wanted_modifier;
17854 },17871 },
17855 // These can be upgraded to comptime. nosuspend bit can be safely ignored.17872 // These can be upgraded to comptime. nosuspend bit can be safely ignored.
17856 .always_tail, .always_inline, .compile_time => m: {17873 .always_tail, .always_inline, .compile_time => {
17857 _ = (try sema.resolveDefinedValue(block, func_src, func)) orelse {17874 _ = (try sema.resolveDefinedValue(block, func_src, func)) orelse {
17858 return sema.fail(block, func_src, "modifier '{s}' requires a comptime-known function", .{@tagName(wanted_modifier)});17875 return sema.fail(block, func_src, "modifier '{s}' requires a comptime-known function", .{@tagName(wanted_modifier)});
17859 };17876 };
1786017877
17861 if (is_comptime) {17878 if (is_comptime) {
17862 break :m .compile_time;17879 return .compile_time;
17863 }17880 }
17864 break :m wanted_modifier;17881 return wanted_modifier;
17865 },17882 },
17866 .async_kw => m: {17883 .async_kw => {
17867 if (extra.flags.is_nosuspend) {17884 if (is_nosuspend) {
17868 return sema.fail(block, options_src, "modifier 'async_kw' cannot be used inside nosuspend block", .{});17885 return sema.fail(block, modifier_src, "modifier 'async_kw' cannot be used inside nosuspend block", .{});
17869 }17886 }
17870 if (is_comptime) {17887 if (is_comptime) {
17871 return sema.fail(block, options_src, "modifier 'async_kw' cannot be used in combination with comptime function call", .{});17888 return sema.fail(block, modifier_src, "modifier 'async_kw' cannot be used in combination with comptime function call", .{});
17872 }17889 }
17873 break :m wanted_modifier;17890 return wanted_modifier;
17874 },17891 },
17875 .never_inline => m: {17892 .never_inline => {
17876 if (is_comptime) {17893 if (is_comptime) {
17877 return sema.fail(block, options_src, "unable to perform 'never_inline' call at compile-time", .{});17894 return sema.fail(block, modifier_src, "unable to perform 'never_inline' call at compile-time", .{});
17878 }17895 }
17879 break :m wanted_modifier;17896 return wanted_modifier;
17880 },17897 },
17898 }
17899}
17900
17901fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
17902 const tracy = trace(@src());
17903 defer tracy.end();
17904
17905 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
17906 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
17907 const func_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
17908 const args_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
17909 const call_src = inst_data.src();
17910
17911 const extra = sema.code.extraData(Zir.Inst.BuiltinCall, inst_data.payload_index).data;
17912 var func = try sema.resolveInst(extra.callee);
17913 const modifier = sema.resolveCallOptions(
17914 block,
17915 .unneeded,
17916 extra.options,
17917 extra.flags.is_comptime,
17918 extra.flags.is_nosuspend,
17919 func,
17920 func_src,
17921 ) catch |err| switch (err) {
17922 error.NeededSourceLocation => {
17923 _ = try sema.resolveCallOptions(
17924 block,
17925 options_src,
17926 extra.options,
17927 extra.flags.is_comptime,
17928 extra.flags.is_nosuspend,
17929 func,
17930 func_src,
17931 );
17932 return error.AnalysisFail;
17933 },
17934 else => |e| return e,
17881 };17935 };
17936 const args = try sema.resolveInst(extra.args);
1788217937
17883 const args_ty = sema.typeOf(args);17938 const args_ty = sema.typeOf(args);
17884 if (!args_ty.isTuple() and args_ty.tag() != .empty_struct_literal) {17939 if (!args_ty.isTuple() and args_ty.tag() != .empty_struct_literal) {
...@@ -18579,6 +18634,36 @@ fn zirWasmMemoryGrow(...@@ -18579,6 +18634,36 @@ fn zirWasmMemoryGrow(
18579 });18634 });
18580}18635}
1858118636
18637fn resolvePrefetchOptions(
18638 sema: *Sema,
18639 block: *Block,
18640 src: LazySrcLoc,
18641 zir_ref: Zir.Inst.Ref,
18642) CompileError!std.builtin.PrefetchOptions {
18643 const options_ty = try sema.getBuiltinType(block, src, "PrefetchOptions");
18644 const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);
18645 const target = sema.mod.getTarget();
18646
18647 const rw_src = sema.maybeOptionsSrc(block, src, "rw");
18648 const locality_src = sema.maybeOptionsSrc(block, src, "locality");
18649 const cache_src = sema.maybeOptionsSrc(block, src, "cache");
18650
18651 const rw = try sema.fieldVal(block, src, options, "rw", rw_src);
18652 const rw_val = try sema.resolveConstValue(block, rw_src, rw, "prefetch read/write must be comptime known");
18653
18654 const locality = try sema.fieldVal(block, src, options, "locality", locality_src);
18655 const locality_val = try sema.resolveConstValue(block, locality_src, locality, "prefetch locality must be comptime known");
18656
18657 const cache = try sema.fieldVal(block, src, options, "cache", cache_src);
18658 const cache_val = try sema.resolveConstValue(block, cache_src, cache, "prefetch cache must be comptime known");
18659
18660 return std.builtin.PrefetchOptions{
18661 .rw = rw_val.toEnum(std.builtin.PrefetchOptions.Rw),
18662 .locality = @intCast(u2, locality_val.toUnsignedInt(target)),
18663 .cache = cache_val.toEnum(std.builtin.PrefetchOptions.Cache),
18664 };
18665}
18666
18582fn zirPrefetch(18667fn zirPrefetch(
18583 sema: *Sema,18668 sema: *Sema,
18584 block: *Block,18669 block: *Block,
...@@ -18587,32 +18672,25 @@ fn zirPrefetch(...@@ -18587,32 +18672,25 @@ fn zirPrefetch(
18587 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;18672 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
18588 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };18673 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
18589 const opts_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };18674 const opts_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
18590 const options_ty = try sema.getBuiltinType(block, opts_src, "PrefetchOptions");
18591 const ptr = try sema.resolveInst(extra.lhs);18675 const ptr = try sema.resolveInst(extra.lhs);
18592 try sema.checkPtrOperand(block, ptr_src, sema.typeOf(ptr));18676 try sema.checkPtrOperand(block, ptr_src, sema.typeOf(ptr));
18593 const options = try sema.coerce(block, options_ty, try sema.resolveInst(extra.rhs), opts_src);
18594 const target = sema.mod.getTarget();
18595
18596 const rw = try sema.fieldVal(block, opts_src, options, "rw", opts_src);
18597 const rw_val = try sema.resolveConstValue(block, opts_src, rw, "prefetch read/write must be comptime known");
18598 const rw_tag = rw_val.toEnum(std.builtin.PrefetchOptions.Rw);
18599
18600 const locality = try sema.fieldVal(block, opts_src, options, "locality", opts_src);
18601 const locality_val = try sema.resolveConstValue(block, opts_src, locality, "prefetch locality must be comptime known");
18602 const locality_int = @intCast(u2, locality_val.toUnsignedInt(target));
1860318677
18604 const cache = try sema.fieldVal(block, opts_src, options, "cache", opts_src);18678 const options = sema.resolvePrefetchOptions(block, .unneeded, extra.rhs) catch |err| switch (err) {
18605 const cache_val = try sema.resolveConstValue(block, opts_src, cache, "prefetch cache must be comptime known");18679 error.NeededSourceLocation => {
18606 const cache_tag = cache_val.toEnum(std.builtin.PrefetchOptions.Cache);18680 _ = try sema.resolvePrefetchOptions(block, opts_src, extra.rhs);
18681 return error.AnalysisFail;
18682 },
18683 else => |e| return e,
18684 };
1860718685
18608 if (!block.is_comptime) {18686 if (!block.is_comptime) {
18609 _ = try block.addInst(.{18687 _ = try block.addInst(.{
18610 .tag = .prefetch,18688 .tag = .prefetch,
18611 .data = .{ .prefetch = .{18689 .data = .{ .prefetch = .{
18612 .ptr = ptr,18690 .ptr = ptr,
18613 .rw = rw_tag,18691 .rw = options.rw,
18614 .locality = locality_int,18692 .locality = options.locality,
18615 .cache = cache_tag,18693 .cache = options.cache,
18616 } },18694 } },
18617 });18695 });
18618 }18696 }
...@@ -18620,71 +18698,93 @@ fn zirPrefetch(...@@ -18620,71 +18698,93 @@ fn zirPrefetch(
18620 return Air.Inst.Ref.void_value;18698 return Air.Inst.Ref.void_value;
18621}18699}
1862218700
18623fn zirBuiltinExtern(18701fn resolveExternOptions(
18624 sema: *Sema,18702 sema: *Sema,
18625 block: *Block,18703 block: *Block,
18626 extended: Zir.Inst.Extended.InstData,18704 src: LazySrcLoc,
18627) CompileError!Air.Inst.Ref {18705 zir_ref: Zir.Inst.Ref,
18628 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;18706) CompileError!std.builtin.ExternOptions {
18629 const src = LazySrcLoc.nodeOffset(extra.node);18707 const options_inst = try sema.resolveInst(zir_ref);
18630 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };18708 const extern_options_ty = try sema.getBuiltinType(block, src, "ExternOptions");
18631 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };18709 const options = try sema.coerce(block, extern_options_ty, options_inst, src);
18632
18633 var ty = try sema.resolveType(block, ty_src, extra.lhs);
18634 const options_inst = try sema.resolveInst(extra.rhs);
18635 const mod = sema.mod;18710 const mod = sema.mod;
1863618711
18637 const options = options: {18712 const name_src = sema.maybeOptionsSrc(block, src, "name");
18638 const extern_options_ty = try sema.getBuiltinType(block, options_src, "ExternOptions");18713 const library_src = sema.maybeOptionsSrc(block, src, "library");
18639 const options = try sema.coerce(block, extern_options_ty, options_inst, options_src);18714 const linkage_src = sema.maybeOptionsSrc(block, src, "linkage");
18715 const thread_local_src = sema.maybeOptionsSrc(block, src, "thread_local");
1864018716
18641 const name = try sema.fieldVal(block, options_src, options, "name", options_src);18717 const name_ref = try sema.fieldVal(block, src, options, "name", name_src);
18642 const name_val = try sema.resolveConstValue(block, options_src, name, "name of the extern symbol must be comptime known");18718 const name_val = try sema.resolveConstValue(block, name_src, name_ref, "name of the extern symbol must be comptime known");
18719 const name = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod);
1864318720
18644 const library_name_inst = try sema.fieldVal(block, options_src, options, "library_name", options_src);18721 const library_name_inst = try sema.fieldVal(block, src, options, "library_name", library_src);
18645 const library_name_val = try sema.resolveConstValue(block, options_src, library_name_inst, "library in which extern symbol is must be comptime known");18722 const library_name_val = try sema.resolveConstValue(block, library_src, library_name_inst, "library in which extern symbol is must be comptime known");
1864618723
18647 const linkage = try sema.fieldVal(block, options_src, options, "linkage", options_src);18724 const linkage_ref = try sema.fieldVal(block, src, options, "linkage", linkage_src);
18648 const linkage_val = try sema.resolveConstValue(block, options_src, linkage, "linkage of the extern symbol must be comptime known");18725 const linkage_val = try sema.resolveConstValue(block, linkage_src, linkage_ref, "linkage of the extern symbol must be comptime known");
18726 const linkage = linkage_val.toEnum(std.builtin.GlobalLinkage);
1864918727
18650 const is_thread_local = try sema.fieldVal(block, options_src, options, "is_thread_local", options_src);18728 const is_thread_local = try sema.fieldVal(block, src, options, "is_thread_local", thread_local_src);
18651 const is_thread_local_val = try sema.resolveConstValue(block, options_src, is_thread_local, "threadlocality of the extern symbol must be comptime known");18729 const is_thread_local_val = try sema.resolveConstValue(block, thread_local_src, is_thread_local, "threadlocality of the extern symbol must be comptime known");
1865218730
18653 var library_name: ?[]const u8 = null;18731 const library_name = if (!library_name_val.isNull()) blk: {
18654 if (!library_name_val.isNull()) {18732 const payload = library_name_val.castTag(.opt_payload).?.data;
18655 const payload = library_name_val.castTag(.opt_payload).?.data;18733 const library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod);
18656 library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod);18734 if (library_name.len == 0) {
18735 return sema.fail(block, library_src, "library name name cannot be empty", .{});
18657 }18736 }
18737 break :blk try sema.handleExternLibName(block, library_src, library_name);
18738 } else null;
1865818739
18659 break :options std.builtin.ExternOptions{18740 if (name.len == 0) {
18660 .name = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod),18741 return sema.fail(block, name_src, "extern symbol name cannot be empty", .{});
18661 .library_name = library_name,
18662 .linkage = linkage_val.toEnum(std.builtin.GlobalLinkage),
18663 .is_thread_local = is_thread_local_val.toBool(),
18664 };
18665 };
18666
18667 if (!ty.isPtrAtRuntime()) {
18668 return sema.fail(block, options_src, "expected (optional) pointer", .{});
18669 }18742 }
1867018743
18671 if (options.name.len == 0) {18744 if (linkage != .Weak and linkage != .Strong) {
18672 return sema.fail(block, options_src, "extern symbol name cannot be empty", .{});18745 return sema.fail(block, linkage_src, "extern symbol must use strong or weak linkage", .{});
18673 }18746 }
1867418747
18675 if (options.linkage != .Weak and options.linkage != .Strong) {18748 return std.builtin.ExternOptions{
18676 return sema.fail(block, options_src, "extern symbol must use strong or weak linkage", .{});18749 .name = name,
18750 .library_name = library_name,
18751 .linkage = linkage,
18752 .is_thread_local = is_thread_local_val.toBool(),
18753 };
18754}
18755
18756fn zirBuiltinExtern(
18757 sema: *Sema,
18758 block: *Block,
18759 extended: Zir.Inst.Extended.InstData,
18760) CompileError!Air.Inst.Ref {
18761 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
18762 const src = LazySrcLoc.nodeOffset(extra.node);
18763 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
18764 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
18765
18766 var ty = try sema.resolveType(block, ty_src, extra.lhs);
18767 if (!ty.isPtrAtRuntime()) {
18768 return sema.fail(block, ty_src, "expected (optional) pointer", .{});
18677 }18769 }
1867818770
18771 const options = sema.resolveExternOptions(block, .unneeded, extra.rhs) catch |err| switch (err) {
18772 error.NeededSourceLocation => {
18773 _ = try sema.resolveExternOptions(block, options_src, extra.rhs);
18774 return error.AnalysisFail;
18775 },
18776 else => |e| return e,
18777 };
18778
18679 if (options.linkage == .Weak and !ty.ptrAllowsZero()) {18779 if (options.linkage == .Weak and !ty.ptrAllowsZero()) {
18680 ty = try Type.optional(sema.arena, ty);18780 ty = try Type.optional(sema.arena, ty);
18681 }18781 }
1868218782
18683 // TODO check duplicate extern18783 // TODO check duplicate extern
1868418784
18685 const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node, null);18785 const new_decl_index = try sema.mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node, null);
18686 errdefer mod.destroyDecl(new_decl_index);18786 errdefer sema.mod.destroyDecl(new_decl_index);
18687 const new_decl = mod.declPtr(new_decl_index);18787 const new_decl = sema.mod.declPtr(new_decl_index);
18688 new_decl.name = try sema.gpa.dupeZ(u8, options.name);18788 new_decl.name = try sema.gpa.dupeZ(u8, options.name);
1868918789
18690 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);18790 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
...@@ -18704,13 +18804,6 @@ fn zirBuiltinExtern(...@@ -18704,13 +18804,6 @@ fn zirBuiltinExtern(
18704 .lib_name = null,18804 .lib_name = null,
18705 };18805 };
1870618806
18707 if (options.library_name) |library_name| {
18708 if (library_name.len == 0) {
18709 return sema.fail(block, options_src, "library name name cannot be empty", .{});
18710 }
18711 new_var.lib_name = try sema.handleExternLibName(block, options_src, library_name);
18712 }
18713
18714 new_decl.src_line = sema.owner_decl.src_line;18807 new_decl.src_line = sema.owner_decl.src_line;
18715 new_decl.ty = try ty.copy(new_decl_arena_allocator);18808 new_decl.ty = try ty.copy(new_decl_arena_allocator);
18716 new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var);18809 new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var);
...@@ -18718,7 +18811,7 @@ fn zirBuiltinExtern(...@@ -18718,7 +18811,7 @@ fn zirBuiltinExtern(
18718 new_decl.@"linksection" = null;18811 new_decl.@"linksection" = null;
18719 new_decl.has_tv = true;18812 new_decl.has_tv = true;
18720 new_decl.analysis = .complete;18813 new_decl.analysis = .complete;
18721 new_decl.generation = mod.generation;18814 new_decl.generation = sema.mod.generation;
1872218815
18723 const arena_state = try new_decl_arena_allocator.create(std.heap.ArenaAllocator.State);18816 const arena_state = try new_decl_arena_allocator.create(std.heap.ArenaAllocator.State);
18724 arena_state.* = new_decl_arena.state;18817 arena_state.* = new_decl_arena.state;
test/cases/compile_errors/bad_usage_of_call.zig+2-2
...@@ -28,8 +28,8 @@ fn baz2() void {}...@@ -28,8 +28,8 @@ fn baz2() void {}
28// target=native28// target=native
29//29//
30// :2:21: error: expected a tuple, found 'void'30// :2:21: error: expected a tuple, found 'void'
31// :5:21: error: unable to perform 'never_inline' call at compile-time31// :5:33: error: unable to perform 'never_inline' call at compile-time
32// :8:21: error: unable to perform 'never_tail' call at compile-time32// :8:33: error: unable to perform 'never_tail' call at compile-time
33// :11:5: error: no-inline call of inline function33// :11:5: error: no-inline call of inline function
34// :15:43: error: modifier 'compile_time' requires a comptime-known function34// :15:43: error: modifier 'compile_time' requires a comptime-known function
35// :19:44: error: modifier 'always_inline' requires a comptime-known function35// :19:44: error: modifier 'always_inline' requires a comptime-known function
test/cases/compile_errors/error_in_call_builtin_args.zig created+15
...@@ -0,0 +1,15 @@
1fn foo(_: u32, _: u32) void {}
2pub export fn entry() void {
3 @call(.{}, foo, .{ 12, 12.34 });
4}
5pub export fn entry1() void {
6 const args = .{ 12, 12.34 };
7 @call(.{}, foo, args);
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :3:28: error: fractional component prevents float value '12.34' from coercion to type 'u32'
15// :7:21: error: fractional component prevents float value '12.34' from coercion to type 'u32'
test/cases/compile_errors/export_with_empty_name_string.zig+1-1
...@@ -7,4 +7,4 @@ comptime {...@@ -7,4 +7,4 @@ comptime {
7// backend=llvm7// backend=llvm
8// target=native8// target=native
9//9//
10// :3:21: error: exported symbol name cannot be empty10// :3:24: error: exported symbol name cannot be empty
test/cases/compile_errors/invalid_identifiers.zig created+33
...@@ -0,0 +1,33 @@
1extern "" var a: u32;
2extern "" fn b() void;
3
4extern "\x00" var c: u32;
5extern "\x00" fn d() void;
6
7test "" {}
8test "\x00" {}
9
10const e = @import("");
11const f = @import("\x00");
12
13comptime {
14 const @"" = undefined;
15}
16comptime {
17 const @"\x00" = undefined;
18}
19
20// error
21// backend=stage2
22// target=native
23//
24// :1:8: error: library name cannot be empty
25// :2:8: error: library name cannot be empty
26// :4:8: error: library name cannot contain null bytes
27// :5:8: error: library name cannot contain null bytes
28// :7:6: error: empty test name must be omitted
29// :8:6: error: test name cannot contain null bytes
30// :10:19: error: import path cannot be empty
31// :11:19: error: import path cannot contain null bytes
32// :14:11: error: identifier cannot be empty
33// :17:11: error: identifier cannot contain null bytes
test/cases/compile_errors/stage1/obj/wrong_panic_signature_runtime_function.zig+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1test "" {}1test {}
22
3pub fn panic() void {}3pub fn panic() void {}
44
test/standalone/issue_9812/main.zig+1-1
...@@ -14,7 +14,7 @@ const Error = error{...@@ -14,7 +14,7 @@ const Error = error{
14 InvalidCmdLine,14 InvalidCmdLine,
15};15};
1616
17test "" {17test {
18 const allocator = std.heap.c_allocator;18 const allocator = std.heap.c_allocator;
1919
20 const args = try std.process.argsAlloc(allocator);20 const args = try std.process.argsAlloc(allocator);