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

Stage2: explain why value must be comptime known
This commit is contained in:
Veikka Tuominen 2022-07-22 13:07:32 +03:00 committed by GitHub
commit 8e75ba653b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
100 changed files with 1829 additions and 1004 deletions

View File

@ -11,6 +11,7 @@ const InstallDirectoryOptions = std.build.InstallDirectoryOptions;
const assert = std.debug.assert;
const zig_version = std.builtin.Version{ .major = 0, .minor = 10, .patch = 0 };
const stack_size = 32 * 1024 * 1024;
pub fn build(b: *Builder) !void {
b.setPreferredReleaseMode(.ReleaseFast);
@ -41,6 +42,7 @@ pub fn build(b: *Builder) !void {
const toolchain_step = b.step("test-toolchain", "Run the tests for the toolchain");
var test_cases = b.addTest("src/test.zig");
test_cases.stack_size = stack_size;
test_cases.setBuildMode(mode);
test_cases.addPackagePath("test_cases", "test/cases.zig");
test_cases.single_threaded = single_threaded;
@ -141,6 +143,7 @@ pub fn build(b: *Builder) !void {
};
const exe = b.addExecutable("zig", main_file);
exe.stack_size = stack_size;
exe.strip = strip;
exe.build_id = b.option(bool, "build-id", "Include a build id note") orelse false;
exe.install();

View File

@ -1347,7 +1347,7 @@ fn arrayInitExpr(
}
}
const array_type_inst = try typeExpr(gz, scope, array_init.ast.type_expr);
_ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, node);
_ = try gz.addUnNode(.validate_array_init_ty, array_type_inst, array_init.ast.type_expr);
break :inst .{
.array = array_type_inst,
.elem = .none,
@ -2332,7 +2332,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
.err_union_code,
.err_union_code_ptr,
.ptr_type,
.ptr_type_simple,
.overflow_arithmetic_ptr,
.enum_literal,
.merge_error_sets,
.error_union_type,
@ -3110,24 +3110,6 @@ fn ptrType(
const elem_type = try typeExpr(gz, scope, ptr_info.ast.child_type);
const simple = ptr_info.ast.align_node == 0 and
ptr_info.ast.addrspace_node == 0 and
ptr_info.ast.sentinel == 0 and
ptr_info.ast.bit_range_start == 0;
if (simple) {
const result = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
.ptr_type_simple = .{
.is_allowzero = ptr_info.allowzero_token != null,
.is_mutable = ptr_info.const_token == null,
.is_volatile = ptr_info.volatile_token != null,
.size = ptr_info.size,
.elem_type = elem_type,
},
} });
return rvalue(gz, rl, result, node);
}
var sentinel_ref: Zir.Inst.Ref = .none;
var align_ref: Zir.Inst.Ref = .none;
var addrspace_ref: Zir.Inst.Ref = .none;
@ -3160,7 +3142,10 @@ fn ptrType(
try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.PtrType).Struct.fields.len +
trailing_count);
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.PtrType{ .elem_type = elem_type });
const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.PtrType{
.elem_type = elem_type,
.src_node = gz.nodeIndexToRelative(node),
});
if (sentinel_ref != .none) {
gz.astgen.extra.appendAssumeCapacity(@enumToInt(sentinel_ref));
}
@ -4314,7 +4299,7 @@ fn unionDeclInner(
members: []const Ast.Node.Index,
layout: std.builtin.Type.ContainerLayout,
arg_node: Ast.Node.Index,
have_auto_enum: bool,
auto_enum_tok: ?Ast.TokenIndex,
) InnerError!Zir.Inst.Ref {
const decl_inst = try gz.reserveInstructionIndex();
@ -4348,6 +4333,15 @@ fn unionDeclInner(
const decl_count = try astgen.scanDecls(&namespace, members);
const field_count = @intCast(u32, members.len - decl_count);
if (layout != .Auto and (auto_enum_tok != null or arg_node != 0)) {
const layout_str = if (layout == .Extern) "extern" else "packed";
if (arg_node != 0) {
return astgen.failNode(arg_node, "{s} union does not support enum tag type", .{layout_str});
} else {
return astgen.failTok(auto_enum_tok.?, "{s} union does not support enum tag type", .{layout_str});
}
}
const arg_inst: Zir.Inst.Ref = if (arg_node != 0)
try typeExpr(&block_scope, &namespace.base, arg_node)
else
@ -4382,7 +4376,7 @@ fn unionDeclInner(
if (have_type) {
const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
wip_members.appendToField(@enumToInt(field_type));
} else if (arg_inst == .none and !have_auto_enum) {
} else if (arg_inst == .none and auto_enum_tok == null) {
return astgen.failNode(member_node, "union field missing type", .{});
}
if (have_align) {
@ -4404,7 +4398,7 @@ fn unionDeclInner(
},
);
}
if (!have_auto_enum) {
if (auto_enum_tok == null) {
return astgen.failNodeNotes(
node,
"explicitly valued tagged union requires inferred enum tag type",
@ -4440,7 +4434,7 @@ fn unionDeclInner(
.body_len = body_len,
.fields_len = field_count,
.decls_len = decl_count,
.auto_enum_tag = have_auto_enum,
.auto_enum_tag = auto_enum_tok != null,
});
wip_members.finishBits(bits_per_field);
@ -4496,9 +4490,7 @@ fn containerDecl(
else => unreachable,
} else std.builtin.Type.ContainerLayout.Auto;
const have_auto_enum = container_decl.ast.enum_token != null;
const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, have_auto_enum);
const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, container_decl.ast.enum_token);
return rvalue(gz, rl, result, node);
},
.keyword_enum => {
@ -4732,7 +4724,10 @@ fn containerDecl(
defer wip_members.deinit();
for (container_decl.ast.members) |member_node| {
_ = try containerMember(gz, &namespace.base, &wip_members, member_node);
const res = try containerMember(gz, &namespace.base, &wip_members, member_node);
if (res == .field) {
return astgen.failNode(member_node, "opaque types cannot have fields", .{});
}
}
try gz.setOpaque(decl_inst, .{
@ -7588,15 +7583,7 @@ fn builtinCall(
.shl_with_overflow => {
const int_type = try typeExpr(gz, scope, params[0]);
const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]);
const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
.ptr_type_simple = .{
.is_allowzero = false,
.is_mutable = true,
.is_volatile = false,
.size = .One,
.elem_type = int_type,
},
} });
const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
const rhs = try expr(gz, scope, .{ .ty = log2_int_type }, params[2]);
const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);
@ -7987,15 +7974,7 @@ fn overflowArithmetic(
tag: Zir.Inst.Extended,
) InnerError!Zir.Inst.Ref {
const int_type = try typeExpr(gz, scope, params[0]);
const ptr_type = try gz.add(.{ .tag = .ptr_type_simple, .data = .{
.ptr_type_simple = .{
.is_allowzero = false,
.is_mutable = true,
.is_volatile = false,
.size = .One,
.elem_type = int_type,
},
} });
const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
const lhs = try expr(gz, scope, .{ .ty = int_type }, params[1]);
const rhs = try expr(gz, scope, .{ .ty = int_type }, params[2]);
const ptr = try expr(gz, scope, .{ .ty = ptr_type }, params[3]);

View File

@ -2348,7 +2348,92 @@ pub const SrcLoc = struct {
}
} else unreachable;
},
.node_offset_switch_prong_capture => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const case_node = src_loc.declRelativeToNodeIndex(node_off);
const node_tags = tree.nodes.items(.tag);
const case = switch (node_tags[case_node]) {
.switch_case_one => tree.switchCaseOne(case_node),
.switch_case => tree.switchCase(case_node),
else => unreachable,
};
const start_tok = case.payload_token.?;
const token_tags = tree.tokens.items(.tag);
const end_tok = switch (token_tags[start_tok]) {
.asterisk => start_tok + 1,
else => start_tok,
};
const start = tree.tokens.items(.start)[start_tok];
const end_start = tree.tokens.items(.start)[end_tok];
const end = end_start + @intCast(u32, tree.tokenSlice(end_tok).len);
return Span{ .start = start, .end = end, .main = start };
},
.node_offset_fn_type_align => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
const node = src_loc.declRelativeToNodeIndex(node_off);
var params: [1]Ast.Node.Index = undefined;
const full = switch (node_tags[node]) {
.fn_proto_simple => tree.fnProtoSimple(&params, node),
.fn_proto_multi => tree.fnProtoMulti(node),
.fn_proto_one => tree.fnProtoOne(&params, node),
.fn_proto => tree.fnProto(node),
.fn_decl => switch (node_tags[node_datas[node].lhs]) {
.fn_proto_simple => tree.fnProtoSimple(&params, node_datas[node].lhs),
.fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
.fn_proto_one => tree.fnProtoOne(&params, node_datas[node].lhs),
.fn_proto => tree.fnProto(node_datas[node].lhs),
else => unreachable,
},
else => unreachable,
};
return nodeToSpan(tree, full.ast.align_expr);
},
.node_offset_fn_type_addrspace => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
const node = src_loc.declRelativeToNodeIndex(node_off);
var params: [1]Ast.Node.Index = undefined;
const full = switch (node_tags[node]) {
.fn_proto_simple => tree.fnProtoSimple(&params, node),
.fn_proto_multi => tree.fnProtoMulti(node),
.fn_proto_one => tree.fnProtoOne(&params, node),
.fn_proto => tree.fnProto(node),
.fn_decl => switch (node_tags[node_datas[node].lhs]) {
.fn_proto_simple => tree.fnProtoSimple(&params, node_datas[node].lhs),
.fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
.fn_proto_one => tree.fnProtoOne(&params, node_datas[node].lhs),
.fn_proto => tree.fnProto(node_datas[node].lhs),
else => unreachable,
},
else => unreachable,
};
return nodeToSpan(tree, full.ast.addrspace_expr);
},
.node_offset_fn_type_section => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
const node = src_loc.declRelativeToNodeIndex(node_off);
var params: [1]Ast.Node.Index = undefined;
const full = switch (node_tags[node]) {
.fn_proto_simple => tree.fnProtoSimple(&params, node),
.fn_proto_multi => tree.fnProtoMulti(node),
.fn_proto_one => tree.fnProtoOne(&params, node),
.fn_proto => tree.fnProto(node),
.fn_decl => switch (node_tags[node_datas[node].lhs]) {
.fn_proto_simple => tree.fnProtoSimple(&params, node_datas[node].lhs),
.fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
.fn_proto_one => tree.fnProtoOne(&params, node_datas[node].lhs),
.fn_proto => tree.fnProto(node_datas[node].lhs),
else => unreachable,
},
else => unreachable,
};
return nodeToSpan(tree, full.ast.section_expr);
},
.node_offset_fn_type_cc => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_datas = tree.nodes.items(.data);
@ -2374,6 +2459,7 @@ pub const SrcLoc = struct {
.node_offset_fn_type_ret_ty => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
const node = src_loc.declRelativeToNodeIndex(node_off);
var params: [1]Ast.Node.Index = undefined;
@ -2382,10 +2468,55 @@ pub const SrcLoc = struct {
.fn_proto_multi => tree.fnProtoMulti(node),
.fn_proto_one => tree.fnProtoOne(&params, node),
.fn_proto => tree.fnProto(node),
.fn_decl => blk: {
const fn_proto = node_datas[node].lhs;
break :blk switch (node_tags[fn_proto]) {
.fn_proto_simple => tree.fnProtoSimple(&params, fn_proto),
.fn_proto_multi => tree.fnProtoMulti(fn_proto),
.fn_proto_one => tree.fnProtoOne(&params, fn_proto),
.fn_proto => tree.fnProto(fn_proto),
else => unreachable,
};
},
else => unreachable,
};
return nodeToSpan(tree, full.ast.return_type);
},
.node_offset_param => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const token_tags = tree.tokens.items(.tag);
const node = src_loc.declRelativeToNodeIndex(node_off);
var first_tok = tree.firstToken(node);
while (true) switch (token_tags[first_tok - 1]) {
.colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
else => break,
};
return tokensToSpan(
tree,
first_tok,
tree.lastToken(node),
first_tok,
);
},
.token_offset_param => |token_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const token_tags = tree.tokens.items(.tag);
const main_token = tree.nodes.items(.main_token)[src_loc.parent_decl_node];
const tok_index = @bitCast(Ast.TokenIndex, token_off + @bitCast(i32, main_token));
var first_tok = tok_index;
while (true) switch (token_tags[first_tok - 1]) {
.colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1,
else => break,
};
return tokensToSpan(
tree,
first_tok,
tok_index,
first_tok,
);
},
.node_offset_anyframe_type => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
@ -2466,6 +2597,113 @@ pub const SrcLoc = struct {
return nodeToSpan(tree, node_datas[node].lhs);
},
.node_offset_ptr_elem => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
.ptr_type => tree.ptrType(parent_node),
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
else => unreachable,
};
return nodeToSpan(tree, full.ast.child_type);
},
.node_offset_ptr_sentinel => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
.ptr_type => tree.ptrType(parent_node),
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
else => unreachable,
};
return nodeToSpan(tree, full.ast.sentinel);
},
.node_offset_ptr_align => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
.ptr_type => tree.ptrType(parent_node),
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
else => unreachable,
};
return nodeToSpan(tree, full.ast.align_node);
},
.node_offset_ptr_addrspace => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
.ptr_type => tree.ptrType(parent_node),
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
else => unreachable,
};
return nodeToSpan(tree, full.ast.addrspace_node);
},
.node_offset_ptr_bitoffset => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
.ptr_type => tree.ptrType(parent_node),
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
else => unreachable,
};
return nodeToSpan(tree, full.ast.bit_range_start);
},
.node_offset_ptr_hostsize => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
const full: Ast.full.PtrType = switch (node_tags[parent_node]) {
.ptr_type_aligned => tree.ptrTypeAligned(parent_node),
.ptr_type_sentinel => tree.ptrTypeSentinel(parent_node),
.ptr_type => tree.ptrType(parent_node),
.ptr_type_bit_range => tree.ptrTypeBitRange(parent_node),
else => unreachable,
};
return nodeToSpan(tree, full.ast.bit_range_end);
},
.node_offset_container_tag => |node_off| {
const tree = try src_loc.file_scope.getTree(gpa);
const node_tags = tree.nodes.items(.tag);
const parent_node = src_loc.declRelativeToNodeIndex(node_off);
switch (node_tags[parent_node]) {
.container_decl_arg, .container_decl_arg_trailing => {
const full = tree.containerDeclArg(parent_node);
return nodeToSpan(tree, full.ast.arg);
},
.tagged_union_enum_tag, .tagged_union_enum_tag_trailing => {
const full = tree.taggedUnionEnumTag(parent_node);
return tokensToSpan(
tree,
tree.firstToken(full.ast.arg) - 2,
tree.lastToken(full.ast.arg) + 1,
tree.nodes.items(.main_token)[full.ast.arg],
);
},
else => unreachable,
}
},
}
}
@ -2694,6 +2932,27 @@ pub const LazySrcLoc = union(enum) {
/// range nodes. The error applies to all of them.
/// The Decl is determined contextually.
node_offset_switch_range: i32,
/// The source location points to the capture of a switch_prong.
/// The Decl is determined contextually.
node_offset_switch_prong_capture: i32,
/// The source location points to the align expr of a function type
/// expression, found by taking this AST node index offset from the containing
/// Decl AST node, which points to a function type AST node. Next, navigate to
/// the calling convention node.
/// The Decl is determined contextually.
node_offset_fn_type_align: i32,
/// The source location points to the addrspace expr of a function type
/// expression, found by taking this AST node index offset from the containing
/// Decl AST node, which points to a function type AST node. Next, navigate to
/// the calling convention node.
/// The Decl is determined contextually.
node_offset_fn_type_addrspace: i32,
/// The source location points to the linksection expr of a function type
/// expression, found by taking this AST node index offset from the containing
/// Decl AST node, which points to a function type AST node. Next, navigate to
/// the calling convention node.
/// The Decl is determined contextually.
node_offset_fn_type_section: i32,
/// The source location points to the calling convention of a function type
/// expression, found by taking this AST node index offset from the containing
/// Decl AST node, which points to a function type AST node. Next, navigate to
@ -2706,6 +2965,8 @@ pub const LazySrcLoc = union(enum) {
/// the return type node.
/// The Decl is determined contextually.
node_offset_fn_type_ret_ty: i32,
node_offset_param: i32,
token_offset_param: i32,
/// The source location points to the type expression of an `anyframe->T`
/// expression, found by taking this AST node index offset from the containing
/// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate
@ -2739,6 +3000,27 @@ pub const LazySrcLoc = union(enum) {
/// The source location points to the operand of an unary expression.
/// The Decl is determined contextually.
node_offset_un_op: i32,
/// The source location points to the elem type of a pointer.
/// The Decl is determined contextually.
node_offset_ptr_elem: i32,
/// The source location points to the sentinel of a pointer.
/// The Decl is determined contextually.
node_offset_ptr_sentinel: i32,
/// The source location points to the align expr of a pointer.
/// The Decl is determined contextually.
node_offset_ptr_align: i32,
/// The source location points to the addrspace expr of a pointer.
/// The Decl is determined contextually.
node_offset_ptr_addrspace: i32,
/// The source location points to the bit-offset of a pointer.
/// The Decl is determined contextually.
node_offset_ptr_bitoffset: i32,
/// The source location points to the host size of a pointer.
/// The Decl is determined contextually.
node_offset_ptr_hostsize: i32,
/// The source location points to the tag type of an union or an enum.
/// The Decl is determined contextually.
node_offset_container_tag: i32,
pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease;
@ -2795,14 +3077,27 @@ pub const LazySrcLoc = union(enum) {
.node_offset_switch_operand,
.node_offset_switch_special_prong,
.node_offset_switch_range,
.node_offset_switch_prong_capture,
.node_offset_fn_type_align,
.node_offset_fn_type_addrspace,
.node_offset_fn_type_section,
.node_offset_fn_type_cc,
.node_offset_fn_type_ret_ty,
.node_offset_param,
.token_offset_param,
.node_offset_anyframe_type,
.node_offset_lib_name,
.node_offset_array_type_len,
.node_offset_array_type_sentinel,
.node_offset_array_type_elem,
.node_offset_un_op,
.node_offset_ptr_elem,
.node_offset_ptr_sentinel,
.node_offset_ptr_align,
.node_offset_ptr_addrspace,
.node_offset_ptr_bitoffset,
.node_offset_ptr_hostsize,
.node_offset_container_tag,
=> .{
.file_scope = decl.getFileScope(),
.parent_decl_node = decl.src_node,
@ -3957,18 +4252,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null);
defer wip_captures.deinit();
var block_scope: Sema.Block = .{
.parent = null,
.sema = &sema,
.src_decl = new_decl_index,
.namespace = &struct_obj.namespace,
.wip_capture_scope = wip_captures.scope,
.instructions = .{},
.inlining = null,
.is_comptime = true,
};
defer block_scope.instructions.deinit(gpa);
if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj)) |_| {
try wip_captures.finalize();
new_decl.analysis = .complete;
@ -4077,7 +4360,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
try wip_captures.finalize();
const src = LazySrcLoc.nodeOffset(0);
const decl_tv = try sema.resolveInstValue(&block_scope, src, result_ref);
const decl_tv = try sema.resolveInstValue(&block_scope, .unneeded, result_ref, undefined);
const decl_align: u32 = blk: {
const align_ref = decl.zirAlignRef();
if (align_ref == .none) break :blk 0;
@ -4086,7 +4369,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
const decl_linksection: ?[*:0]const u8 = blk: {
const linksection_ref = decl.zirLinksectionRef();
if (linksection_ref == .none) break :blk null;
const bytes = try sema.resolveConstString(&block_scope, src, linksection_ref);
const bytes = try sema.resolveConstString(&block_scope, src, linksection_ref, "linksection must be comptime known");
break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr;
};
const target = sema.mod.getTarget();
@ -4518,7 +4801,7 @@ pub fn scanNamespace(
extra_start: usize,
decls_len: u32,
parent_decl: *Decl,
) SemaError!usize {
) Allocator.Error!usize {
const tracy = trace(@src());
defer tracy.end();
@ -4565,7 +4848,7 @@ const ScanDeclIter = struct {
unnamed_test_index: usize = 0,
};
fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!void {
fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Error!void {
const tracy = trace(@src());
defer tracy.end();
@ -5382,6 +5665,7 @@ pub const SwitchProngSrc = union(enum) {
scalar: u32,
multi: Multi,
range: Multi,
multi_capture: u32,
pub const Multi = struct {
prong: u32,
@ -5437,6 +5721,9 @@ pub const SwitchProngSrc = union(enum) {
.scalar => |i| if (!is_multi and i == scalar_i) return LazySrcLoc.nodeOffset(
decl.nodeIndexToRelative(case.ast.values[0]),
),
.multi_capture => |i| if (is_multi and i == multi_i) {
return LazySrcLoc{ .node_offset_switch_prong_capture = decl.nodeIndexToRelative(case_node) };
},
.multi => |s| if (is_multi and s.prong == multi_i) {
var item_i: u32 = 0;
for (case.ast.values) |item_node| {
@ -5578,6 +5865,77 @@ fn queryFieldSrc(
unreachable;
}
pub fn paramSrc(
func_node_offset: i32,
gpa: Allocator,
decl: *Decl,
param_i: usize,
) LazySrcLoc {
@setCold(true);
const tree = decl.getFileScope().getTree(gpa) catch |err| {
// In this case we emit a warning + a less precise source location.
log.warn("unable to load {s}: {s}", .{
decl.getFileScope().sub_file_path, @errorName(err),
});
return LazySrcLoc.nodeOffset(0);
};
const node_datas = tree.nodes.items(.data);
const node_tags = tree.nodes.items(.tag);
const node = decl.relativeToNodeIndex(func_node_offset);
var params: [1]Ast.Node.Index = undefined;
const full = switch (node_tags[node]) {
.fn_proto_simple => tree.fnProtoSimple(&params, node),
.fn_proto_multi => tree.fnProtoMulti(node),
.fn_proto_one => tree.fnProtoOne(&params, node),
.fn_proto => tree.fnProto(node),
.fn_decl => switch (node_tags[node_datas[node].lhs]) {
.fn_proto_simple => tree.fnProtoSimple(&params, node_datas[node].lhs),
.fn_proto_multi => tree.fnProtoMulti(node_datas[node].lhs),
.fn_proto_one => tree.fnProtoOne(&params, node_datas[node].lhs),
.fn_proto => tree.fnProto(node_datas[node].lhs),
else => unreachable,
},
else => unreachable,
};
var it = full.iterate(tree);
while (true) {
if (it.param_i == param_i) {
const param = it.next().?;
if (param.anytype_ellipsis3) |some| {
const main_token = tree.nodes.items(.main_token)[decl.src_node];
return .{ .token_offset_param = @bitCast(i32, some) - @bitCast(i32, main_token) };
}
return .{ .node_offset_param = decl.nodeIndexToRelative(param.type_expr) };
}
_ = it.next();
}
}
pub fn argSrc(
call_node_offset: i32,
gpa: Allocator,
decl: *Decl,
arg_i: usize,
) LazySrcLoc {
@setCold(true);
const tree = decl.getFileScope().getTree(gpa) catch |err| {
// In this case we emit a warning + a less precise source location.
log.warn("unable to load {s}: {s}", .{
decl.getFileScope().sub_file_path, @errorName(err),
});
return LazySrcLoc.nodeOffset(0);
};
const node_tags = tree.nodes.items(.tag);
const node = decl.relativeToNodeIndex(call_node_offset);
var args: [1]Ast.Node.Index = undefined;
const full = switch (node_tags[node]) {
.call_one, .call_one_comma, .async_call_one, .async_call_one_comma => tree.callOne(&args, node),
.call, .call_comma, .async_call, .async_call_comma => tree.callFull(node),
else => unreachable,
};
return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(full.ast.params[arg_i]));
}
/// Called from `performAllTheWork`, after all AstGen workers have finished,
/// and before the main semantic analysis loop begins.
pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {

File diff suppressed because it is too large Load Diff

View File

@ -534,9 +534,9 @@ pub const Inst = struct {
/// Obtains the return type of the in-scope function.
/// Uses the `node` union field.
ret_type,
/// Create a pointer type that does not have a sentinel, alignment, address space, or bit range specified.
/// Uses the `ptr_type_simple` union field.
ptr_type_simple,
/// Create a pointer type for overflow arithmetic.
/// TODO remove when doing https://github.com/ziglang/zig/issues/10248
overflow_arithmetic_ptr,
/// Create a pointer type which can have a sentinel, alignment, address space, and/or bit range.
/// Uses the `ptr_type` union field.
ptr_type,
@ -1121,7 +1121,7 @@ pub const Inst = struct {
.err_union_code,
.err_union_code_ptr,
.ptr_type,
.ptr_type_simple,
.overflow_arithmetic_ptr,
.ensure_err_payload_void,
.enum_literal,
.merge_error_sets,
@ -1417,7 +1417,7 @@ pub const Inst = struct {
.err_union_code,
.err_union_code_ptr,
.ptr_type,
.ptr_type_simple,
.overflow_arithmetic_ptr,
.enum_literal,
.merge_error_sets,
.error_union_type,
@ -1659,7 +1659,7 @@ pub const Inst = struct {
.ret_err_value_code = .str_tok,
.ret_ptr = .node,
.ret_type = .node,
.ptr_type_simple = .ptr_type_simple,
.overflow_arithmetic_ptr = .un_node,
.ptr_type = .ptr_type,
.slice_start = .pl_node,
.slice_end = .pl_node,
@ -2499,13 +2499,6 @@ pub const Inst = struct {
node: i32,
int: u64,
float: f64,
ptr_type_simple: struct {
is_allowzero: bool,
is_mutable: bool,
is_volatile: bool,
size: std.builtin.Type.Pointer.Size,
elem_type: Ref,
},
ptr_type: struct {
flags: packed struct {
is_allowzero: bool,
@ -2608,7 +2601,6 @@ pub const Inst = struct {
node,
int,
float,
ptr_type_simple,
ptr_type,
int_type,
bool_br,
@ -2869,6 +2861,7 @@ pub const Inst = struct {
/// 4. host_size: Ref // if `has_bit_range` flag is set
pub const PtrType = struct {
elem_type: Ref,
src_node: i32,
};
pub const ArrayTypeSentinel = struct {

View File

@ -233,6 +233,7 @@ const Writer = struct {
.validate_struct_init_ty,
.make_ptr_const,
.validate_deref,
.overflow_arithmetic_ptr,
=> try self.writeUnNode(stream, inst),
.ref,
@ -247,7 +248,6 @@ const Writer = struct {
.array_type_sentinel => try self.writeArrayTypeSentinel(stream, inst),
.param_type => try self.writeParamType(stream, inst),
.ptr_type_simple => try self.writePtrTypeSimple(stream, inst),
.ptr_type => try self.writePtrType(stream, inst),
.int => try self.writeInt(stream, inst),
.int_big => try self.writeIntBig(stream, inst),
@ -601,24 +601,6 @@ const Writer = struct {
try stream.print(", {d})", .{inst_data.param_index});
}
fn writePtrTypeSimple(
self: *Writer,
stream: anytype,
inst: Zir.Inst.Index,
) (@TypeOf(stream).Error || error{OutOfMemory})!void {
const inst_data = self.code.instructions.items(.data)[inst].ptr_type_simple;
const str_allowzero = if (inst_data.is_allowzero) "allowzero, " else "";
const str_const = if (!inst_data.is_mutable) "const, " else "";
const str_volatile = if (inst_data.is_volatile) "volatile, " else "";
try self.writeInstRef(stream, inst_data.elem_type);
try stream.print(", {s}{s}{s}{s})", .{
str_allowzero,
str_const,
str_volatile,
@tagName(inst_data.size),
});
}
fn writePtrType(
self: *Writer,
stream: anytype,
@ -660,7 +642,8 @@ const Writer = struct {
try self.writeInstRef(stream, @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]));
try stream.writeAll(")");
}
try stream.writeAll(")");
try stream.writeAll(") ");
try self.writeSrc(stream, LazySrcLoc.nodeOffset(extra.data.src_node));
}
fn writeInt(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {

View File

@ -744,6 +744,7 @@ pub fn llvmMachineAbi(target: std.Target) ?[:0]const u8 {
}
}
/// This function returns 1 if function alignment is not observable or settable.
pub fn defaultFunctionAlignment(target: std.Target) u32 {
return switch (target.cpu.arch) {
.arm, .armeb => 4,
@ -753,3 +754,10 @@ pub fn defaultFunctionAlignment(target: std.Target) u32 {
else => 1,
};
}
pub fn supportsFunctionAlignment(target: std.Target) bool {
return switch (target.cpu.arch) {
.wasm32, .wasm64 => false,
else => true,
};
}

View File

@ -4643,13 +4643,27 @@ pub const Type = extern union {
}
/// Asserts the type is a function.
pub fn fnCallingConventionAllowsZigTypes(self: Type) bool {
return switch (self.fnCallingConvention()) {
pub fn fnCallingConventionAllowsZigTypes(cc: std.builtin.CallingConvention) bool {
return switch (cc) {
.Unspecified, .Async, .Inline, .PtxKernel => true,
else => false,
};
}
pub fn isValidParamType(self: Type) bool {
return switch (self.zigTypeTagOrPoison() catch return true) {
.Undefined, .Null, .Opaque, .NoReturn => false,
else => true,
};
}
pub fn isValidReturnType(self: Type) bool {
return switch (self.zigTypeTagOrPoison() catch return true) {
.Undefined, .Null, .Opaque => false,
else => true,
};
}
/// Asserts the type is a function.
pub fn fnIsVarArgs(self: Type) bool {
return switch (self.tag()) {
@ -5650,6 +5664,10 @@ pub const Type = extern union {
const union_obj = ty.cast(Payload.Union).?.data;
return union_obj.srcLoc(mod);
},
.@"opaque" => {
const opaque_obj = ty.cast(Payload.Opaque).?.data;
return opaque_obj.srcLoc(mod);
},
.atomic_order,
.atomic_rmw_op,
.calling_convention,

View File

@ -299,8 +299,7 @@ test "implicitly decreasing fn alignment" {
try testImplicitlyDecreaseFnAlign(alignedBig, 5678);
}
// TODO make it a compile error to put align on the fn proto instead of on the ptr
fn testImplicitlyDecreaseFnAlign(ptr: *align(1) const fn () i32, answer: i32) !void {
fn testImplicitlyDecreaseFnAlign(ptr: *const fn () align(1) i32, answer: i32) !void {
try expect(ptr() == answer);
}
@ -326,7 +325,7 @@ test "@alignCast functions" {
fn fnExpectsOnly1(ptr: *const fn () align(1) i32) i32 {
return fnExpects4(@alignCast(4, ptr));
}
fn fnExpects4(ptr: *align(4) const fn () i32) i32 {
fn fnExpects4(ptr: *const fn () align(4) i32) i32 {
return ptr();
}
fn simple4() align(4) i32 {

View File

@ -4,7 +4,7 @@ const builtin = @import("builtin");
pub const VM = ?[*]const struct_InvocationTable_;
pub const struct_InvocationTable_ = extern struct {
GetVM: ?fn (?[*]VM) callconv(.C) c_int,
GetVM: ?*const fn (?[*]VM) callconv(.C) c_int,
};
pub const struct_VM_ = extern struct {
@ -23,5 +23,7 @@ fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 {
}
test "fixed" {
if (builtin.zig_backend == .stage1) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
try expect(agent_callback(undefined, undefined) == 11);
}

View File

@ -1016,7 +1016,6 @@ test "switching on non exhaustive union" {
switch (a) {
.a => |val| try expect(val == 2),
.b => return error.Fail,
_ => return error.Fail,
}
}
};

View File

@ -0,0 +1,14 @@
const Foo = struct {};
export fn a() void {
const T = [*c]Foo;
var t: T = undefined;
_ = t;
}
// error
// backend=stage2
// target=native
//
// :3:19: error: C pointers cannot point to non-C-ABI-compatible type 'tmp.Foo'
// :3:19: note: only structs with packed or extern layout are extern compatible
// :1:13: note: struct declared here

View File

@ -5,7 +5,7 @@ export fn a() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:3:16: error: C pointers cannot point to opaque types
// :3:16: error: C pointers cannot point to opaque types

View File

@ -0,0 +1,9 @@
export fn foo() align(1) void {
return;
}
// error
// backend=stage2
// target=wasm32-freestanding-none
//
// :1:23: error: target does not support function alignment

View File

@ -8,8 +8,8 @@ export fn g() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:3:8: error: array access of non-array type 'bool'
// tmp.zig:7:12: error: array access of non-array type 'bool'
// :3:8: error: element access of non-indexable type 'bool'
// :7:12: error: element access of non-indexable type 'bool'

View File

@ -10,8 +10,8 @@ export fn g() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:4:11: error: expected type 'usize', found 'bool'
// tmp.zig:9:15: error: expected type 'usize', found 'bool'
// :4:11: error: expected type 'usize', found 'bool'
// :9:15: error: expected type 'usize', found 'bool'

View File

@ -0,0 +1,16 @@
export fn zig_array(x: [10]u8) void {
try std.testing.expect(std.mem.eql(u8, &x, "1234567890"));
}
const std = @import("std");
export fn zig_return_array() [10]u8 {
return "1234567890".*;
}
// error
// backend=stage2
// target=native
//
// :1:21: error: parameter of type '[10]u8' not allowed in function with calling convention 'C'
// :1:21: note: arrays are not allowed as a parameter type
// :5:30: error: return type '[10]u8' not allowed in function with calling convention 'C'
// :5:30: note: arrays are not allowed as a return type

View File

@ -14,5 +14,5 @@ fn doSomeAsm() void {
// backend=llvm
// target=native
//
// :6:5: error: unable to resolve comptime value
// :6:5: error: unable to evalutate comptime expression
// :2:14: note: called from here

View File

@ -7,5 +7,5 @@ export fn entry() void {
// backend=stage2
// target=native
//
// :1:1: error: C pointers cannot point to non-C-ABI-compatible type 'void'
// :1:1: note: 'void' is a zero bit type; for C 'void' use 'anyopaque'
// :2:16: error: C pointers cannot point to non-C-ABI-compatible type 'void'
// :2:16: note: 'void' is a zero bit type; for C 'void' use 'anyopaque'

View File

@ -17,4 +17,4 @@ fn bad(ok: bool) void {
// target=native
// backend=stage2
//
// :12:18: error: unable to resolve comptime value
// :12:18: error: cannot load runtime value in comptime block

View File

@ -7,4 +7,4 @@ pub extern fn foo(format: *const u8, ...) void;
// backend=stage2
// target=native
//
// :2:8: error: expected type '*const u8', found '[5:0]u8'
// :2:16: error: expected type '*const u8', found '[5:0]u8'

View File

@ -13,9 +13,9 @@ comptime {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:8:20: error: capture group with incompatible types
// tmp.zig:8:9: note: type 'usize' here
// tmp.zig:8:13: note: type 'isize' here
// :8:20: error: capture group with incompatible types
// :8:10: note: type 'usize' here
// :8:14: note: type 'isize' here

View File

@ -18,6 +18,6 @@ export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }
// backend=stage2
// target=native
//
// :8:15: error: expected type '*const u3', found '*align(0:3:1) const u3'
// :8:15: note: pointer host size '1' cannot cast into pointer host size '0'
// :8:15: note: pointer bit offset '3' cannot cast into pointer bit offset '0'
// :8:16: error: expected type '*const u3', found '*align(0:3:1) const u3'
// :8:16: note: pointer host size '1' cannot cast into pointer host size '0'
// :8:16: note: pointer bit offset '3' cannot cast into pointer bit offset '0'

View File

@ -7,4 +7,4 @@ export fn entry() usize { return @sizeOf(@TypeOf(a)); }
// backend=stage2
// target=native
//
// :2:15: error: expected type 'type', found 'i32'
// :2:11: error: expected type 'type', found 'i32'

View File

@ -0,0 +1,9 @@
fn a() i32 {}
export fn entry() void { _ = a(); }
// error
// backend=stage2
// target=native
//
// :1:13: error: expected type 'i32', found 'void'
// :1:8: note: function return type declared here

View File

@ -45,7 +45,11 @@ pub export fn entry() void {
// backend=llvm
//
// :11:22: error: comparison of 'void' with null
// :25:51: error: unable to resolve comptime value
// :25:51: error: unable to resolve comptime value
// :25:51: error: unable to resolve comptime value
// :25:51: error: unable to resolve comptime value
// :25:51: error: values of type 'anyopaque' must be comptime known, but operand value is runtime known
// :25:51: note: opaque type 'anyopaque' has undefined size
// :25:51: error: values of type 'fn(*anyopaque, usize, u29, u29, usize) error{OutOfMemory}![]u8' must be comptime known, but operand value is runtime known
// :25:51: note: use '*const fn(*anyopaque, usize, u29, u29, usize) error{OutOfMemory}![]u8' for a function pointer type
// :25:51: error: values of type 'fn(*anyopaque, []u8, u29, usize, u29, usize) ?usize' must be comptime known, but operand value is runtime known
// :25:51: note: use '*const fn(*anyopaque, []u8, u29, usize, u29, usize) ?usize' for a function pointer type
// :25:51: error: values of type 'fn(*anyopaque, []u8, u29, usize) void' must be comptime known, but operand value is runtime known
// :25:51: note: use '*const fn(*anyopaque, []u8, u29, usize) void' for a function pointer type

View File

@ -0,0 +1,38 @@
const O = opaque {};
const Foo = struct {
o: O,
};
const Bar = union {
One: i32,
Two: O,
};
export fn a() void {
var foo: Foo = undefined;
_ = foo;
}
export fn b() void {
var bar: Bar = undefined;
_ = bar;
}
export fn c() void {
const baz = &@as(opaque {}, undefined);
const qux = .{baz.*};
_ = qux;
}
export fn d() void {
const baz = &@as(opaque {}, undefined);
const qux = .{ .a = baz.* };
_ = qux;
}
// error
// backend=stage2
// target=native
//
// :3:5: error: opaque types have unknown size and therefore cannot be directly embedded in structs
// :1:11: note: opaque declared here
// :7:5: error: opaque types have unknown size and therefore cannot be directly embedded in unions
// :19:18: error: opaque types have unknown size and therefore cannot be directly embedded in structs
// :18:22: note: opaque declared here
// :24:18: error: opaque types have unknown size and therefore cannot be directly embedded in structs
// :23:22: note: opaque declared here

View File

@ -1,12 +1,13 @@
extern fn puts(s: [*:0]const u8) c_int;
pub fn main() void {
pub export fn entry() void {
const no_zero_array = [_]u8{'h', 'e', 'l', 'l', 'o'};
const no_zero_ptr: [*]const u8 = &no_zero_array;
_ = puts(no_zero_ptr);
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:5:14: error: expected type '[*:0]const u8', found '[*]const u8'
// :5:14: error: expected type '[*:0]const u8', found '[*]const u8'
// :5:14: note: destination pointer requires '0' sentinel

View File

@ -0,0 +1,15 @@
const seventh_fib_number = fibonacci(7);
fn fibonacci(x: i32) i32 {
return fibonacci(x - 1) + fibonacci(x - 2);
}
export fn entry() usize { return @sizeOf(@TypeOf(&seventh_fib_number)); }
// error
// backend=stage2
// target=native
//
// :3:21: error: evaluation exceeded 1000 backwards branches
// :3:21: note: use @setEvalBranchQuota() to raise the branch limit from 1000
// :3:21: note: called from here (999 times)
// :1:37: note: called from here

View File

@ -8,6 +8,6 @@ export fn entry() void {
// backend=stage2
// target=native
//
// :4:17: error: expected type '*const fn(i32) void', found '*const fn(bool) void'
// :4:17: note: pointer type child 'fn(bool) void' cannot cast into pointer type child 'fn(i32) void'
// :4:17: note: parameter 0 'bool' cannot cast into 'i32'
// :4:18: error: expected type '*const fn(i32) void', found '*const fn(bool) void'
// :4:18: note: pointer type child 'fn(bool) void' cannot cast into pointer type child 'fn(i32) void'
// :4:18: note: parameter 0 'bool' cannot cast into 'i32'

View File

@ -0,0 +1,9 @@
export fn foo(comptime x: anytype, y: i32) i32{
return x + y;
}
// error
// backend=stage2
// target=native
//
// :1:15: error: generic parameters not allowed in function with calling convention 'C'

View File

@ -0,0 +1,10 @@
export fn foo(num: anytype) i32 {
_ = num;
return 0;
}
// error
// backend=stage2
// target=native
//
// :1:15: error: generic parameters not allowed in function with calling convention 'C'

View File

@ -0,0 +1,20 @@
extern fn foo(comptime x: i32, y: i32) i32;
fn f() i32 {
return foo(1, 2);
}
pub extern fn entry1(b: u32, comptime a: [2]u8, c: i32) void;
pub extern fn entry2(b: u32, noalias a: anytype, i43) void;
comptime { _ = f; }
comptime { _ = entry1; }
comptime { _ = entry2; }
// error
// backend=stage2
// target=native
//
// :5:12: error: extern function cannot be generic
// :5:30: note: function is generic because of this parameter
// :6:12: error: extern function cannot be generic
// :6:30: note: function is generic because of this parameter
// :1:8: error: extern function cannot be generic
// :1:15: note: function is generic because of this parameter

View File

@ -39,7 +39,7 @@ export fn entry() void {
// backend=stage2
// target=native
//
// :33:8: error: extern structs cannot contain fields of type 'tmp.E'
// :33:8: note: enum tag type 'u9' is not extern compatible
// :33:8: note: only integers with power of two bits are extern compatible
// :31:5: error: extern structs cannot contain fields of type 'tmp.E'
// :31:5: note: enum tag type 'u9' is not extern compatible
// :31:5: note: only integers with power of two bits are extern compatible
// :1:15: note: enum declared here

View File

@ -11,7 +11,7 @@ export fn entry() void {
// backend=stage2
// target=native
//
// :5:8: error: extern structs cannot contain fields of type 'tmp.E'
// :5:8: note: enum tag type 'u31' is not extern compatible
// :5:8: note: only integers with power of two bits are extern compatible
// :3:5: error: extern structs cannot contain fields of type 'tmp.E'
// :3:5: note: enum tag type 'u31' is not extern compatible
// :3:5: note: only integers with power of two bits are extern compatible
// :1:15: note: enum declared here

View File

@ -14,7 +14,7 @@ export fn entry() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:6:30: error: extern union does not support enum tag type
// :6:30: error: extern union does not support enum tag type

View File

@ -2,7 +2,7 @@ extern fn foo() align(3) void;
export fn entry() void { return foo(); }
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:1:23: error: alignment value 3 is not a power of 2
// :1:23: error: alignment value '3' is not a power of two

View File

@ -11,3 +11,4 @@ fn concat() [16]f32 {
// target=native
//
// :3:17: error: expected type '[4]f32', found '[16]f32'
// :3:17: note: array of length 16 cannot cast into an array of length 4

View File

@ -20,10 +20,11 @@ export fn entry4() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:3:28: error: parameter of opaque type 'FooType' not allowed
// tmp.zig:8:28: error: parameter of type '@Type(.Null)' not allowed
// tmp.zig:12:11: error: parameter of opaque type 'FooType' not allowed
// tmp.zig:17:11: error: parameter of type '@Type(.Null)' not allowed
// :3:28: error: parameter of opaque type 'tmp.FooType' not allowed
// :1:17: note: opaque declared here
// :8:28: error: parameter of type '@TypeOf(null)' not allowed
// :12:8: error: parameter of opaque type 'tmp.FooType' not allowed
// :17:8: error: parameter of type '@TypeOf(null)' not allowed

View File

@ -0,0 +1,28 @@
comptime {
var a: *align(2) @TypeOf(foo) = undefined;
_ = a;
}
fn foo() void {}
comptime {
var a: *align(1) fn () void = undefined;
_ = a;
}
comptime {
var a: *align(2) fn () align(2) void = undefined;
_ = a;
}
comptime {
var a: *align(2) fn () void = undefined;
_ = a;
}
comptime {
var a: *align(1) fn () align(2) void = undefined;
_ = a;
}
// error
// backend=stage2
// target=native
//
// :20:19: error: function pointer alignment disagrees with function alignment

View File

@ -0,0 +1,19 @@
const FooType = opaque {};
export fn bar() !FooType {
return error.InvalidValue;
}
export fn bav() !@TypeOf(null) {
return error.InvalidValue;
}
export fn baz() !@TypeOf(undefined) {
return error.InvalidValue;
}
// error
// backend=stage2
// target=native
//
// :2:18: error: opaque return type 'tmp.FooType' not allowed
// :1:17: note: opaque declared here
// :5:18: error: return type '@TypeOf(null)' not allowed
// :8:18: error: return type '@TypeOf(undefined)' not allowed

View File

@ -0,0 +1,11 @@
const Foo = enum { A, B, C };
export fn entry(foo: Foo) void { _ = foo; }
// error
// backend=stage2
// target=native
//
// :2:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
// :2:17: note: enum tag type 'u2' is not extern compatible
// :2:17: note: only integers with power of two bits are extern compatible
// :1:13: note: enum declared here

View File

@ -0,0 +1,14 @@
const Foo = struct {
A: i32,
B: f32,
C: bool,
};
export fn entry(foo: Foo) void { _ = foo; }
// error
// backend=stage2
// target=native
//
// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
// :6:17: note: only structs with packed or extern layout are extern compatible
// :1:13: note: struct declared here

View File

@ -0,0 +1,14 @@
const Foo = union {
A: i32,
B: f32,
C: bool,
};
export fn entry(foo: Foo) void { _ = foo; }
// error
// backend=stage2
// target=native
//
// :6:17: error: parameter of type 'tmp.Foo' not allowed in function with calling convention 'C'
// :6:17: note: only unions with packed or extern layout are extern compatible
// :1:13: note: union declared here

View File

@ -0,0 +1,13 @@
fn foo(comptime x: i32, y: i32) i32 { return x + y; }
fn test1(a: i32, b: i32) i32 {
return foo(a, b);
}
export fn entry() usize { return @sizeOf(@TypeOf(&test1)); }
// error
// backend=stage2
// target=native
//
// :3:16: error: unable to resolve comptime value
// :3:16: note: parameter is comptime

View File

@ -5,7 +5,7 @@ export fn entry() void {
}
// error
// backend=stage1
// backend=llvm
// target=native
//
// tmp.zig:4:9: error: expected type '[]i32', found '[10]i32'
// :4:9: error: array literal requires address-of operator (&) to coerce to slice type '[]i32'

View File

@ -13,7 +13,8 @@ fn bar(x: *u32) void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:8:13: error: expected type '*u32', found '*align(1) u32'
// :8:9: error: expected type '*u32', found '*align(1) u32'
// :8:9: note: pointer alignment '1' cannot cast into pointer alignment '4'

View File

@ -12,4 +12,6 @@ export fn bar() void {
// target=native
//
// :3:35: error: unable to resolve comptime value
// :3:35: note: value being casted to 'comptime_int' must be comptime known
// :7:37: error: unable to resolve comptime value
// :7:37: note: value being casted to 'comptime_float' must be comptime known

View File

@ -7,5 +7,5 @@ export fn testf(fluff: *stroo) void { _ = fluff; }
// backend=stage2
// target=native
//
// :4:8: error: extern structs cannot contain fields of type '?[*c]u8'
// :4:8: note: only pointer like optionals are extern compatible
// :2:5: error: extern structs cannot contain fields of type '?[*c]u8'
// :2:5: note: only pointer like optionals are extern compatible

View File

@ -7,7 +7,7 @@ export fn entry() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:5:28: error: attempt to read 8 bytes from pointer to f32 which is 4 bytes
// :5:28: error: dereference of '*const i64' exceeds bounds of containing decl of type 'f32'

View File

@ -14,5 +14,5 @@ export fn entry() usize { return @sizeOf(@TypeOf(a)); }
// backend=stage2
// target=native
//
// :6:26: error: unable to resolve comptime value
// :6:26: error: cannot store to runtime value in comptime block
// :4:17: note: called from here

View File

@ -7,7 +7,7 @@ export fn entry() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:1:19: error: expected enum tag type, found 'u32'
// :1:19: error: expected enum tag type, found 'u32'

View File

@ -7,7 +7,7 @@ export fn entry() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:1:24: error: expected integer tag type, found 'f32'
// :1:24: error: expected integer tag type, found 'f32'

View File

@ -0,0 +1,13 @@
const Foo = enum(f32) {
A,
};
export fn entry() void {
var f: Foo = undefined;
_ = f;
}
// error
// backend=stage2
// target=native
//
// :1:18: error: expected integer tag type, found 'f32'

View File

@ -21,5 +21,5 @@ export fn function_with_return_type_type() void {
// backend=stage2
// target=native
//
// :3:7: error: unable to resolve comptime value
// :3:7: error: cannot load runtime value in comptime block
// :16:19: note: called from here

View File

@ -10,5 +10,5 @@ export fn entry() usize { return @offsetOf(Foo, "y"); }
// backend=stage2
// target=native
//
// :5:25: error: unable to resolve comptime value
// :5:25: error: cannot load runtime value in comptime block
// :2:15: note: called from here

View File

@ -5,7 +5,7 @@ export fn entry() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:1:25: error: opaque types cannot have fields
// :1:25: error: opaque types cannot have fields

View File

@ -8,10 +8,11 @@ fn ptrEql(a: *[]const u8, b: *[]const u8) bool {
return true;
}
export fn entry() usize { return @sizeOf(@TypeOf(foo)); }
export fn entry() usize { return @sizeOf(@TypeOf(&foo)); }
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:4:19: error: expected type '*[]const u8', found '*const []const u8'
// :4:19: error: expected type '*[]const u8', found '*const []const u8'
// :4:19: note: cast discards const qualifier

View File

@ -2,7 +2,7 @@ fn a() *noreturn {}
export fn entry() void { _ = a(); }
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:1:9: error: pointer to noreturn not allowed
// :1:9: error: pointer to noreturn not allowed

View File

@ -7,5 +7,5 @@ export fn entry() void {
// backend=stage2
// target=native
//
// :2:19: error: type '[]u8' does not support array initialization syntax
// :2:19: note: inferred array length is specified with an underscore: '[_]u8'
// :2:15: error: type '[]u8' does not support array initialization syntax
// :2:15: note: inferred array length is specified with an underscore: '[_]u8'

View File

@ -1,12 +0,0 @@
const Foo = struct {};
export fn a() void {
const T = [*c]Foo;
var t: T = undefined;
_ = t;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:3:19: error: C pointers cannot point to non-C-ABI-compatible type 'Foo'

View File

@ -1,9 +0,0 @@
export fn foo() align(1) void {
return;
}
// error
// backend=stage1
// target=wasm32-freestanding-none
//
// tmp.zig:1:23: error: align(N) expr is not allowed on function prototypes in wasm32/wasm64

View File

@ -1,14 +0,0 @@
export fn zig_array(x: [10]u8) void {
try std.testing.expect(std.mem.eql(u8, &x, "1234567890"));
}
const std = @import("std");
export fn zig_return_array() [10]u8 {
return "1234567890".*;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:1:24: error: parameter of type '[10]u8' not allowed in function with calling convention 'C'
// tmp.zig:5:30: error: return type '[10]u8' not allowed in function with calling convention 'C'

View File

@ -1,8 +0,0 @@
fn a() i32 {}
export fn entry() void { _ = a(); }
// error
// backend=stage1
// target=native
//
// tmp.zig:1:12: error: expected type 'i32', found 'void'

View File

@ -1,29 +0,0 @@
const O = opaque {};
const Foo = struct {
o: O,
};
const Bar = union {
One: i32,
Two: O,
};
export fn a() void {
var foo: Foo = undefined;
_ = foo;
}
export fn b() void {
var bar: Bar = undefined;
_ = bar;
}
export fn c() void {
var baz: *opaque {} = undefined;
const qux = .{baz.*};
_ = qux;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:3:5: error: opaque types have unknown size and therefore cannot be directly embedded in structs
// tmp.zig:7:5: error: opaque types have unknown size and therefore cannot be directly embedded in unions
// tmp.zig:19:22: error: opaque types have unknown size and therefore cannot be directly embedded in structs

View File

@ -1,12 +0,0 @@
const seventh_fib_number = fibonacci(7);
fn fibonacci(x: i32) i32 {
return fibonacci(x - 1) + fibonacci(x - 2);
}
export fn entry() usize { return @sizeOf(@TypeOf(seventh_fib_number)); }
// error
// backend=stage1
// target=native
//
// tmp.zig:3:21: error: evaluation exceeded 1000 backwards branches

View File

@ -1,9 +0,0 @@
export fn foo(comptime x: i32, y: i32) i32{
return x + y;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'

View File

@ -1,10 +0,0 @@
export fn foo(num: anytype) i32 {
_ = num;
return 0;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:1:15: error: parameter of type 'anytype' not allowed in function with calling convention 'C'

View File

@ -1,11 +0,0 @@
extern fn foo(comptime x: i32, y: i32) i32;
fn f() i32 {
return foo(1, 2);
}
export fn entry() usize { return @sizeOf(@TypeOf(f)); }
// error
// backend=stage1
// target=native
//
// tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'

View File

@ -1,19 +0,0 @@
const FooType = opaque {};
export fn bar() !FooType {
return error.InvalidValue;
}
export fn bav() !@TypeOf(null) {
return error.InvalidValue;
}
export fn baz() !@TypeOf(undefined) {
return error.InvalidValue;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:2:18: error: Opaque return type 'FooType' not allowed
// tmp.zig:1:1: note: type declared here
// tmp.zig:5:18: error: Null return type '@Type(.Null)' not allowed
// tmp.zig:8:18: error: Undefined return type '@Type(.Undefined)' not allowed

View File

@ -1,8 +0,0 @@
const Foo = enum { A, B, C };
export fn entry(foo: Foo) void { _ = foo; }
// error
// backend=stage1
// target=native
//
// tmp.zig:2:22: error: parameter of type 'Foo' not allowed in function with calling convention 'C'

View File

@ -1,12 +0,0 @@
const Foo = struct {
A: i32,
B: f32,
C: bool,
};
export fn entry(foo: Foo) void { _ = foo; }
// error
// backend=stage1
// target=native
//
// tmp.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'C'

View File

@ -1,12 +0,0 @@
const Foo = union {
A: i32,
B: f32,
C: bool,
};
export fn entry(foo: Foo) void { _ = foo; }
// error
// backend=stage1
// target=native
//
// tmp.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'C'

View File

@ -1,12 +0,0 @@
fn foo(comptime x: i32, y: i32) i32 { return x + y; }
fn test1(a: i32, b: i32) i32 {
return foo(a, b);
}
export fn entry() usize { return @sizeOf(@TypeOf(test1)); }
// error
// backend=stage1
// target=native
//
// tmp.zig:3:16: error: runtime value cannot be passed to comptime arg

View File

@ -1,7 +0,0 @@
export const T = [*]opaque {};
// error
// backend=stage1
// target=native
//
// tmp.zig:1:21: error: unknown-length pointer to opaque

View File

@ -1,14 +0,0 @@
export fn entry() void {
var x: i32 = 1234;
var p: *i32 = &x;
var pp: *?*i32 = &p;
pp.* = null;
var y = p.*;
_ = y;
}
// error
// backend=stage1
// target=native
//
// tmp.zig:4:23: error: expected type '*?*i32', found '**i32'

View File

@ -1,12 +0,0 @@
const Derp = opaque {};
extern fn bar(d: *Derp) void;
export fn foo() void {
var x = @as(u8, 1);
bar(@ptrCast(*anyopaque, &x));
}
// error
// backend=stage1
// target=native
//
// tmp.zig:5:9: error: expected type '*Derp', found '*anyopaque'

View File

@ -16,6 +16,6 @@ export fn entry() usize {
// error
// target=native
//
// :7:1: error: enum field(s) missing in union
// :7:11: error: enum field(s) missing in union
// :4:5: note: field 'c' missing, declared here
// :1:11: note: enum declared here

View File

@ -16,5 +16,5 @@ export fn entry() usize {
// error
// target=native
//
// :6:1: error: enum 'tmp.E' has no field named 'd'
// :10:5: error: enum 'tmp.E' has no field named 'd'
// :1:11: note: enum declared here

View File

@ -19,5 +19,5 @@ export fn entry() usize { return @sizeOf(@TypeOf(&f)); }
// target=native
//
// :8:5: error: switch must handle all possibilities
// :8:5: note: unhandled enumeration value: 'Four'
// :5:5: note: unhandled enumeration value: 'Four'
// :1:16: note: enum 'tmp.Number' declared here

View File

@ -10,5 +10,5 @@ export fn entry() void {
// target=native
//
// :5:5: error: switch must handle all possibilities
// :5:5: note: unhandled enumeration value: 'M'
// :1:20: note: unhandled enumeration value: 'M'
// :1:13: note: enum 'tmp.Foo' declared here

View File

@ -7,16 +7,21 @@ const U = union(E) {
a: i32,
b: u32,
};
pub export fn entry() void {
pub export fn entry1() void {
var e: E = .b;
switch (e) { // error: switch not handling the tag `b`
.a => {},
_ => {},
}
}
pub export fn entry2() void {
var e: E = .b;
switch (e) { // error: switch on non-exhaustive enum must include `else` or `_` prong
.a => {},
.b => {},
}
}
pub export fn entry3() void {
var u = U{.a = 2};
switch (u) { // error: `_` prong not allowed when switching on tagged union
.a => {},
@ -26,10 +31,12 @@ pub export fn entry() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
// is_test=1
//
// tmp.zig:12:5: error: enumeration value 'E.b' not handled in switch
// tmp.zig:16:5: error: switch on non-exhaustive enum must include `else` or `_` prong
// tmp.zig:21:5: error: `_` prong not allowed when switching on tagged union
// :12:5: error: switch must handle all possibilities
// :3:5: note: unhandled enumeration value: 'b'
// :1:11: note: enum 'tmp.E' declared here
// :19:5: error: switch on non-exhaustive enum must include 'else' or '_' prong
// :26:5: error: '_' prong only allowed when switching on non-exhaustive enums
// :29:11: note: '_' prong here

View File

@ -10,6 +10,6 @@ export fn entry() void {
// backend=stage2
// target=native
//
// :6:6: error: expected type '*const fn(*const u8) void', found '*const fn(u8) void'
// :6:6: note: pointer type child 'fn(u8) void' cannot cast into pointer type child 'fn(*const u8) void'
// :6:6: note: parameter 0 'u8' cannot cast into '*const u8'
// :6:7: error: expected type '*const fn(*const u8) void', found '*const fn(u8) void'
// :6:7: note: pointer type child 'fn(u8) void' cannot cast into pointer type child 'fn(*const u8) void'
// :6:7: note: parameter 0 'u8' cannot cast into '*const u8'

View File

@ -15,6 +15,6 @@ export fn entry() usize {
// backend=stage2
// target=native
//
// :6:1: error: enum field(s) missing in union
// :6:17: error: enum field(s) missing in union
// :4:5: note: field 'C' missing, declared here
// :1:16: note: enum declared here

View File

@ -0,0 +1,7 @@
export const T = [*]opaque {};
// error
// backend=stage2
// target=native
//
// :1:21: error: unknown-length pointer to opaque not allowed

View File

@ -2,7 +2,7 @@ fn f(a: noreturn) void { _ = a; }
export fn entry() void { f(); }
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:1:9: error: parameter of type 'noreturn' not allowed
// :1:6: error: parameter of type 'noreturn' not allowed

View File

@ -4,7 +4,7 @@ export fn entry() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:2:20: error: return type cannot be opaque
// :2:20: error: opaque return type 'anyopaque' not allowed

View File

@ -0,0 +1,16 @@
export fn entry() void {
var x: i32 = 1234;
var p: *i32 = &x;
var pp: *?*i32 = &p;
pp.* = null;
var y = p.*;
_ = y;
}
// error
// backend=stage2
// target=native
//
// :4:22: error: expected type '*?*i32', found '**i32'
// :4:22: note: pointer type child '*i32' cannot cast into pointer type child '?*i32'
// :4:22: note: mutable '*i32' allows illegal null values stored to type '?*i32'

View File

@ -7,7 +7,7 @@ comptime {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:1:21: error: expected array type or [_], found '[*][*]const u8'
// :1:22: error: type '[*][*]const u8' does not support array initialization syntax

View File

@ -10,7 +10,8 @@ export fn entry() void {
}
// error
// backend=stage1
// backend=stage2
// target=native
//
// tmp.zig:9:8: error: use of undefined value here causes undefined behavior
// :9:14: error: expected type 'type', found 'tmp.U'
// :1:11: note: union declared here

View File

@ -0,0 +1,14 @@
const Derp = opaque {};
extern fn bar(d: *Derp) void;
export fn foo() void {
var x = @as(u8, 1);
bar(@ptrCast(*anyopaque, &x));
}
// error
// backend=stage2
// target=native
//
// :5:9: error: expected type '*tmp.Derp', found '*anyopaque'
// :5:9: note: pointer type child 'anyopaque' cannot cast into pointer type child 'tmp.Derp'
// :1:14: note: opaque declared here

View File

@ -6,4 +6,4 @@ extern var foo: i32;
// error
//
// :2:15: error: unable to resolve comptime value
// :2:15: error: cannot load runtime value in comptime block

View File

@ -22,3 +22,4 @@ pub fn assert(ok: bool) void {
// error
//
// :3:21: error: unable to resolve comptime value
// :3:21: note: condition in comptime branch must be comptime known

View File

@ -17,3 +17,4 @@ pub fn assert(ok: bool) void {
// error
//
// :5:21: error: unable to resolve comptime value
// :5:21: note: condition in comptime branch must be comptime known

View File

@ -51,8 +51,8 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\var y: @import("std").builtin.CallingConvention = .C;
, &.{
":2:22: error: unable to resolve comptime value",
":5:26: error: unable to resolve comptime value",
":2:22: error: cannot load runtime value in comptime block",
":5:26: error: cannot load runtime value in comptime block",
});
}
@ -772,7 +772,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
, &.{
":4:5: error: switch must handle all possibilities",
":4:5: note: unhandled enumeration value: 'b'",
":1:21: note: unhandled enumeration value: 'b'",
":1:11: note: enum 'tmp.E' declared here",
});