diff --git a/src/AstGen.zig b/src/AstGen.zig index cf4ee91366..f49d5de6e3 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -1683,7 +1683,7 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn const defer_scope = scope.cast(Scope.Defer).?; scope = defer_scope.parent; const expr_node = node_datas[defer_scope.defer_node].rhs; - _ = try unusedResultExpr(parent_gz, defer_scope.parent, expr_node); + try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node); }, .defer_error => scope = scope.cast(Scope.Defer).?.parent, .top => unreachable, @@ -1736,7 +1736,7 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) const defer_scope = scope.cast(Scope.Defer).?; scope = defer_scope.parent; const expr_node = node_datas[defer_scope.defer_node].rhs; - _ = try unusedResultExpr(parent_gz, defer_scope.parent, expr_node); + try unusedResultDeferExpr(parent_gz, defer_scope, defer_scope.parent, expr_node); }, .defer_error => scope = scope.cast(Scope.Defer).?.parent, .namespace => break, @@ -1922,8 +1922,8 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod .simple_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.simpleVarDecl(statement)), .aligned_var_decl => scope = try varDecl(gz, scope, statement, &block_arena.allocator, tree.alignedVarDecl(statement)), - .@"defer" => scope = try makeDeferScope(scope, statement, &block_arena.allocator, .defer_normal), - .@"errdefer" => scope = try makeDeferScope(scope, statement, &block_arena.allocator, .defer_error), + .@"defer" => scope = try makeDeferScope(gz.astgen, scope, statement, &block_arena.allocator, .defer_normal), + .@"errdefer" => scope = try makeDeferScope(gz.astgen, scope, statement, &block_arena.allocator, .defer_error), .assign => try assign(gz, scope, statement), @@ -1951,6 +1951,22 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod try checkUsed(gz, parent_scope, scope); } +fn unusedResultDeferExpr(gz: *GenZir, defer_scope: *Scope.Defer, expr_scope: *Scope, expr_node: Ast.Node.Index) InnerError!void { + const astgen = gz.astgen; + const prev_offset = astgen.source_offset; + const prev_line = astgen.source_line; + const prev_column = astgen.source_column; + defer { + astgen.source_offset = prev_offset; + astgen.source_line = prev_line; + astgen.source_column = prev_column; + } + astgen.source_offset = defer_scope.source_offset; + astgen.source_line = defer_scope.source_line; + astgen.source_column = defer_scope.source_column; + _ = try unusedResultExpr(gz, expr_scope, expr_node); +} + /// Returns AST source node of the thing that is noreturn if the statement is definitely `noreturn`. /// Otherwise returns 0. fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) InnerError!Ast.Node.Index { @@ -2333,7 +2349,7 @@ fn genDefers( const prev_in_defer = gz.in_defer; gz.in_defer = true; defer gz.in_defer = prev_in_defer; - _ = try unusedResultExpr(gz, defer_scope.parent, expr_node); + try unusedResultDeferExpr(gz, defer_scope, defer_scope.parent, expr_node); }, .defer_error => { const defer_scope = scope.cast(Scope.Defer).?; @@ -2344,7 +2360,7 @@ fn genDefers( const prev_in_defer = gz.in_defer; gz.in_defer = true; defer gz.in_defer = prev_in_defer; - _ = try unusedResultExpr(gz, defer_scope.parent, expr_node); + try unusedResultDeferExpr(gz, defer_scope, defer_scope.parent, expr_node); }, .both => |err_code| { const expr_node = node_datas[defer_scope.defer_node].rhs; @@ -2365,7 +2381,7 @@ fn genDefers( }; break :blk &local_val_scope.base; }; - _ = try unusedResultExpr(gz, sub_scope, expr_node); + try unusedResultDeferExpr(gz, defer_scope, sub_scope, expr_node); }, .normal_only => continue, } @@ -2409,16 +2425,27 @@ fn checkUsed( } fn makeDeferScope( + astgen: *AstGen, scope: *Scope, node: Ast.Node.Index, block_arena: *Allocator, scope_tag: Scope.Tag, ) InnerError!*Scope { + const tree = astgen.tree; + const node_datas = tree.nodes.items(.data); + const expr_node = node_datas[node].rhs; + const token_starts = tree.tokens.items(.start); + const node_start = token_starts[tree.firstToken(expr_node)]; const defer_scope = try block_arena.create(Scope.Defer); + astgen.advanceSourceCursor(tree.source, node_start); + defer_scope.* = .{ .base = .{ .tag = scope_tag }, .parent = scope, .defer_node = node, + .source_offset = astgen.source_offset, + .source_line = astgen.source_line, + .source_column = astgen.source_column, }; return &defer_scope.base; } @@ -9245,6 +9272,9 @@ const Scope = struct { /// Parents can be: `LocalVal`, `LocalPtr`, `GenZir`, `Defer`, `Namespace`. parent: *Scope, defer_node: Ast.Node.Index, + source_offset: u32, + source_line: u32, + source_column: u32, }; /// Represents a global scope that has any number of declarations in it.