authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-01 16:21:38-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-07-02 13:27:35-07:00
log41336acb0bb89dd23ef9c49b15d91a847f6796bc
tree4823d19caddb3cd25c7a6e5a4b44ca7a2e0d5c03
parentabfee127353cbdadab4282b61056222cdfbec2d4

AstGen: detect redeclaration of function parameters

Also improve redeclaration error message to include the category of variable.

2 files changed, 113 insertions(+), 111 deletions(-)

lib/std/os/uefi/protocols/simple_network_protocol.zig+4-4
...@@ -57,13 +57,13 @@ pub const SimpleNetworkProtocol = extern struct {...@@ -57,13 +57,13 @@ pub const SimpleNetworkProtocol = extern struct {
57 }57 }
5858
59 /// Modifies or resets the current station address, if supported.59 /// Modifies or resets the current station address, if supported.
60 pub fn stationAddress(self: *const SimpleNetworkProtocol, reset: bool, new: ?*const MacAddress) Status {60 pub fn stationAddress(self: *const SimpleNetworkProtocol, reset_flag: bool, new: ?*const MacAddress) Status {
61 return self._station_address(self, reset, new);61 return self._station_address(self, reset_flag, new);
62 }62 }
6363
64 /// Resets or collects the statistics on a network interface.64 /// Resets or collects the statistics on a network interface.
65 pub fn statistics(self: *const SimpleNetworkProtocol, reset_: bool, statistics_size: ?*usize, statistics_table: ?*NetworkStatistics) Status {65 pub fn statistics(self: *const SimpleNetworkProtocol, reset_flag: bool, statistics_size: ?*usize, statistics_table: ?*NetworkStatistics) Status {
66 return self._statistics(self, reset_, statistics_size, statistics_table);66 return self._statistics(self, reset_flag, statistics_size, statistics_table);
67 }67 }
6868
69 /// Converts a multicast IP address to a multicast HW MAC address.69 /// Converts a multicast IP address to a multicast HW MAC address.
src/AstGen.zig+109-107
...@@ -2216,25 +2216,15 @@ fn checkUsed(...@@ -2216,25 +2216,15 @@ fn checkUsed(
2216 .gen_zir => scope = scope.cast(GenZir).?.parent,2216 .gen_zir => scope = scope.cast(GenZir).?.parent,
2217 .local_val => {2217 .local_val => {
2218 const s = scope.cast(Scope.LocalVal).?;2218 const s = scope.cast(Scope.LocalVal).?;
2219 switch (s.used) {2219 if (!s.used) {
2220 .used => {},2220 return astgen.failTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
2221 .fn_param => return astgen.failTok(s.token_src, "unused function parameter", .{}),
2222 .constant => return astgen.failTok(s.token_src, "unused local constant", .{}),
2223 .variable => unreachable,
2224 .loop_index => unreachable,
2225 .capture => return astgen.failTok(s.token_src, "unused capture", .{}),
2226 }2221 }
2227 scope = s.parent;2222 scope = s.parent;
2228 },2223 },
2229 .local_ptr => {2224 .local_ptr => {
2230 const s = scope.cast(Scope.LocalPtr).?;2225 const s = scope.cast(Scope.LocalPtr).?;
2231 switch (s.used) {2226 if (!s.used) {
2232 .used => {},2227 return astgen.failTok(s.token_src, "unused {s}", .{@tagName(s.id_cat)});
2233 .fn_param => unreachable,
2234 .constant => return astgen.failTok(s.token_src, "unused local constant", .{}),
2235 .variable => return astgen.failTok(s.token_src, "unused local variable", .{}),
2236 .loop_index => return astgen.failTok(s.token_src, "unused loop index capture", .{}),
2237 .capture => unreachable,
2238 }2228 }
2239 scope = s.parent;2229 scope = s.parent;
2240 },2230 },
...@@ -2280,63 +2270,7 @@ fn varDecl(...@@ -2280,63 +2270,7 @@ fn varDecl(
2280 }2270 }
2281 const ident_name = try astgen.identAsString(name_token);2271 const ident_name = try astgen.identAsString(name_token);
22822272
2283 // Local variables shadowing detection, including function parameters.2273 try astgen.detectLocalShadowing(scope, ident_name, name_token);
2284 {
2285 var s = scope;
2286 while (true) switch (s.tag) {
2287 .local_val => {
2288 const local_val = s.cast(Scope.LocalVal).?;
2289 if (local_val.name == ident_name) {
2290 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name)));
2291 defer gpa.free(name);
2292 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{
2293 name,
2294 }, &[_]u32{
2295 try astgen.errNoteTok(
2296 local_val.token_src,
2297 "previously declared here",
2298 .{},
2299 ),
2300 });
2301 }
2302 s = local_val.parent;
2303 },
2304 .local_ptr => {
2305 const local_ptr = s.cast(Scope.LocalPtr).?;
2306 if (local_ptr.name == ident_name) {
2307 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name)));
2308 defer gpa.free(name);
2309 return astgen.failTokNotes(name_token, "redeclaration of '{s}'", .{
2310 name,
2311 }, &[_]u32{
2312 try astgen.errNoteTok(
2313 local_ptr.token_src,
2314 "previously declared here",
2315 .{},
2316 ),
2317 });
2318 }
2319 s = local_ptr.parent;
2320 },
2321 .namespace => {
2322 const ns = s.cast(Scope.Namespace).?;
2323 const decl_node = ns.decls.get(ident_name) orelse {
2324 s = ns.parent;
2325 continue;
2326 };
2327 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name)));
2328 defer gpa.free(name);
2329 return astgen.failTokNotes(name_token, "local shadows declaration of '{s}'", .{
2330 name,
2331 }, &[_]u32{
2332 try astgen.errNoteNode(decl_node, "declared here", .{}),
2333 });
2334 },
2335 .gen_zir => s = s.cast(GenZir).?.parent,
2336 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
2337 .top => break,
2338 };
2339 }
23402274
2341 if (var_decl.ast.init_node == 0) {2275 if (var_decl.ast.init_node == 0) {
2342 return astgen.failNode(node, "variables must be initialized", .{});2276 return astgen.failNode(node, "variables must be initialized", .{});
...@@ -2369,7 +2303,7 @@ fn varDecl(...@@ -2369,7 +2303,7 @@ fn varDecl(
2369 .name = ident_name,2303 .name = ident_name,
2370 .inst = init_inst,2304 .inst = init_inst,
2371 .token_src = name_token,2305 .token_src = name_token,
2372 .used = .constant,2306 .id_cat = .@"local constant",
2373 };2307 };
2374 return &sub_scope.base;2308 return &sub_scope.base;
2375 }2309 }
...@@ -2438,7 +2372,7 @@ fn varDecl(...@@ -2438,7 +2372,7 @@ fn varDecl(
2438 .name = ident_name,2372 .name = ident_name,
2439 .inst = init_inst,2373 .inst = init_inst,
2440 .token_src = name_token,2374 .token_src = name_token,
2441 .used = .constant,2375 .id_cat = .@"local constant",
2442 };2376 };
2443 return &sub_scope.base;2377 return &sub_scope.base;
2444 }2378 }
...@@ -2468,7 +2402,7 @@ fn varDecl(...@@ -2468,7 +2402,7 @@ fn varDecl(
2468 .ptr = init_scope.rl_ptr,2402 .ptr = init_scope.rl_ptr,
2469 .token_src = name_token,2403 .token_src = name_token,
2470 .maybe_comptime = true,2404 .maybe_comptime = true,
2471 .used = .constant,2405 .id_cat = .@"local constant",
2472 };2406 };
2473 return &sub_scope.base;2407 return &sub_scope.base;
2474 },2408 },
...@@ -2525,7 +2459,7 @@ fn varDecl(...@@ -2525,7 +2459,7 @@ fn varDecl(
2525 .ptr = var_data.alloc,2459 .ptr = var_data.alloc,
2526 .token_src = name_token,2460 .token_src = name_token,
2527 .maybe_comptime = is_comptime,2461 .maybe_comptime = is_comptime,
2528 .used = .variable,2462 .id_cat = .@"local variable",
2529 };2463 };
2530 return &sub_scope.base;2464 return &sub_scope.base;
2531 },2465 },
...@@ -3028,7 +2962,7 @@ fn fnDecl(...@@ -3028,7 +2962,7 @@ fn fnDecl(
3028 const param_name = try astgen.identAsString(name_token);2962 const param_name = try astgen.identAsString(name_token);
3029 // Create an arg instruction. This is needed to emit a semantic analysis2963 // Create an arg instruction. This is needed to emit a semantic analysis
3030 // error for shadowing decls.2964 // error for shadowing decls.
3031 // TODO emit a compile error here for shadowing locals.2965 try astgen.detectLocalShadowing(params_scope, param_name, name_token);
3032 const arg_inst = try fn_gz.addStrTok(.arg, param_name, name_token);2966 const arg_inst = try fn_gz.addStrTok(.arg, param_name, name_token);
3033 const sub_scope = try astgen.arena.create(Scope.LocalVal);2967 const sub_scope = try astgen.arena.create(Scope.LocalVal);
3034 sub_scope.* = .{2968 sub_scope.* = .{
...@@ -3037,7 +2971,7 @@ fn fnDecl(...@@ -3037,7 +2971,7 @@ fn fnDecl(
3037 .name = param_name,2971 .name = param_name,
3038 .inst = arg_inst,2972 .inst = arg_inst,
3039 .token_src = name_token,2973 .token_src = name_token,
3040 .used = .fn_param,2974 .id_cat = .@"function parameter",
3041 };2975 };
3042 params_scope = &sub_scope.base;2976 params_scope = &sub_scope.base;
30432977
...@@ -4701,7 +4635,7 @@ fn orelseCatchExpr(...@@ -4701,7 +4635,7 @@ fn orelseCatchExpr(
4701 .name = err_name,4635 .name = err_name,
4702 .inst = try then_scope.addUnNode(unwrap_code_op, operand, node),4636 .inst = try then_scope.addUnNode(unwrap_code_op, operand, node),
4703 .token_src = payload,4637 .token_src = payload,
4704 .used = .capture,4638 .id_cat = .@"capture",
4705 };4639 };
4706 break :blk &err_val_scope.base;4640 break :blk &err_val_scope.base;
4707 };4641 };
...@@ -4993,7 +4927,7 @@ fn ifExpr(...@@ -4993,7 +4927,7 @@ fn ifExpr(
4993 .name = ident_name,4927 .name = ident_name,
4994 .inst = payload_inst,4928 .inst = payload_inst,
4995 .token_src = payload_token,4929 .token_src = payload_token,
4996 .used = .capture,4930 .id_cat = .@"capture",
4997 };4931 };
4998 break :s &payload_val_scope.base;4932 break :s &payload_val_scope.base;
4999 } else {4933 } else {
...@@ -5015,7 +4949,7 @@ fn ifExpr(...@@ -5015,7 +4949,7 @@ fn ifExpr(
5015 .name = ident_name,4949 .name = ident_name,
5016 .inst = payload_inst,4950 .inst = payload_inst,
5017 .token_src = ident_token,4951 .token_src = ident_token,
5018 .used = .capture,4952 .id_cat = .@"capture",
5019 };4953 };
5020 break :s &payload_val_scope.base;4954 break :s &payload_val_scope.base;
5021 } else {4955 } else {
...@@ -5056,7 +4990,7 @@ fn ifExpr(...@@ -5056,7 +4990,7 @@ fn ifExpr(
5056 .name = ident_name,4990 .name = ident_name,
5057 .inst = payload_inst,4991 .inst = payload_inst,
5058 .token_src = error_token,4992 .token_src = error_token,
5059 .used = .capture,4993 .id_cat = .@"capture",
5060 };4994 };
5061 break :s &payload_val_scope.base;4995 break :s &payload_val_scope.base;
5062 } else {4996 } else {
...@@ -5250,7 +5184,7 @@ fn whileExpr(...@@ -5250,7 +5184,7 @@ fn whileExpr(
5250 .name = ident_name,5184 .name = ident_name,
5251 .inst = payload_inst,5185 .inst = payload_inst,
5252 .token_src = payload_token,5186 .token_src = payload_token,
5253 .used = .capture,5187 .id_cat = .@"capture",
5254 };5188 };
5255 break :s &payload_val_scope.base;5189 break :s &payload_val_scope.base;
5256 } else {5190 } else {
...@@ -5272,7 +5206,7 @@ fn whileExpr(...@@ -5272,7 +5206,7 @@ fn whileExpr(
5272 .name = ident_name,5206 .name = ident_name,
5273 .inst = payload_inst,5207 .inst = payload_inst,
5274 .token_src = ident_token,5208 .token_src = ident_token,
5275 .used = .capture,5209 .id_cat = .@"capture",
5276 };5210 };
5277 break :s &payload_val_scope.base;5211 break :s &payload_val_scope.base;
5278 } else {5212 } else {
...@@ -5329,7 +5263,7 @@ fn whileExpr(...@@ -5329,7 +5263,7 @@ fn whileExpr(
5329 .name = ident_name,5263 .name = ident_name,
5330 .inst = payload_inst,5264 .inst = payload_inst,
5331 .token_src = error_token,5265 .token_src = error_token,
5332 .used = .capture,5266 .id_cat = .@"capture",
5333 };5267 };
5334 break :s &payload_val_scope.base;5268 break :s &payload_val_scope.base;
5335 } else {5269 } else {
...@@ -5468,7 +5402,7 @@ fn forExpr(...@@ -5468,7 +5402,7 @@ fn forExpr(
5468 .name = name_str_index,5402 .name = name_str_index,
5469 .inst = payload_inst,5403 .inst = payload_inst,
5470 .token_src = ident,5404 .token_src = ident,
5471 .used = .capture,5405 .id_cat = .@"capture",
5472 };5406 };
5473 payload_sub_scope = &payload_val_scope.base;5407 payload_sub_scope = &payload_val_scope.base;
5474 } else if (is_ptr) {5408 } else if (is_ptr) {
...@@ -5492,7 +5426,7 @@ fn forExpr(...@@ -5492,7 +5426,7 @@ fn forExpr(
5492 .ptr = index_ptr,5426 .ptr = index_ptr,
5493 .token_src = index_token,5427 .token_src = index_token,
5494 .maybe_comptime = is_inline,5428 .maybe_comptime = is_inline,
5495 .used = .loop_index,5429 .id_cat = .@"loop index capture",
5496 };5430 };
5497 break :blk &index_scope.base;5431 break :blk &index_scope.base;
5498 };5432 };
...@@ -5737,7 +5671,7 @@ fn switchExpr(...@@ -5737,7 +5671,7 @@ fn switchExpr(
5737 .name = capture_name,5671 .name = capture_name,
5738 .inst = capture,5672 .inst = capture,
5739 .token_src = payload_token,5673 .token_src = payload_token,
5740 .used = .capture,5674 .id_cat = .@"capture",
5741 };5675 };
5742 break :blk &capture_val_scope.base;5676 break :blk &capture_val_scope.base;
5743 };5677 };
...@@ -5831,7 +5765,7 @@ fn switchExpr(...@@ -5831,7 +5765,7 @@ fn switchExpr(
5831 .name = capture_name,5765 .name = capture_name,
5832 .inst = capture,5766 .inst = capture,
5833 .token_src = payload_token,5767 .token_src = payload_token,
5834 .used = .capture,5768 .id_cat = .@"capture",
5835 };5769 };
5836 break :blk &capture_val_scope.base;5770 break :blk &capture_val_scope.base;
5837 };5771 };
...@@ -6261,7 +6195,7 @@ fn identifier(...@@ -6261,7 +6195,7 @@ fn identifier(
6261 const local_val = s.cast(Scope.LocalVal).?;6195 const local_val = s.cast(Scope.LocalVal).?;
62626196
6263 if (local_val.name == name_str_index) {6197 if (local_val.name == name_str_index) {
6264 local_val.used = .used;6198 local_val.used = true;
6265 // Captures of non-locals need to be emitted as decl_val or decl_ref.6199 // Captures of non-locals need to be emitted as decl_val or decl_ref.
6266 // This *might* be capturable depending on if it is comptime known.6200 // This *might* be capturable depending on if it is comptime known.
6267 if (!hit_namespace) {6201 if (!hit_namespace) {
...@@ -6273,7 +6207,7 @@ fn identifier(...@@ -6273,7 +6207,7 @@ fn identifier(
6273 .local_ptr => {6207 .local_ptr => {
6274 const local_ptr = s.cast(Scope.LocalPtr).?;6208 const local_ptr = s.cast(Scope.LocalPtr).?;
6275 if (local_ptr.name == name_str_index) {6209 if (local_ptr.name == name_str_index) {
6276 local_ptr.used = .used;6210 local_ptr.used = true;
6277 if (hit_namespace) {6211 if (hit_namespace) {
6278 if (local_ptr.maybe_comptime)6212 if (local_ptr.maybe_comptime)
6279 break6213 break
...@@ -6609,7 +6543,7 @@ fn asmExpr(...@@ -6609,7 +6543,7 @@ fn asmExpr(
6609 .local_val => {6543 .local_val => {
6610 const local_val = s.cast(Scope.LocalVal).?;6544 const local_val = s.cast(Scope.LocalVal).?;
6611 if (local_val.name == str_index) {6545 if (local_val.name == str_index) {
6612 local_val.used = .used;6546 local_val.used = true;
6613 break;6547 break;
6614 }6548 }
6615 s = local_val.parent;6549 s = local_val.parent;
...@@ -6617,7 +6551,7 @@ fn asmExpr(...@@ -6617,7 +6551,7 @@ fn asmExpr(
6617 .local_ptr => {6551 .local_ptr => {
6618 const local_ptr = s.cast(Scope.LocalPtr).?;6552 const local_ptr = s.cast(Scope.LocalPtr).?;
6619 if (local_ptr.name == str_index) {6553 if (local_ptr.name == str_index) {
6620 local_ptr.used = .used;6554 local_ptr.used = true;
6621 break;6555 break;
6622 }6556 }
6623 s = local_ptr.parent;6557 s = local_ptr.parent;
...@@ -6968,7 +6902,7 @@ fn builtinCall(...@@ -6968,7 +6902,7 @@ fn builtinCall(
6968 .local_val => {6902 .local_val => {
6969 const local_val = s.cast(Scope.LocalVal).?;6903 const local_val = s.cast(Scope.LocalVal).?;
6970 if (local_val.name == decl_name) {6904 if (local_val.name == decl_name) {
6971 local_val.used = .used;6905 local_val.used = true;
6972 break;6906 break;
6973 }6907 }
6974 s = local_val.parent;6908 s = local_val.parent;
...@@ -6978,7 +6912,7 @@ fn builtinCall(...@@ -6978,7 +6912,7 @@ fn builtinCall(
6978 if (local_ptr.name == decl_name) {6912 if (local_ptr.name == decl_name) {
6979 if (!local_ptr.maybe_comptime)6913 if (!local_ptr.maybe_comptime)
6980 return astgen.failNode(params[0], "unable to export runtime-known value", .{});6914 return astgen.failNode(params[0], "unable to export runtime-known value", .{});
6981 local_ptr.used = .used;6915 local_ptr.used = true;
6982 break;6916 break;
6983 }6917 }
6984 s = local_ptr.parent;6918 s = local_ptr.parent;
...@@ -8545,15 +8479,15 @@ const Scope = struct {...@@ -8545,15 +8479,15 @@ const Scope = struct {
8545 top,8479 top,
8546 };8480 };
85478481
8548 // either .used or the type of the var/constant8482 /// The category of identifier. These tag names are user-visible in compile errors.
8549 const Used = enum {8483 const IdCat = enum {
8550 fn_param,8484 @"function parameter",
8551 constant,8485 @"local constant",
8552 variable,8486 @"local variable",
8553 loop_index,8487 @"loop index capture",
8554 capture,8488 @"capture",
8555 used,
8556 };8489 };
8490
8557 /// This is always a `const` local and importantly the `inst` is a value type, not a pointer.8491 /// This is always a `const` local and importantly the `inst` is a value type, not a pointer.
8558 /// This structure lives as long as the AST generation of the Block8492 /// This structure lives as long as the AST generation of the Block
8559 /// node that contains the variable.8493 /// node that contains the variable.
...@@ -8568,8 +8502,9 @@ const Scope = struct {...@@ -8568,8 +8502,9 @@ const Scope = struct {
8568 token_src: ast.TokenIndex,8502 token_src: ast.TokenIndex,
8569 /// String table index.8503 /// String table index.
8570 name: u32,8504 name: u32,
8571 /// has this variable been referenced?8505 id_cat: IdCat,
8572 used: Used,8506 /// Track whether the name has been referenced.
8507 used: bool = false,
8573 };8508 };
85748509
8575 /// This could be a `const` or `var` local. It has a pointer instead of a value.8510 /// This could be a `const` or `var` local. It has a pointer instead of a value.
...@@ -8586,10 +8521,12 @@ const Scope = struct {...@@ -8586,10 +8521,12 @@ const Scope = struct {
8586 token_src: ast.TokenIndex,8521 token_src: ast.TokenIndex,
8587 /// String table index.8522 /// String table index.
8588 name: u32,8523 name: u32,
8589 /// true means we find out during Sema whether the value is comptime. false means it is already known at AstGen the value is runtime-known.8524 id_cat: IdCat,
8525 /// true means we find out during Sema whether the value is comptime.
8526 /// false means it is already known at AstGen the value is runtime-known.
8590 maybe_comptime: bool,8527 maybe_comptime: bool,
8591 /// has this variable been referenced?8528 /// Track whether the name has been referenced.
8592 used: Used,8529 used: bool = false,
8593 };8530 };
85948531
8595 const Defer = struct {8532 const Defer = struct {
...@@ -9680,6 +9617,71 @@ fn declareNewName(...@@ -9680,6 +9617,71 @@ fn declareNewName(
9680 }9617 }
9681}9618}
96829619
9620/// Local variables shadowing detection, including function parameters.
9621fn detectLocalShadowing(
9622 astgen: *AstGen,
9623 scope: *Scope,
9624 ident_name: u32,
9625 name_token: ast.TokenIndex,
9626) !void {
9627 const gpa = astgen.gpa;
9628
9629 var s = scope;
9630 while (true) switch (s.tag) {
9631 .local_val => {
9632 const local_val = s.cast(Scope.LocalVal).?;
9633 if (local_val.name == ident_name) {
9634 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name)));
9635 defer gpa.free(name);
9636 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
9637 @tagName(local_val.id_cat), name,
9638 }, &[_]u32{
9639 try astgen.errNoteTok(
9640 local_val.token_src,
9641 "previously declared here",
9642 .{},
9643 ),
9644 });
9645 }
9646 s = local_val.parent;
9647 },
9648 .local_ptr => {
9649 const local_ptr = s.cast(Scope.LocalPtr).?;
9650 if (local_ptr.name == ident_name) {
9651 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name)));
9652 defer gpa.free(name);
9653 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
9654 @tagName(local_ptr.id_cat), name,
9655 }, &[_]u32{
9656 try astgen.errNoteTok(
9657 local_ptr.token_src,
9658 "previously declared here",
9659 .{},
9660 ),
9661 });
9662 }
9663 s = local_ptr.parent;
9664 },
9665 .namespace => {
9666 const ns = s.cast(Scope.Namespace).?;
9667 const decl_node = ns.decls.get(ident_name) orelse {
9668 s = ns.parent;
9669 continue;
9670 };
9671 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(ident_name)));
9672 defer gpa.free(name);
9673 return astgen.failTokNotes(name_token, "local shadows declaration of '{s}'", .{
9674 name,
9675 }, &[_]u32{
9676 try astgen.errNoteNode(decl_node, "declared here", .{}),
9677 });
9678 },
9679 .gen_zir => s = s.cast(GenZir).?.parent,
9680 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
9681 .top => break,
9682 };
9683}
9684
9683fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {9685fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void {
9684 var i = astgen.source_offset;9686 var i = astgen.source_offset;
9685 var line = astgen.source_line;9687 var line = astgen.source_line;