| ... | @@ -528,10 +528,10 @@ pub const Decl = struct { | ... | @@ -528,10 +528,10 @@ pub const Decl = struct { |
| 528 | /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it | 528 | /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it |
| 529 | /// deletes the Decl on the spot. | 529 | /// deletes the Decl on the spot. |
| 530 | alive: bool, | 530 | alive: bool, |
| 531 | /// Whether the Decl is a `usingnamespace` declaration. | | |
| 532 | is_usingnamespace: bool, | | |
| 533 | /// If true `name` is already fully qualified. | 531 | /// If true `name` is already fully qualified. |
| 534 | name_fully_qualified: bool = false, | 532 | name_fully_qualified: bool = false, |
| | 533 | /// What kind of a declaration is this. |
| | 534 | kind: Kind, |
| 535 | | 535 | |
| 536 | /// Represents the position of the code in the output file. | 536 | /// Represents the position of the code in the output file. |
| 537 | /// This is populated regardless of semantic analysis and code generation. | 537 | /// This is populated regardless of semantic analysis and code generation. |
| ... | @@ -551,6 +551,14 @@ pub const Decl = struct { | ... | @@ -551,6 +551,14 @@ pub const Decl = struct { |
| 551 | /// typed_value may need to be regenerated. | 551 | /// typed_value may need to be regenerated. |
| 552 | dependencies: DepsTable = .{}, | 552 | dependencies: DepsTable = .{}, |
| 553 | | 553 | |
| | 554 | pub const Kind = enum { |
| | 555 | @"usingnamespace", |
| | 556 | @"test", |
| | 557 | @"comptime", |
| | 558 | named, |
| | 559 | anon, |
| | 560 | }; |
| | 561 | |
| 554 | pub const Index = enum(u32) { | 562 | pub const Index = enum(u32) { |
| 555 | _, | 563 | _, |
| 556 | | 564 | |
| ... | @@ -4438,7 +4446,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4438,7 +4446,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4438 | // not the struct itself. | 4446 | // not the struct itself. |
| 4439 | try sema.resolveTypeLayout(decl_tv.ty); | 4447 | try sema.resolveTypeLayout(decl_tv.ty); |
| 4440 | | 4448 | |
| 4441 | if (decl.is_usingnamespace) { | 4449 | if (decl.kind == .@"usingnamespace") { |
| 4442 | if (!decl_tv.ty.eql(Type.type, mod)) { | 4450 | if (!decl_tv.ty.eql(Type.type, mod)) { |
| 4443 | return sema.fail(&block_scope, ty_src, "expected type, found {}", .{ | 4451 | return sema.fail(&block_scope, ty_src, "expected type, found {}", .{ |
| 4444 | decl_tv.ty.fmt(mod), | 4452 | decl_tv.ty.fmt(mod), |
| ... | @@ -4964,26 +4972,31 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err | ... | @@ -4964,26 +4972,31 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 4964 | | 4972 | |
| 4965 | // Every Decl needs a name. | 4973 | // Every Decl needs a name. |
| 4966 | var is_named_test = false; | 4974 | var is_named_test = false; |
| | 4975 | var kind: Decl.Kind = .named; |
| 4967 | const decl_name: [:0]const u8 = switch (decl_name_index) { | 4976 | const decl_name: [:0]const u8 = switch (decl_name_index) { |
| 4968 | 0 => name: { | 4977 | 0 => name: { |
| 4969 | if (export_bit) { | 4978 | if (export_bit) { |
| 4970 | const i = iter.usingnamespace_index; | 4979 | const i = iter.usingnamespace_index; |
| 4971 | iter.usingnamespace_index += 1; | 4980 | iter.usingnamespace_index += 1; |
| | 4981 | kind = .@"usingnamespace"; |
| 4972 | break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i}); | 4982 | break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i}); |
| 4973 | } else { | 4983 | } else { |
| 4974 | const i = iter.comptime_index; | 4984 | const i = iter.comptime_index; |
| 4975 | iter.comptime_index += 1; | 4985 | iter.comptime_index += 1; |
| | 4986 | kind = .@"comptime"; |
| 4976 | break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i}); | 4987 | break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i}); |
| 4977 | } | 4988 | } |
| 4978 | }, | 4989 | }, |
| 4979 | 1 => name: { | 4990 | 1 => name: { |
| 4980 | const i = iter.unnamed_test_index; | 4991 | const i = iter.unnamed_test_index; |
| 4981 | iter.unnamed_test_index += 1; | 4992 | iter.unnamed_test_index += 1; |
| | 4993 | kind = .@"test"; |
| 4982 | break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i}); | 4994 | break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i}); |
| 4983 | }, | 4995 | }, |
| 4984 | 2 => name: { | 4996 | 2 => name: { |
| 4985 | is_named_test = true; | 4997 | is_named_test = true; |
| 4986 | const test_name = zir.nullTerminatedString(decl_doccomment_index); | 4998 | const test_name = zir.nullTerminatedString(decl_doccomment_index); |
| | 4999 | kind = .@"test"; |
| 4987 | break :name try std.fmt.allocPrintZ(gpa, "decltest.{s}", .{test_name}); | 5000 | break :name try std.fmt.allocPrintZ(gpa, "decltest.{s}", .{test_name}); |
| 4988 | }, | 5001 | }, |
| 4989 | else => name: { | 5002 | else => name: { |
| ... | @@ -4991,6 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err | ... | @@ -4991,6 +5004,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 4991 | if (raw_name.len == 0) { | 5004 | if (raw_name.len == 0) { |
| 4992 | is_named_test = true; | 5005 | is_named_test = true; |
| 4993 | const test_name = zir.nullTerminatedString(decl_name_index + 1); | 5006 | const test_name = zir.nullTerminatedString(decl_name_index + 1); |
| | 5007 | kind = .@"test"; |
| 4994 | break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name}); | 5008 | break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name}); |
| 4995 | } else { | 5009 | } else { |
| 4996 | break :name try gpa.dupeZ(u8, raw_name); | 5010 | break :name try gpa.dupeZ(u8, raw_name); |
| ... | @@ -4998,8 +5012,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err | ... | @@ -4998,8 +5012,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 4998 | }, | 5012 | }, |
| 4999 | }; | 5013 | }; |
| 5000 | const is_exported = export_bit and decl_name_index != 0; | 5014 | const is_exported = export_bit and decl_name_index != 0; |
| 5001 | const is_usingnamespace = export_bit and decl_name_index == 0; | 5015 | if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1); |
| 5002 | if (is_usingnamespace) try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1); | | |
| 5003 | | 5016 | |
| 5004 | // We create a Decl for it regardless of analysis status. | 5017 | // We create a Decl for it regardless of analysis status. |
| 5005 | const gop = try namespace.decls.getOrPutContextAdapted( | 5018 | const gop = try namespace.decls.getOrPutContextAdapted( |
| ... | @@ -5012,8 +5025,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err | ... | @@ -5012,8 +5025,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 5012 | if (!gop.found_existing) { | 5025 | if (!gop.found_existing) { |
| 5013 | const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope); | 5026 | const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope); |
| 5014 | const new_decl = mod.declPtr(new_decl_index); | 5027 | const new_decl = mod.declPtr(new_decl_index); |
| | 5028 | new_decl.kind = kind; |
| 5015 | new_decl.name = decl_name; | 5029 | new_decl.name = decl_name; |
| 5016 | if (is_usingnamespace) { | 5030 | if (kind == .@"usingnamespace") { |
| 5017 | namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub); | 5031 | namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub); |
| 5018 | } | 5032 | } |
| 5019 | log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace }); | 5033 | log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace }); |
| ... | @@ -5058,7 +5072,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err | ... | @@ -5058,7 +5072,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 5058 | } | 5072 | } |
| 5059 | new_decl.is_pub = is_pub; | 5073 | new_decl.is_pub = is_pub; |
| 5060 | new_decl.is_exported = is_exported; | 5074 | new_decl.is_exported = is_exported; |
| 5061 | new_decl.is_usingnamespace = is_usingnamespace; | | |
| 5062 | new_decl.has_align = has_align; | 5075 | new_decl.has_align = has_align; |
| 5063 | new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace; | 5076 | new_decl.has_linksection_or_addrspace = has_linksection_or_addrspace; |
| 5064 | new_decl.zir_decl_index = @intCast(u32, decl_sub_index); | 5077 | new_decl.zir_decl_index = @intCast(u32, decl_sub_index); |
| ... | @@ -5076,7 +5089,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err | ... | @@ -5076,7 +5089,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err |
| 5076 | | 5089 | |
| 5077 | decl.is_pub = is_pub; | 5090 | decl.is_pub = is_pub; |
| 5078 | decl.is_exported = is_exported; | 5091 | decl.is_exported = is_exported; |
| 5079 | decl.is_usingnamespace = is_usingnamespace; | 5092 | decl.kind = kind; |
| 5080 | decl.has_align = has_align; | 5093 | decl.has_align = has_align; |
| 5081 | decl.has_linksection_or_addrspace = has_linksection_or_addrspace; | 5094 | decl.has_linksection_or_addrspace = has_linksection_or_addrspace; |
| 5082 | decl.zir_decl_index = @intCast(u32, decl_sub_index); | 5095 | decl.zir_decl_index = @intCast(u32, decl_sub_index); |
| ... | @@ -5635,7 +5648,7 @@ pub fn allocateNewDecl( | ... | @@ -5635,7 +5648,7 @@ pub fn allocateNewDecl( |
| 5635 | .has_linksection_or_addrspace = false, | 5648 | .has_linksection_or_addrspace = false, |
| 5636 | .has_align = false, | 5649 | .has_align = false, |
| 5637 | .alive = false, | 5650 | .alive = false, |
| 5638 | .is_usingnamespace = false, | 5651 | .kind = .anon, |
| 5639 | }; | 5652 | }; |
| 5640 | | 5653 | |
| 5641 | return decl_and_index.decl_index; | 5654 | return decl_and_index.decl_index; |