diff --git a/doc/docgen.zig b/doc/docgen.zig index 636f633805..4007fa099c 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -318,7 +318,7 @@ const Action = enum { fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc { var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator); - %defer urls.deinit(); + errdefer urls.deinit(); var header_stack_size: usize = 0; var last_action = Action.Open; @@ -399,7 +399,7 @@ fn genToc(allocator: &mem.Allocator, tokenizer: &Tokenizer) -> %Toc { } } else if (mem.eql(u8, tag_name, "see_also")) { var list = std.ArrayList(SeeAlsoItem).init(allocator); - %defer list.deinit(); + errdefer list.deinit(); while (true) { const see_also_tok = tokenizer.next(); diff --git a/doc/langref.html.in b/doc/langref.html.in index 3734d9ff75..601b53463f 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2533,7 +2533,7 @@ test "defer unwinding" { deferUnwindExample(); } -// The %defer keyword is similar to defer, but will only execute if the +// The errdefer keyword is similar to defer, but will only execute if the // scope returns with an error. // // This is especially useful in allowing a function to clean up properly @@ -2547,7 +2547,7 @@ fn deferErrorExample(is_error: bool) -> %void { warn("end of function\n"); } - %defer { + errdefer { warn("encountered an error!\n"); } @@ -2556,7 +2556,7 @@ fn deferErrorExample(is_error: bool) -> %void { } } -test "%defer unwinding" { +test "errdefer unwinding" { _ = deferErrorExample(false); _ = deferErrorExample(true); } @@ -2922,7 +2922,7 @@ fn doAThing(str: []u8) { {#code_end#}

The other component to error handling is defer statements. - In addition to an unconditional defer, Zig has %defer, + In addition to an unconditional defer, Zig has errdefer, which evaluates the deferred expression on block exit path if and only if the function returned with an error from the block.

@@ -2934,7 +2934,7 @@ fn createFoo(param: i32) -> %Foo { const foo = try tryToAllocateFoo(); // now we have allocated foo. we need to free it if the function fails. // but we want to return it if the function succeeds. - %defer deallocateFoo(foo); + errdefer deallocateFoo(foo); const tmp_buf = allocateTmpBuffer() ?? return error.OutOfMemory; // tmp_buf is truly a temporary resource, and we for sure want to clean it up @@ -2943,7 +2943,7 @@ fn createFoo(param: i32) -> %Foo { if (param > 1337) return error.InvalidParam; - // here the %defer will not run since we're returning success from the function. + // here the errdefer will not run since we're returning success from the function. // but the defer will run! return foo; } @@ -5619,7 +5619,7 @@ TryExpression = "try" Expression BreakExpression = "break" option(":" Symbol) option(Expression) -Defer(body) = option("%") "defer" body +Defer(body) = ("defer" | "deferror") body IfExpression(body) = "if" "(" Expression ")" body option("else" BlockExpression(body)) diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 80df1aaac9..8a2f6888eb 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -371,7 +371,7 @@ pub fn main2() -> %void { defer allocator.free(full_cache_dir); const zig_lib_dir = try resolveZigLibDir(allocator, zig_install_prefix); - %defer allocator.free(zig_lib_dir); + errdefer allocator.free(zig_lib_dir); const module = try Module.create(allocator, root_name, zig_root_source_file, Target.Native, build_kind, build_mode, zig_lib_dir, full_cache_dir); @@ -587,7 +587,7 @@ fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const /// Caller must free result fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[]u8 { const test_zig_dir = try os.path.join(allocator, test_path, "lib", "zig"); - %defer allocator.free(test_zig_dir); + errdefer allocator.free(test_zig_dir); const test_index_file = try os.path.join(allocator, test_zig_dir, "std", "index.zig"); defer allocator.free(test_index_file); diff --git a/src-self-hosted/module.zig b/src-self-hosted/module.zig index f17175cc61..c246468915 100644 --- a/src-self-hosted/module.zig +++ b/src-self-hosted/module.zig @@ -113,19 +113,19 @@ pub const Module = struct { kind: Kind, build_mode: builtin.Mode, zig_lib_dir: []const u8, cache_dir: []const u8) -> %&Module { var name_buffer = try Buffer.init(allocator, name); - %defer name_buffer.deinit(); + errdefer name_buffer.deinit(); const context = c.LLVMContextCreate() ?? return error.OutOfMemory; - %defer c.LLVMContextDispose(context); + errdefer c.LLVMContextDispose(context); const module = c.LLVMModuleCreateWithNameInContext(name_buffer.ptr(), context) ?? return error.OutOfMemory; - %defer c.LLVMDisposeModule(module); + errdefer c.LLVMDisposeModule(module); const builder = c.LLVMCreateBuilderInContext(context) ?? return error.OutOfMemory; - %defer c.LLVMDisposeBuilder(builder); + errdefer c.LLVMDisposeBuilder(builder); const module_ptr = try allocator.create(Module); - %defer allocator.destroy(module_ptr); + errdefer allocator.destroy(module_ptr); *module_ptr = Module { .allocator = allocator, @@ -211,13 +211,13 @@ pub const Module = struct { try printError("unable to get real path '{}': {}", root_src_path, err); return err; }; - %defer self.allocator.free(root_src_real_path); + errdefer self.allocator.free(root_src_real_path); const source_code = io.readFileAllocExtra(root_src_real_path, self.allocator, 3) catch |err| { try printError("unable to open '{}': {}", root_src_real_path, err); return err; }; - %defer self.allocator.free(source_code); + errdefer self.allocator.free(source_code); source_code[source_code.len - 3] = '\n'; source_code[source_code.len - 2] = '\n'; source_code[source_code.len - 1] = '\n'; diff --git a/src-self-hosted/parser.zig b/src-self-hosted/parser.zig index 5e1975339a..791bec3fa7 100644 --- a/src-self-hosted/parser.zig +++ b/src-self-hosted/parser.zig @@ -127,7 +127,7 @@ pub const Parser = struct { const root_node = x: { const root_node = try self.createRoot(); - %defer self.allocator.destroy(root_node); + errdefer self.allocator.destroy(root_node); // This stack append has to succeed for freeAst to work try stack.append(State.TopLevel); break :x root_node; @@ -577,7 +577,7 @@ pub const Parser = struct { fn createRoot(self: &Parser) -> %&ast.NodeRoot { const node = try self.allocator.create(ast.NodeRoot); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodeRoot { .base = ast.Node {.id = ast.Node.Id.Root}, @@ -590,7 +590,7 @@ pub const Parser = struct { extern_token: &const ?Token) -> %&ast.NodeVarDecl { const node = try self.allocator.create(ast.NodeVarDecl); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodeVarDecl { .base = ast.Node {.id = ast.Node.Id.VarDecl}, @@ -613,7 +613,7 @@ pub const Parser = struct { cc_token: &const ?Token, visib_token: &const ?Token, inline_token: &const ?Token) -> %&ast.NodeFnProto { const node = try self.allocator.create(ast.NodeFnProto); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodeFnProto { .base = ast.Node {.id = ast.Node.Id.FnProto}, @@ -635,7 +635,7 @@ pub const Parser = struct { fn createParamDecl(self: &Parser) -> %&ast.NodeParamDecl { const node = try self.allocator.create(ast.NodeParamDecl); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodeParamDecl { .base = ast.Node {.id = ast.Node.Id.ParamDecl}, @@ -650,7 +650,7 @@ pub const Parser = struct { fn createBlock(self: &Parser, begin_token: &const Token) -> %&ast.NodeBlock { const node = try self.allocator.create(ast.NodeBlock); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodeBlock { .base = ast.Node {.id = ast.Node.Id.Block}, @@ -663,7 +663,7 @@ pub const Parser = struct { fn createInfixOp(self: &Parser, op_token: &const Token, op: &const ast.NodeInfixOp.InfixOp) -> %&ast.NodeInfixOp { const node = try self.allocator.create(ast.NodeInfixOp); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodeInfixOp { .base = ast.Node {.id = ast.Node.Id.InfixOp}, @@ -677,7 +677,7 @@ pub const Parser = struct { fn createPrefixOp(self: &Parser, op_token: &const Token, op: &const ast.NodePrefixOp.PrefixOp) -> %&ast.NodePrefixOp { const node = try self.allocator.create(ast.NodePrefixOp); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodePrefixOp { .base = ast.Node {.id = ast.Node.Id.PrefixOp}, @@ -690,7 +690,7 @@ pub const Parser = struct { fn createIdentifier(self: &Parser, name_token: &const Token) -> %&ast.NodeIdentifier { const node = try self.allocator.create(ast.NodeIdentifier); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodeIdentifier { .base = ast.Node {.id = ast.Node.Id.Identifier}, @@ -701,7 +701,7 @@ pub const Parser = struct { fn createIntegerLiteral(self: &Parser, token: &const Token) -> %&ast.NodeIntegerLiteral { const node = try self.allocator.create(ast.NodeIntegerLiteral); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodeIntegerLiteral { .base = ast.Node {.id = ast.Node.Id.IntegerLiteral}, @@ -712,7 +712,7 @@ pub const Parser = struct { fn createFloatLiteral(self: &Parser, token: &const Token) -> %&ast.NodeFloatLiteral { const node = try self.allocator.create(ast.NodeFloatLiteral); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); *node = ast.NodeFloatLiteral { .base = ast.Node {.id = ast.Node.Id.FloatLiteral}, @@ -723,14 +723,14 @@ pub const Parser = struct { fn createAttachIdentifier(self: &Parser, dest_ptr: &const DestPtr, name_token: &const Token) -> %&ast.NodeIdentifier { const node = try self.createIdentifier(name_token); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); try dest_ptr.store(&node.base); return node; } fn createAttachParamDecl(self: &Parser, list: &ArrayList(&ast.Node)) -> %&ast.NodeParamDecl { const node = try self.createParamDecl(); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); try list.append(&node.base); return node; } @@ -740,7 +740,7 @@ pub const Parser = struct { inline_token: &const ?Token) -> %&ast.NodeFnProto { const node = try self.createFnProto(fn_token, extern_token, cc_token, visib_token, inline_token); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); try list.append(&node.base); return node; } @@ -749,7 +749,7 @@ pub const Parser = struct { mut_token: &const Token, comptime_token: &const ?Token, extern_token: &const ?Token) -> %&ast.NodeVarDecl { const node = try self.createVarDecl(visib_token, mut_token, comptime_token, extern_token); - %defer self.allocator.destroy(node); + errdefer self.allocator.destroy(node); try list.append(&node.base); return node; } diff --git a/src/parser.cpp b/src/parser.cpp index de62c8c612..3439ec0c54 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1495,7 +1495,7 @@ static AstNode *ast_parse_break_expr(ParseContext *pc, size_t *token_index) { } /* -Defer(body) = option("%") "defer" body +Defer(body) = ("defer" | "errdefer") body */ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { Token *token = &pc->tokens->at(*token_index); @@ -1503,15 +1503,10 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { NodeType node_type; ReturnKind kind; - if (token->id == TokenIdPercent) { - Token *next_token = &pc->tokens->at(*token_index + 1); - if (next_token->id == TokenIdKeywordDefer) { - kind = ReturnKindError; - node_type = NodeTypeDefer; - *token_index += 2; - } else { - return nullptr; - } + if (token->id == TokenIdKeywordErrdefer) { + kind = ReturnKindError; + node_type = NodeTypeDefer; + *token_index += 1; } else if (token->id == TokenIdKeywordDefer) { kind = ReturnKindUnconditional; node_type = NodeTypeDefer; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 57eac899da..f98c0c8344 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -118,6 +118,7 @@ static const struct ZigKeyword zig_keywords[] = { {"defer", TokenIdKeywordDefer}, {"else", TokenIdKeywordElse}, {"enum", TokenIdKeywordEnum}, + {"errdefer", TokenIdKeywordErrdefer}, {"error", TokenIdKeywordError}, {"export", TokenIdKeywordExport}, {"extern", TokenIdKeywordExtern}, @@ -1514,6 +1515,7 @@ const char * token_name(TokenId id) { case TokenIdKeywordDefer: return "defer"; case TokenIdKeywordElse: return "else"; case TokenIdKeywordEnum: return "enum"; + case TokenIdKeywordErrdefer: return "errdefer"; case TokenIdKeywordError: return "error"; case TokenIdKeywordExport: return "export"; case TokenIdKeywordExtern: return "extern"; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index 6c9704224a..749f72f419 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -57,6 +57,7 @@ enum TokenId { TokenIdKeywordDefer, TokenIdKeywordElse, TokenIdKeywordEnum, + TokenIdKeywordErrdefer, TokenIdKeywordError, TokenIdKeywordExport, TokenIdKeywordExtern, diff --git a/std/buf_map.zig b/std/buf_map.zig index 3ff0624f63..5063884b2c 100644 --- a/std/buf_map.zig +++ b/std/buf_map.zig @@ -30,14 +30,14 @@ pub const BufMap = struct { pub fn set(self: &BufMap, key: []const u8, value: []const u8) -> %void { if (self.hash_map.get(key)) |entry| { const value_copy = try self.copy(value); - %defer self.free(value_copy); + errdefer self.free(value_copy); _ = try self.hash_map.put(key, value_copy); self.free(entry.value); } else { const key_copy = try self.copy(key); - %defer self.free(key_copy); + errdefer self.free(key_copy); const value_copy = try self.copy(value); - %defer self.free(value_copy); + errdefer self.free(value_copy); _ = try self.hash_map.put(key_copy, value_copy); } } diff --git a/std/buf_set.zig b/std/buf_set.zig index 5ce54551db..b5b252911f 100644 --- a/std/buf_set.zig +++ b/std/buf_set.zig @@ -27,7 +27,7 @@ pub const BufSet = struct { pub fn put(self: &BufSet, key: []const u8) -> %void { if (self.hash_map.get(key) == null) { const key_copy = try self.copy(key); - %defer self.free(key_copy); + errdefer self.free(key_copy); _ = try self.hash_map.put(key_copy, {}); } } diff --git a/std/cstr.zig b/std/cstr.zig index 0f63592950..31fb4ccca7 100644 --- a/std/cstr.zig +++ b/std/cstr.zig @@ -71,7 +71,7 @@ pub const NullTerminated2DArray = struct { byte_count += index_size; const buf = try allocator.alignedAlloc(u8, @alignOf(?&u8), byte_count); - %defer allocator.free(buf); + errdefer allocator.free(buf); var write_index = index_size; const index_buf = ([]?&u8)(buf); diff --git a/std/debug/index.zig b/std/debug/index.zig index 87e81ab8c2..df5cc0a322 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -248,10 +248,10 @@ pub fn openSelfDebugInfo(allocator: &mem.Allocator) -> %&ElfStackTrace { .compile_unit_list = ArrayList(CompileUnit).init(allocator), }; st.self_exe_file = try os.openSelfExe(); - %defer st.self_exe_file.close(); + errdefer st.self_exe_file.close(); try st.elf.openFile(allocator, &st.self_exe_file); - %defer st.elf.close(); + errdefer st.elf.close(); st.debug_info = (try st.elf.findSection(".debug_info")) ?? return error.MissingDebugInfo; st.debug_abbrev = (try st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; @@ -524,7 +524,7 @@ const LineNumberProgram = struct { return error.InvalidDebugInfo; } else self.include_dirs[file_entry.dir_index]; const file_name = try os.path.join(self.file_entries.allocator, dir_name, file_entry.file_name); - %defer self.file_entries.allocator.free(file_name); + errdefer self.file_entries.allocator.free(file_name); return LineInfo { .line = if (self.prev_line >= 0) usize(self.prev_line) else 0, .column = self.prev_column, @@ -563,7 +563,7 @@ fn getString(st: &ElfStackTrace, offset: u64) -> %[]u8 { fn readAllocBytes(allocator: &mem.Allocator, in_stream: &io.InStream, size: usize) -> %[]u8 { const buf = try global_allocator.alloc(u8, size); - %defer global_allocator.free(buf); + errdefer global_allocator.free(buf); if ((try in_stream.read(buf)) < size) return error.EndOfFile; return buf; } diff --git a/std/elf.zig b/std/elf.zig index c91509ff7d..377bd76f11 100644 --- a/std/elf.zig +++ b/std/elf.zig @@ -183,7 +183,7 @@ pub const Elf = struct { try elf.in_file.seekTo(elf.section_header_offset); elf.section_headers = try elf.allocator.alloc(SectionHeader, sh_entry_count); - %defer elf.allocator.free(elf.section_headers); + errdefer elf.allocator.free(elf.section_headers); if (elf.is_64) { if (sh_entry_size != 64) return error.InvalidFormat; diff --git a/std/io.zig b/std/io.zig index cfde7c6013..fd8bb80984 100644 --- a/std/io.zig +++ b/std/io.zig @@ -550,7 +550,7 @@ pub fn readFileAllocExtra(path: []const u8, allocator: &mem.Allocator, extra_len const size = try file.getEndPos(); const buf = try allocator.alloc(u8, size + extra_len); - %defer allocator.free(buf); + errdefer allocator.free(buf); var adapter = FileInStream.init(&file); try adapter.stream.readNoEof(buf[0..size]); diff --git a/std/mem.zig b/std/mem.zig index 5f6cc0c3e0..cee49fead7 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -440,7 +440,7 @@ pub fn join(allocator: &Allocator, sep: u8, strings: ...) -> %[]u8 { } const buf = try allocator.alloc(u8, total_strings_len); - %defer allocator.free(buf); + errdefer allocator.free(buf); var buf_index: usize = 0; comptime var string_i = 0; diff --git a/std/os/child_process.zig b/std/os/child_process.zig index 8bf60bc52b..aaa7ac3970 100644 --- a/std/os/child_process.zig +++ b/std/os/child_process.zig @@ -76,7 +76,7 @@ pub const ChildProcess = struct { /// On success must call deinit. pub fn init(argv: []const []const u8, allocator: &mem.Allocator) -> %&ChildProcess { const child = try allocator.create(ChildProcess); - %defer allocator.destroy(child); + errdefer allocator.destroy(child); *child = ChildProcess { .allocator = allocator, @@ -336,13 +336,13 @@ pub const ChildProcess = struct { install_SIGCHLD_handler(); const stdin_pipe = if (self.stdin_behavior == StdIo.Pipe) try makePipe() else undefined; - %defer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); }; + errdefer if (self.stdin_behavior == StdIo.Pipe) { destroyPipe(stdin_pipe); }; const stdout_pipe = if (self.stdout_behavior == StdIo.Pipe) try makePipe() else undefined; - %defer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); }; + errdefer if (self.stdout_behavior == StdIo.Pipe) { destroyPipe(stdout_pipe); }; const stderr_pipe = if (self.stderr_behavior == StdIo.Pipe) try makePipe() else undefined; - %defer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); }; + errdefer if (self.stderr_behavior == StdIo.Pipe) { destroyPipe(stderr_pipe); }; const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore); const dev_null_fd = if (any_ignore) @@ -367,7 +367,7 @@ pub const ChildProcess = struct { // This pipe is used to communicate errors between the time of fork // and execve from the child process to the parent process. const err_pipe = try makePipe(); - %defer destroyPipe(err_pipe); + errdefer destroyPipe(err_pipe); block_SIGCHLD(); const pid_result = posix.fork(); @@ -479,7 +479,7 @@ pub const ChildProcess = struct { g_hChildStd_IN_Rd = null; }, } - %defer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); }; + errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_IN_Rd, g_hChildStd_IN_Wr); }; var g_hChildStd_OUT_Rd: ?windows.HANDLE = null; var g_hChildStd_OUT_Wr: ?windows.HANDLE = null; @@ -497,7 +497,7 @@ pub const ChildProcess = struct { g_hChildStd_OUT_Wr = null; }, } - %defer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); }; + errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_OUT_Rd, g_hChildStd_OUT_Wr); }; var g_hChildStd_ERR_Rd: ?windows.HANDLE = null; var g_hChildStd_ERR_Wr: ?windows.HANDLE = null; @@ -515,7 +515,7 @@ pub const ChildProcess = struct { g_hChildStd_ERR_Wr = null; }, } - %defer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); }; + errdefer if (self.stdin_behavior == StdIo.Pipe) { windowsDestroyPipe(g_hChildStd_ERR_Rd, g_hChildStd_ERR_Wr); }; const cmd_line = try windowsCreateCommandLine(self.allocator, self.argv); defer self.allocator.free(cmd_line); @@ -722,7 +722,7 @@ fn windowsMakePipeIn(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const S var rd_h: windows.HANDLE = undefined; var wr_h: windows.HANDLE = undefined; try windowsMakePipe(&rd_h, &wr_h, sattr); - %defer windowsDestroyPipe(rd_h, wr_h); + errdefer windowsDestroyPipe(rd_h, wr_h); try windowsSetHandleInfo(wr_h, windows.HANDLE_FLAG_INHERIT, 0); *rd = rd_h; *wr = wr_h; @@ -732,7 +732,7 @@ fn windowsMakePipeOut(rd: &?windows.HANDLE, wr: &?windows.HANDLE, sattr: &const var rd_h: windows.HANDLE = undefined; var wr_h: windows.HANDLE = undefined; try windowsMakePipe(&rd_h, &wr_h, sattr); - %defer windowsDestroyPipe(rd_h, wr_h); + errdefer windowsDestroyPipe(rd_h, wr_h); try windowsSetHandleInfo(rd_h, windows.HANDLE_FLAG_INHERIT, 0); *rd = rd_h; *wr = wr_h; diff --git a/std/os/index.zig b/std/os/index.zig index dbf9ddcb45..34ab49ca56 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -311,7 +311,7 @@ pub fn createNullDelimitedEnvMap(allocator: &Allocator, env_map: &const BufMap) const envp_count = env_map.count(); const envp_buf = try allocator.alloc(?&u8, envp_count + 1); mem.set(?&u8, envp_buf, null); - %defer freeNullDelimitedEnvMap(allocator, envp_buf); + errdefer freeNullDelimitedEnvMap(allocator, envp_buf); { var it = env_map.iterator(); var i: usize = 0; @@ -421,7 +421,7 @@ pub var posix_environ_raw: []&u8 = undefined; /// Caller must free result when done. pub fn getEnvMap(allocator: &Allocator) -> %BufMap { var result = BufMap.init(allocator); - %defer result.deinit(); + errdefer result.deinit(); if (is_windows) { const ptr = windows.GetEnvironmentStringsA() ?? return error.OutOfMemory; @@ -489,7 +489,7 @@ pub fn getEnvVarOwned(allocator: &mem.Allocator, key: []const u8) -> %[]u8 { defer allocator.free(key_with_null); var buf = try allocator.alloc(u8, 256); - %defer allocator.free(buf); + errdefer allocator.free(buf); while (true) { const windows_buf_len = try math.cast(windows.DWORD, buf.len); @@ -521,7 +521,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { switch (builtin.os) { Os.windows => { var buf = try allocator.alloc(u8, 256); - %defer allocator.free(buf); + errdefer allocator.free(buf); while (true) { const result = windows.GetCurrentDirectoryA(windows.WORD(buf.len), buf.ptr); @@ -543,7 +543,7 @@ pub fn getCwd(allocator: &Allocator) -> %[]u8 { }, else => { var buf = try allocator.alloc(u8, 1024); - %defer allocator.free(buf); + errdefer allocator.free(buf); while (true) { const err = posix.getErrno(posix.getcwd(buf.ptr, buf.len)); if (err == posix.ERANGE) { @@ -724,7 +724,7 @@ pub fn copyFileMode(allocator: &Allocator, source_path: []const u8, dest_path: [ var out_file = try io.File.openWriteMode(tmp_path, mode, allocator); defer out_file.close(); - %defer _ = deleteFile(allocator, tmp_path); + errdefer _ = deleteFile(allocator, tmp_path); var in_file = try io.File.openRead(source_path, allocator); defer in_file.close(); @@ -1074,7 +1074,7 @@ pub fn readLink(allocator: &Allocator, pathname: []const u8) -> %[]u8 { path_buf[pathname.len] = 0; var result_buf = try allocator.alloc(u8, 1024); - %defer allocator.free(result_buf); + errdefer allocator.free(result_buf); while (true) { const ret_val = posix.readlink(path_buf.ptr, result_buf.ptr, result_buf.len); const err = posix.getErrno(ret_val); @@ -1443,7 +1443,7 @@ pub fn argsAlloc(allocator: &mem.Allocator) -> %[]const []u8 { const slice_list_bytes = try math.mul(usize, @sizeOf([]u8), slice_sizes.len); const total_bytes = try math.add(usize, slice_list_bytes, contents_slice.len); const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes); - %defer allocator.free(buf); + errdefer allocator.free(buf); const result_slice_list = ([][]u8)(buf[0..slice_list_bytes]); const result_contents = buf[slice_list_bytes..]; @@ -1556,7 +1556,7 @@ pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 { }, Os.windows => { var out_path = try Buffer.initSize(allocator, 0xff); - %defer out_path.deinit(); + errdefer out_path.deinit(); while (true) { const dword_len = try math.cast(windows.DWORD, out_path.len()); const copied_amt = windows.GetModuleFileNameA(null, out_path.ptr(), dword_len); @@ -1579,7 +1579,7 @@ pub fn selfExePath(allocator: &mem.Allocator) -> %[]u8 { const ret1 = c._NSGetExecutablePath(undefined, &u32_len); assert(ret1 != 0); const bytes = try allocator.alloc(u8, u32_len); - %defer allocator.free(bytes); + errdefer allocator.free(bytes); const ret2 = c._NSGetExecutablePath(bytes.ptr, &u32_len); assert(ret2 == 0); return bytes; @@ -1598,13 +1598,13 @@ pub fn selfExeDirPath(allocator: &mem.Allocator) -> %[]u8 { // This path cannot be opened, but it's valid for determining the directory // the executable was in when it was run. const full_exe_path = try readLink(allocator, "/proc/self/exe"); - %defer allocator.free(full_exe_path); + errdefer allocator.free(full_exe_path); const dir = path.dirname(full_exe_path); return allocator.shrink(u8, full_exe_path, dir.len); }, Os.windows, Os.macosx, Os.ios => { const self_exe_path = try selfExePath(allocator); - %defer allocator.free(self_exe_path); + errdefer allocator.free(self_exe_path); const dirname = os.path.dirname(self_exe_path); return allocator.shrink(u8, self_exe_path, dirname.len); }, diff --git a/std/os/path.zig b/std/os/path.zig index 7597282669..c71fa68716 100644 --- a/std/os/path.zig +++ b/std/os/path.zig @@ -468,7 +468,7 @@ pub fn resolveWindows(allocator: &Allocator, paths: []const []const u8) -> %[]u8 } have_drive_kind = parsed_cwd.kind; } - %defer allocator.free(result); + errdefer allocator.free(result); // Now we know the disk designator to use, if any, and what kind it is. And our result // is big enough to append all the paths to. @@ -551,7 +551,7 @@ pub fn resolvePosix(allocator: &Allocator, paths: []const []const u8) -> %[]u8 { mem.copy(u8, result, cwd); result_index += cwd.len; } - %defer allocator.free(result); + errdefer allocator.free(result); for (paths[first_index..]) |p, i| { var it = mem.split(p, "/"); @@ -943,7 +943,7 @@ pub fn relativeWindows(allocator: &Allocator, from: []const u8, to: []const u8) } const up_index_end = up_count * "..\\".len; const result = try allocator.alloc(u8, up_index_end + to_rest.len); - %defer allocator.free(result); + errdefer allocator.free(result); var result_index: usize = 0; while (result_index < up_index_end) { @@ -993,7 +993,7 @@ pub fn relativePosix(allocator: &Allocator, from: []const u8, to: []const u8) -> } const up_index_end = up_count * "../".len; const result = try allocator.alloc(u8, up_index_end + to_rest.len); - %defer allocator.free(result); + errdefer allocator.free(result); var result_index: usize = 0; while (result_index < up_index_end) { @@ -1100,7 +1100,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { } defer os.close(h_file); var buf = try allocator.alloc(u8, 256); - %defer allocator.free(buf); + errdefer allocator.free(buf); while (true) { const buf_len = math.cast(windows.DWORD, buf.len) catch return error.NameTooLong; const result = windows.GetFinalPathNameByHandleA(h_file, buf.ptr, buf_len, windows.VOLUME_NAME_DOS); @@ -1144,7 +1144,7 @@ pub fn real(allocator: &Allocator, pathname: []const u8) -> %[]u8 { defer allocator.free(pathname_buf); const result_buf = try allocator.alloc(u8, posix.PATH_MAX); - %defer allocator.free(result_buf); + errdefer allocator.free(result_buf); mem.copy(u8, pathname_buf, pathname); pathname_buf[pathname.len] = 0; diff --git a/std/os/windows/util.zig b/std/os/windows/util.zig index c92575c31d..f1c6f049ee 100644 --- a/std/os/windows/util.zig +++ b/std/os/windows/util.zig @@ -133,7 +133,7 @@ pub fn createWindowsEnvBlock(allocator: &mem.Allocator, env_map: &const BufMap) break :x bytes_needed; }; const result = try allocator.alloc(u8, bytes_needed); - %defer allocator.free(result); + errdefer allocator.free(result); var it = env_map.iterator(); var i: usize = 0; diff --git a/test/cases/defer.zig b/test/cases/defer.zig index b84e784713..4fefce0389 100644 --- a/test/cases/defer.zig +++ b/test/cases/defer.zig @@ -8,7 +8,7 @@ error FalseNotAllowed; fn runSomeErrorDefers(x: bool) -> %bool { index = 0; defer {result[index] = 'a'; index += 1;} - %defer {result[index] = 'b'; index += 1;} + errdefer {result[index] = 'b'; index += 1;} defer {result[index] = 'c'; index += 1;} return if (x) x else error.FalseNotAllowed; } diff --git a/test/compare_output.zig b/test/compare_output.zig index e4600d70e5..1af94f9f4a 100644 --- a/test/compare_output.zig +++ b/test/compare_output.zig @@ -392,7 +392,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { \\} , "before\ndefer2\ndefer1\n"); - cases.add("%defer and it fails", + cases.add("errdefer and it fails", \\const io = @import("std").io; \\pub fn main() -> %void { \\ do_test() catch return; @@ -401,7 +401,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); \\ stdout.print("before\n") catch unreachable; \\ defer stdout.print("defer1\n") catch unreachable; - \\ %defer stdout.print("deferErr\n") catch unreachable; + \\ errdefer stdout.print("deferErr\n") catch unreachable; \\ try its_gonna_fail(); \\ defer stdout.print("defer3\n") catch unreachable; \\ stdout.print("after\n") catch unreachable; @@ -412,7 +412,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { \\} , "before\ndeferErr\ndefer1\n"); - cases.add("%defer and it passes", + cases.add("errdefer and it passes", \\const io = @import("std").io; \\pub fn main() -> %void { \\ do_test() catch return; @@ -421,7 +421,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { \\ const stdout = &(io.FileOutStream.init(&(io.getStdOut() catch unreachable)).stream); \\ stdout.print("before\n") catch unreachable; \\ defer stdout.print("defer1\n") catch unreachable; - \\ %defer stdout.print("deferErr\n") catch unreachable; + \\ errdefer stdout.print("deferErr\n") catch unreachable; \\ try its_gonna_pass(); \\ defer stdout.print("defer3\n") catch unreachable; \\ stdout.print("after\n") catch unreachable;