diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 5dc41cc9d2..56254411ce 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -9695,6 +9695,19 @@ fn builtinCall( .volatile_cast, => return ptrCast(gz, scope, ri, node), + .deprecated => { + _ = try gz.addExtendedNodeSmall(.deprecated, node, 0); + switch (params.len) { + 0 => return .void_value, + 1 => return expr(gz, scope, ri, params[0]), + else => return astgen.failNode( + node, + "expected 0 or 1 argument, found {}", + .{params.len}, + ), + } + }, + // zig fmt: off .has_decl => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_decl), .has_field => return hasDeclOrField(gz, scope, ri, node, params[0], params[1], .has_field), diff --git a/lib/std/zig/AstRlAnnotate.zig b/lib/std/zig/AstRlAnnotate.zig index ccc23b18aa..f58ba213cd 100644 --- a/lib/std/zig/AstRlAnnotate.zig +++ b/lib/std/zig/AstRlAnnotate.zig @@ -817,8 +817,6 @@ fn blockExpr(astrl: *AstRlAnnotate, parent_block: ?*Block, ri: ResultInfo, node: } fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast.Node.Index, args: []const Ast.Node.Index) !bool { - _ = ri; // Currently, no builtin consumes its result location. - const tree = astrl.tree; const main_tokens = tree.nodes.items(.main_token); const builtin_token = main_tokens[node]; @@ -828,6 +826,11 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. if (expected != args.len) return false; } switch (info.tag) { + .deprecated => if (args.len >= 1) { + return astrl.expr(args[0], block, ri); + } else { + return false; + }, .import => return false, .branch_hint => { _ = try astrl.expr(args[0], block, ResultInfo.type_only); diff --git a/lib/std/zig/BuiltinFn.zig b/lib/std/zig/BuiltinFn.zig index 1bf31cd165..c0e0b522a3 100644 --- a/lib/std/zig/BuiltinFn.zig +++ b/lib/std/zig/BuiltinFn.zig @@ -121,6 +121,7 @@ pub const Tag = enum { work_item_id, work_group_size, work_group_id, + deprecated, }; pub const EvalToError = enum { @@ -1016,6 +1017,14 @@ pub const list = list: { .illegal_outside_function = true, }, }, + .{ + "@deprecated", + .{ + .tag = .deprecated, + .param_count = null, + .eval_to_error = .maybe, + }, + }, }); }; diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index 5d013635cb..ea69bc2da0 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -2112,6 +2112,9 @@ pub const Inst = struct { /// any code may have gone here, avoiding false-positive "unreachable code" errors. astgen_error, + /// `operand` is `src_node: i32`. + deprecated, + pub const InstData = struct { opcode: Extended, small: u16, @@ -4310,6 +4313,7 @@ fn findTrackableInner( .value_placeholder => unreachable, // Once again, we start with the boring tags. + .deprecated, .this, .ret_addr, .builtin_src, diff --git a/src/Compilation.zig b/src/Compilation.zig index 969a399640..7331bf2097 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -869,6 +869,7 @@ pub const cache_helpers = struct { hh.add(mod.sanitize_c); hh.add(mod.sanitize_thread); hh.add(mod.fuzz); + hh.add(mod.allow_deprecated); hh.add(mod.unwind_tables); hh.add(mod.structured_cfg); hh.add(mod.no_builtin); diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 0dec7bde76..6bd33dffa1 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -27,6 +27,7 @@ red_zone: bool, sanitize_c: bool, sanitize_thread: bool, fuzz: bool, +allow_deprecated: bool, unwind_tables: std.builtin.UnwindTables, cc_argv: []const []const u8, /// (SPIR-V) whether to generate a structured control flow graph or not @@ -95,6 +96,7 @@ pub const CreateOptions = struct { sanitize_c: ?bool = null, sanitize_thread: ?bool = null, fuzz: ?bool = null, + allow_deprecated: ?bool = null, structured_cfg: ?bool = null, no_builtin: ?bool = null, }; @@ -234,6 +236,12 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { break :b false; }; + const allow_deprecated = b: { + if (options.inherited.allow_deprecated) |x| break :b x; + if (options.parent) |p| break :b p.allow_deprecated; + break :b false; + }; + const code_model = b: { if (options.inherited.code_model) |x| break :b x; if (options.parent) |p| break :b p.code_model; @@ -380,6 +388,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { .sanitize_c = sanitize_c, .sanitize_thread = sanitize_thread, .fuzz = fuzz, + .allow_deprecated = allow_deprecated, .unwind_tables = unwind_tables, .cc_argv = options.cc_argv, .structured_cfg = structured_cfg, @@ -474,6 +483,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { .sanitize_c = sanitize_c, .sanitize_thread = sanitize_thread, .fuzz = fuzz, + .allow_deprecated = allow_deprecated, .unwind_tables = unwind_tables, .cc_argv = &.{}, .structured_cfg = structured_cfg, @@ -532,6 +542,7 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P .sanitize_c = undefined, .sanitize_thread = undefined, .fuzz = undefined, + .allow_deprecated = undefined, .unwind_tables = undefined, .cc_argv = undefined, .structured_cfg = undefined, diff --git a/src/Sema.zig b/src/Sema.zig index 9e729a17ea..e68177433d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1091,6 +1091,7 @@ fn analyzeBodyInner( const map = &sema.inst_map; const tags = sema.code.instructions.items(.tag); const datas = sema.code.instructions.items(.data); + const mod = block.ownerModule(); var crash_info = crash_report.prepAnalyzeBody(sema, block, body); crash_info.push(); @@ -1341,6 +1342,15 @@ fn analyzeBodyInner( .extended => ext: { const extended = datas[@intFromEnum(inst)].extended; break :ext switch (extended.opcode) { + .deprecated => { + if (!mod.allow_deprecated) { + const src_node: i32 = @bitCast(extended.operand); + const src = block.nodeOffset(src_node); + return sema.fail(block, src, "found deprecated code", .{}); + } + + break :ext .void_value; + }, // zig fmt: off .struct_decl => try sema.zirStructDecl( block, extended, inst), .enum_decl => try sema.zirEnumDecl( block, extended, inst), diff --git a/src/main.zig b/src/main.zig index 5e66244484..ed862b03a0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -520,6 +520,8 @@ const usage_build_generic = \\ -fno-sanitize-thread Disable Thread Sanitizer \\ -ffuzz Enable fuzz testing instrumentation \\ -fno-fuzz Disable fuzz testing instrumentation + \\ -fallow-deprecated Allow usage of deprecated code + \\ -fno-allow-deprecated Disallow usage of deprecated code \\ -funwind-tables Always produce unwind table entries for all functions \\ -fasync-unwind-tables Always produce asynchronous unwind table entries for all functions \\ -fno-unwind-tables Never produce unwind table entries @@ -1454,6 +1456,10 @@ fn buildOutputType( mod_opts.fuzz = true; } else if (mem.eql(u8, arg, "-fno-fuzz")) { mod_opts.fuzz = false; + } else if (mem.eql(u8, arg, "-fallow-deprecated")) { + mod_opts.allow_deprecated = true; + } else if (mem.eql(u8, arg, "-fno-allow-deprecated")) { + mod_opts.allow_deprecated = false; } else if (mem.eql(u8, arg, "-fllvm")) { create_module.opts.use_llvm = true; } else if (mem.eql(u8, arg, "-fno-llvm")) { diff --git a/src/print_zir.zig b/src/print_zir.zig index 46f399dda9..ab3fa1aadc 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -535,6 +535,7 @@ const Writer = struct { .c_va_start, .in_comptime, .value_placeholder, + .deprecated, => try self.writeExtNode(stream, extended), .builtin_src => {