authorgravatar for goon.pri.low@gmail.comKendall Condon <goon.pri.low@gmail.com> 2026-05-18 18:59:50-04:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-09 10:09:42+02:00
logb7b6d66675dc1eb20862b6a18ac9745287bc7e32
treea42d3e4d362ee056b81f8db8fc3d8e70e497c514
parent18d9b2850ecba8fca14b11bd18111c17f0415aa9

AstGen: properly advance cursor for decl qualifiers

Reorders the parsing code so the expressions are parsed in the same order as in source and removes unnecessary cursor restores when parsing function qualifiers.

2 files changed, 114 insertions(+), 68 deletions(-)

lib/std/zig/AstGen.zig+69-68
...@@ -3135,6 +3135,11 @@ fn varDecl(...@@ -3135,6 +3135,11 @@ fn varDecl(
3135 return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw});3135 return astgen.failTok(tree.nodeMainToken(section_node), "cannot set section of local variable '{s}'", .{ident_name_raw});
3136 }3136 }
31373137
3138 const type_inst: Zir.Inst.Ref = if (var_decl.ast.type_node.unwrap()) |type_node|
3139 try typeExpr(gz, scope, type_node)
3140 else
3141 .none;
3142
3138 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node.unwrap()) |align_node|3143 const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node.unwrap()) |align_node|
3139 try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align")3144 try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align")
3140 else3145 else
...@@ -3155,8 +3160,8 @@ fn varDecl(...@@ -3155,8 +3160,8 @@ fn varDecl(
3155 if (align_inst == .none and3160 if (align_inst == .none and
3156 !astgen.nodes_need_rl.contains(node))3161 !astgen.nodes_need_rl.contains(node))
3157 {3162 {
3158 const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| .{3163 const result_info: ResultInfo = if (type_inst != .none) .{
3159 .rl = .{ .ty = try typeExpr(gz, scope, type_node) },3164 .rl = .{ .ty = type_inst },
3160 .ctx = .const_init,3165 .ctx = .const_init,
3161 } else .{ .rl = .none, .ctx = .const_init };3166 } else .{ .rl = .none, .ctx = .const_init };
3162 const init_inst: Zir.Inst.Ref = try nameStratExpr(gz, scope, result_info, init_node, .dbg_var) orelse3167 const init_inst: Zir.Inst.Ref = try nameStratExpr(gz, scope, result_info, init_node, .dbg_var) orelse
...@@ -3185,8 +3190,7 @@ fn varDecl(...@@ -3185,8 +3190,7 @@ fn varDecl(
3185 const is_comptime = gz.is_comptime or3190 const is_comptime = gz.is_comptime or
3186 tree.nodeTag(init_node) == .@"comptime";3191 tree.nodeTag(init_node) == .@"comptime";
31873192
3188 const init_rl: ResultInfo.Loc = if (var_decl.ast.type_node.unwrap()) |type_node| init_rl: {3193 const init_rl: ResultInfo.Loc = if (type_inst != .none) init_rl: {
3189 const type_inst = try typeExpr(gz, scope, type_node);
3190 if (align_inst == .none) {3194 if (align_inst == .none) {
3191 break :init_rl .{ .ptr = .{ .inst = try gz.addUnNode(.alloc, type_inst, node) } };3195 break :init_rl .{ .ptr = .{ .inst = try gz.addUnNode(.alloc, type_inst, node) } };
3192 } else {3196 } else {
...@@ -3254,8 +3258,7 @@ fn varDecl(...@@ -3254,8 +3258,7 @@ fn varDecl(
3254 if (var_decl.comptime_token != null and gz.is_comptime)3258 if (var_decl.comptime_token != null and gz.is_comptime)
3255 return astgen.failTok(var_decl.comptime_token.?, "'comptime var' is redundant in comptime scope", .{});3259 return astgen.failTok(var_decl.comptime_token.?, "'comptime var' is redundant in comptime scope", .{});
3256 const is_comptime = var_decl.comptime_token != null or gz.is_comptime;3260 const is_comptime = var_decl.comptime_token != null or gz.is_comptime;
3257 const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (var_decl.ast.type_node.unwrap()) |type_node| a: {3261 const alloc: Zir.Inst.Ref, const resolve_inferred: bool, const result_info: ResultInfo = if (type_inst != .none) a: {
3258 const type_inst = try typeExpr(gz, scope, type_node);
3259 const alloc = alloc: {3262 const alloc = alloc: {
3260 if (align_inst == .none) {3263 if (align_inst == .none) {
3261 const tag: Zir.Inst.Tag = if (is_comptime)3264 const tag: Zir.Inst.Tag = if (is_comptime)
...@@ -3482,14 +3485,18 @@ fn assignDestructureMaybeDecls(...@@ -3482,14 +3485,18 @@ fn assignDestructureMaybeDecls(
3482 // We also mark `const`s as comptime if the RHS is definitely comptime-known.3485 // We also mark `const`s as comptime if the RHS is definitely comptime-known.
3483 const this_variable_comptime = is_comptime or (is_const and value_is_comptime);3486 const this_variable_comptime = is_comptime or (is_const and value_is_comptime);
34843487
3488 const type_inst = if (full_var_decl.ast.type_node.unwrap()) |type_node|
3489 try typeExpr(gz, scope, type_node)
3490 else
3491 .none;
3492
3485 const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node.unwrap()) |align_node|3493 const align_inst: Zir.Inst.Ref = if (full_var_decl.ast.align_node.unwrap()) |align_node|
3486 try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align")3494 try comptimeExpr(gz, scope, coerced_align_ri, align_node, .@"align")
3487 else3495 else
3488 .none;3496 .none;
34893497
3490 if (full_var_decl.ast.type_node.unwrap()) |type_node| {3498 if (type_inst != .none) {
3491 // Typed alloc3499 // Typed alloc
3492 const type_inst = try typeExpr(gz, scope, type_node);
3493 const ptr = if (align_inst == .none) ptr: {3500 const ptr = if (align_inst == .none) ptr: {
3494 const tag: Zir.Inst.Tag = if (this_variable_comptime)3501 const tag: Zir.Inst.Tag = if (this_variable_comptime)
3495 .alloc_comptime_mut3502 .alloc_comptime_mut
...@@ -4061,43 +4068,41 @@ fn fnDecl(...@@ -4061,43 +4068,41 @@ fn fnDecl(
4061 // We include a function *type*, not a value.4068 // We include a function *type*, not a value.
4062 const type_inst = try fnProtoExprInner(&type_gz, &type_gz.base, .{ .rl = .none }, decl_node, fn_proto, true);4069 const type_inst = try fnProtoExprInner(&type_gz, &type_gz.base, .{ .rl = .none }, decl_node, fn_proto, true);
4063 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, decl_node);4070 _ = try type_gz.addBreakWithSrcNode(.break_inline, decl_inst, type_inst, decl_node);
4071 astgen.restoreSourceCursor(saved_cursor);
4064 }4072 }
40654073
4066 var align_gz = type_gz.makeSubBlock(scope);4074 var align_gz = type_gz.makeSubBlock(scope);
4067 defer align_gz.unstack();4075 defer align_gz.unstack();
40684076
4069 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {4077 if (fn_proto.ast.align_expr.unwrap()) |align_expr| {
4070 astgen.restoreSourceCursor(saved_cursor);
4071 const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_expr);4078 const inst = try expr(&align_gz, &align_gz.base, coerced_align_ri, align_expr);
4072 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);4079 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4073 }4080 }
40744081
4075 var linksection_gz = align_gz.makeSubBlock(scope);4082 var addrspace_gz = align_gz.makeSubBlock(scope);
4076 defer linksection_gz.unstack();
4077
4078 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
4079 astgen.restoreSourceCursor(saved_cursor);
4080 const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_expr);
4081 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4082 }
4083
4084 var addrspace_gz = linksection_gz.makeSubBlock(scope);
4085 defer addrspace_gz.unstack();4083 defer addrspace_gz.unstack();
40864084
4087 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {4085 if (fn_proto.ast.addrspace_expr.unwrap()) |addrspace_expr| {
4088 astgen.restoreSourceCursor(saved_cursor);
4089 const addrspace_ty = try addrspace_gz.addStdLangValue(addrspace_expr, .address_space);4086 const addrspace_ty = try addrspace_gz.addStdLangValue(addrspace_expr, .address_space);
4090 const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_expr);4087 const inst = try expr(&addrspace_gz, &addrspace_gz.base, .{ .rl = .{ .coerced_ty = addrspace_ty } }, addrspace_expr);
4091 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);4088 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4092 }4089 }
40934090
4094 var value_gz = addrspace_gz.makeSubBlock(scope);4091 var linksection_gz = addrspace_gz.makeSubBlock(scope);
4092 defer linksection_gz.unstack();
4093
4094 if (fn_proto.ast.section_expr.unwrap()) |section_expr| {
4095 const inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_expr);
4096 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, inst, decl_node);
4097 }
4098
4099 var value_gz = linksection_gz.makeSubBlock(scope);
4095 defer value_gz.unstack();4100 defer value_gz.unstack();
40964101
4097 if (!is_extern) {4102 if (!is_extern) {
4098 // We include a function *value*, not a type.4103 // We include a function *value*, not a type.
4099 astgen.restoreSourceCursor(saved_cursor);4104 astgen.restoreSourceCursor(saved_cursor);
4100 try astgen.fnDeclInner(&value_gz, &value_gz.base, saved_cursor, decl_inst, decl_node, body_node.unwrap().?, fn_proto);4105 try astgen.fnDeclInner(&value_gz, &value_gz.base, decl_inst, decl_node, body_node.unwrap().?, fn_proto);
4101 }4106 }
41024107
4103 // *Now* we can incorporate the full source code into the hasher.4108 // *Now* we can incorporate the full source code into the hasher.
...@@ -4119,8 +4124,8 @@ fn fnDecl(...@@ -4119,8 +4124,8 @@ fn fnDecl(
41194124
4120 .type_gz = &type_gz,4125 .type_gz = &type_gz,
4121 .align_gz = &align_gz,4126 .align_gz = &align_gz,
4122 .linksection_gz = &linksection_gz,
4123 .addrspace_gz = &addrspace_gz,4127 .addrspace_gz = &addrspace_gz,
4128 .linksection_gz = &linksection_gz,
4124 .value_gz = &value_gz,4129 .value_gz = &value_gz,
4125 });4130 });
4126}4131}
...@@ -4129,7 +4134,6 @@ fn fnDeclInner(...@@ -4129,7 +4134,6 @@ fn fnDeclInner(
4129 astgen: *AstGen,4134 astgen: *AstGen,
4130 decl_gz: *GenZir,4135 decl_gz: *GenZir,
4131 scope: *Scope,4136 scope: *Scope,
4132 saved_cursor: SourceCursor,
4133 decl_inst: Zir.Inst.Index,4137 decl_inst: Zir.Inst.Index,
4134 decl_node: Ast.Node.Index,4138 decl_node: Ast.Node.Index,
4135 body_node: Ast.Node.Index,4139 body_node: Ast.Node.Index,
...@@ -4266,27 +4270,6 @@ fn fnDeclInner(...@@ -4266,27 +4270,6 @@ fn fnDeclInner(
4266 // instructions inside the expression blocks for cc and ret_ty to use the function4270 // instructions inside the expression blocks for cc and ret_ty to use the function
4267 // instruction as the body to break from.4271 // instruction as the body to break from.
42684272
4269 var ret_gz = decl_gz.makeSubBlock(params_scope);
4270 defer ret_gz.unstack();
4271 any_param_used = false; // we will check this later
4272 const ret_ref: Zir.Inst.Ref = inst: {
4273 // Parameters are in scope for the return type, so we use `params_scope` here.
4274 // The calling convention will not have parameters in scope, so we'll just use `scope`.
4275 // See #22263 for a proposal to solve the inconsistency here.
4276 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type.unwrap().?, .normal);
4277 if (ret_gz.instructionsSlice().len == 0) {
4278 // In this case we will send a len=0 body which can be encoded more efficiently.
4279 break :inst inst;
4280 }
4281 _ = try ret_gz.addBreak(.break_inline, @fromBackingInt(@intCast(0)), inst);
4282 break :inst inst;
4283 };
4284 const ret_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items);
4285 const ret_ty_is_generic = any_param_used;
4286
4287 // We're jumping back in source, so restore the cursor.
4288 astgen.restoreSourceCursor(saved_cursor);
4289
4290 var cc_gz = decl_gz.makeSubBlock(scope);4273 var cc_gz = decl_gz.makeSubBlock(scope);
4291 defer cc_gz.unstack();4274 defer cc_gz.unstack();
4292 const cc_ref: Zir.Inst.Ref = blk: {4275 const cc_ref: Zir.Inst.Ref = blk: {
...@@ -4312,6 +4295,24 @@ fn fnDeclInner(...@@ -4312,6 +4295,24 @@ fn fnDeclInner(
4312 }4295 }
4313 };4296 };
43144297
4298 var ret_gz = decl_gz.makeSubBlock(params_scope);
4299 defer ret_gz.unstack();
4300 any_param_used = false; // we will check this later
4301 const ret_ref: Zir.Inst.Ref = inst: {
4302 // Parameters are in scope for the return type, so we use `params_scope` here.
4303 // The calling convention will not have parameters in scope, so we'll just use `scope`.
4304 // See #22263 for a proposal to solve the inconsistency here.
4305 const inst = try fullBodyExpr(&ret_gz, params_scope, coerced_type_ri, fn_proto.ast.return_type.unwrap().?, .normal);
4306 if (ret_gz.instructionsSlice().len == 0) {
4307 // In this case we will send a len=0 body which can be encoded more efficiently.
4308 break :inst inst;
4309 }
4310 _ = try ret_gz.addBreak(.break_inline, @fromBackingInt(@intCast(0)), inst);
4311 break :inst inst;
4312 };
4313 const ret_body_param_refs = try astgen.fetchRemoveRefEntries(param_insts.items);
4314 const ret_ty_is_generic = any_param_used;
4315
4315 var body_gz: GenZir = .{4316 var body_gz: GenZir = .{
4316 .is_comptime = false,4317 .is_comptime = false,
4317 .src_baseline = fn_proto.ast.proto_node,4318 .src_baseline = fn_proto.ast.proto_node,
...@@ -4490,14 +4491,6 @@ fn globalVarDecl(...@@ -4490,14 +4491,6 @@ fn globalVarDecl(
4490 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);4491 _ = try align_gz.addBreakWithSrcNode(.break_inline, decl_inst, align_inst, node);
4491 }4492 }
44924493
4493 var linksection_gz = type_gz.makeSubBlock(scope);
4494 defer linksection_gz.unstack();
4495
4496 if (var_decl.ast.section_node.unwrap()) |section_node| {
4497 const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_node);
4498 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
4499 }
4500
4501 var addrspace_gz = type_gz.makeSubBlock(scope);4494 var addrspace_gz = type_gz.makeSubBlock(scope);
4502 defer addrspace_gz.unstack();4495 defer addrspace_gz.unstack();
45034496
...@@ -4507,6 +4500,14 @@ fn globalVarDecl(...@@ -4507,6 +4500,14 @@ fn globalVarDecl(
4507 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);4500 _ = try addrspace_gz.addBreakWithSrcNode(.break_inline, decl_inst, addrspace_inst, node);
4508 }4501 }
45094502
4503 var linksection_gz = type_gz.makeSubBlock(scope);
4504 defer linksection_gz.unstack();
4505
4506 if (var_decl.ast.section_node.unwrap()) |section_node| {
4507 const linksection_inst = try expr(&linksection_gz, &linksection_gz.base, coerced_linksection_ri, section_node);
4508 _ = try linksection_gz.addBreakWithSrcNode(.break_inline, decl_inst, linksection_inst, node);
4509 }
4510
4510 var init_gz = type_gz.makeSubBlock(scope);4511 var init_gz = type_gz.makeSubBlock(scope);
4511 defer init_gz.unstack();4512 defer init_gz.unstack();
45124513
...@@ -4536,8 +4537,8 @@ fn globalVarDecl(...@@ -4536,8 +4537,8 @@ fn globalVarDecl(
45364537
4537 .type_gz = &type_gz,4538 .type_gz = &type_gz,
4538 .align_gz = &align_gz,4539 .align_gz = &align_gz,
4539 .linksection_gz = &linksection_gz,
4540 .addrspace_gz = &addrspace_gz,4540 .addrspace_gz = &addrspace_gz,
4541 .linksection_gz = &linksection_gz,
4541 .value_gz = &init_gz,4542 .value_gz = &init_gz,
4542 });4543 });
4543}4544}
...@@ -4599,8 +4600,8 @@ fn comptimeDecl(...@@ -4599,8 +4600,8 @@ fn comptimeDecl(
4599 .linkage = .normal,4600 .linkage = .normal,
4600 .type_gz = &dummy_gz,4601 .type_gz = &dummy_gz,
4601 .align_gz = &dummy_gz,4602 .align_gz = &dummy_gz,
4602 .linksection_gz = &dummy_gz,
4603 .addrspace_gz = &dummy_gz,4603 .addrspace_gz = &dummy_gz,
4604 .linksection_gz = &dummy_gz,
4604 .value_gz = &comptime_gz,4605 .value_gz = &comptime_gz,
4605 });4606 });
4606}4607}
...@@ -11527,8 +11528,8 @@ const GenZir = struct {...@@ -11527,8 +11528,8 @@ const GenZir = struct {
1152711528
11528 /// Must be called with the following stack set up:11529 /// Must be called with the following stack set up:
11529 /// * gz (bottom)11530 /// * gz (bottom)
11530 /// * ret_gz
11531 /// * cc_gz11531 /// * cc_gz
11532 /// * ret_gz
11532 /// * body_gz (top)11533 /// * body_gz (top)
11533 /// Unstacks all of those except for `gz`.11534 /// Unstacks all of those except for `gz`.
11534 fn addFunc(11535 fn addFunc(
...@@ -11575,16 +11576,16 @@ const GenZir = struct {...@@ -11575,16 +11576,16 @@ const GenZir = struct {
11575 stacked_gz = body_gz;11576 stacked_gz = body_gz;
11576 break :body body;11577 break :body body;
11577 } else &.{};11578 } else &.{};
11578 const cc_body: []const Zir.Inst.Index = if (args.cc_gz) |cc_gz| body: {
11579 const cc_body = cc_gz.instructionsSliceUptoOpt(stacked_gz);
11580 stacked_gz = cc_gz;
11581 break :body cc_body;
11582 } else &.{};
11583 const ret_body: []const Zir.Inst.Index = if (args.ret_gz) |ret_gz| body: {11579 const ret_body: []const Zir.Inst.Index = if (args.ret_gz) |ret_gz| body: {
11584 const ret_body = ret_gz.instructionsSliceUptoOpt(stacked_gz);11580 const ret_body = ret_gz.instructionsSliceUptoOpt(stacked_gz);
11585 stacked_gz = ret_gz;11581 stacked_gz = ret_gz;
11586 break :body ret_body;11582 break :body ret_body;
11587 } else &.{};11583 } else &.{};
11584 const cc_body: []const Zir.Inst.Index = if (args.cc_gz) |cc_gz| body: {
11585 const cc_body = cc_gz.instructionsSliceUptoOpt(stacked_gz);
11586 stacked_gz = cc_gz;
11587 break :body cc_body;
11588 } else &.{};
11588 break :bodies .{ body, cc_body, ret_body };11589 break :bodies .{ body, cc_body, ret_body };
11589 };11590 };
1159011591
...@@ -11725,8 +11726,8 @@ const GenZir = struct {...@@ -11725,8 +11726,8 @@ const GenZir = struct {
1172511726
11726 // Order is important when unstacking.11727 // Order is important when unstacking.
11727 if (args.body_gz) |body_gz| body_gz.unstack();11728 if (args.body_gz) |body_gz| body_gz.unstack();
11728 if (args.cc_gz) |cc_gz| cc_gz.unstack();
11729 if (args.ret_gz) |ret_gz| ret_gz.unstack();11729 if (args.ret_gz) |ret_gz| ret_gz.unstack();
11730 if (args.cc_gz) |cc_gz| cc_gz.unstack();
1173011731
11731 astgen.instructions.appendAssumeCapacity(.{11732 astgen.instructions.appendAssumeCapacity(.{
11732 .tag = tag,11733 .tag = tag,
...@@ -13502,10 +13503,10 @@ fn setDeclaration(...@@ -13502,10 +13503,10 @@ fn setDeclaration(
13502 /// Must be stacked on `type_gz`.13503 /// Must be stacked on `type_gz`.
13503 align_gz: *GenZir,13504 align_gz: *GenZir,
13504 /// Must be stacked on `align_gz`.13505 /// Must be stacked on `align_gz`.
13505 linksection_gz: *GenZir,
13506 /// Must be stacked on `linksection_gz`.
13507 addrspace_gz: *GenZir,13506 addrspace_gz: *GenZir,
13508 /// Must be stacked on `addrspace_gz` and have nothing stacked on top of it.13507 /// Must be stacked on `addrspace_gz`.
13508 linksection_gz: *GenZir,
13509 /// Must be stacked on `linksection_gz` and have nothing stacked on top of it.
13509 value_gz: *GenZir,13510 value_gz: *GenZir,
13510 },13511 },
13511) !void {13512) !void {
...@@ -13513,9 +13514,9 @@ fn setDeclaration(...@@ -13513,9 +13514,9 @@ fn setDeclaration(
13513 const gpa = astgen.gpa;13514 const gpa = astgen.gpa;
1351413515
13515 const type_body = args.type_gz.instructionsSliceUpto(args.align_gz);13516 const type_body = args.type_gz.instructionsSliceUpto(args.align_gz);
13516 const align_body = args.align_gz.instructionsSliceUpto(args.linksection_gz);13517 const align_body = args.align_gz.instructionsSliceUpto(args.addrspace_gz);
13517 const linksection_body = args.linksection_gz.instructionsSliceUpto(args.addrspace_gz);13518 const addrspace_body = args.addrspace_gz.instructionsSliceUpto(args.linksection_gz);
13518 const addrspace_body = args.addrspace_gz.instructionsSliceUpto(args.value_gz);13519 const linksection_body = args.linksection_gz.instructionsSliceUpto(args.value_gz);
13519 const value_body = args.value_gz.instructionsSlice();13520 const value_body = args.value_gz.instructionsSlice();
1352013521
13521 const has_name = args.name != .empty;13522 const has_name = args.name != .empty;
test/cases/decl_qualifier_cursor.zig created+45
...@@ -0,0 +1,45 @@
1const lang = @import("std").lang;
2
3fn al() comptime_int {
4 return 16;
5}
6
7fn as() lang.AddressSpace {
8 return .generic;
9}
10
11fn ls() []const u8 {
12 return "text";
13}
14
15fn cc() lang.CallingConvention {
16 return .c;
17}
18
19fn rv() type {
20 return void;
21}
22
23extern var a: u64 align(al()) addrspace(as()) linksection(ls());
24extern fn b() align(al()) addrspace(as()) linksection(ls()) callconv(cc()) rv();
25// Intentionally not `export` so it is never analyzed since the qualifiers are
26// not valid for all targets. The main point of this test is checking that Zir
27// generation is done correctly for these, so the above is not an issue.
28fn c() align(al()) addrspace(as()) linksection(ls()) callconv(cc()) rv() {
29 const v: struct {
30 x: u32,
31 y: u32,
32 } align(al()) = undefined;
33 const ta: u64, const tb: struct {
34 x: u32,
35 y: u32,
36 } align(al()) = .{ 0, .{ .x = 10, .y = 20 } };
37 _ = v;
38 _ = a;
39 _ = b;
40 _ = ta;
41 _ = tb;
42}
43
44// compile
45// output_mode=Obj