@@ -2161,6 +2161,10 @@ pub const SrcLoc = struct {
2161
2161
.local_var_decl = > tree .localVarDecl (node ),
2162
2162
.simple_var_decl = > tree .simpleVarDecl (node ),
2163
2163
.aligned_var_decl = > tree .alignedVarDecl (node ),
2164
+ .@"usingnamespace" = > {
2165
+ const node_data = tree .nodes .items (.data );
2166
+ return nodeToSpan (tree , node_data [node ].lhs );
2167
+ },
2164
2168
else = > unreachable ,
2165
2169
};
2166
2170
if (full .ast .type_node != 0 ) {
@@ -2171,6 +2175,58 @@ pub const SrcLoc = struct {
2171
2175
const end = start + @intCast (u32 , tree .tokenSlice (tok_index ).len );
2172
2176
return Span { .start = start , .end = end , .main = start };
2173
2177
},
2178
+ .node_offset_var_decl_align = > | node_off | {
2179
+ const tree = try src_loc .file_scope .getTree (gpa );
2180
+ const node = src_loc .declRelativeToNodeIndex (node_off );
2181
+ const node_tags = tree .nodes .items (.tag );
2182
+ const full : Ast.full.VarDecl = switch (node_tags [node ]) {
2183
+ .global_var_decl = > tree .globalVarDecl (node ),
2184
+ .local_var_decl = > tree .localVarDecl (node ),
2185
+ .simple_var_decl = > tree .simpleVarDecl (node ),
2186
+ .aligned_var_decl = > tree .alignedVarDecl (node ),
2187
+ else = > unreachable ,
2188
+ };
2189
+ return nodeToSpan (tree , full .ast .align_node );
2190
+ },
2191
+ .node_offset_var_decl_section = > | node_off | {
2192
+ const tree = try src_loc .file_scope .getTree (gpa );
2193
+ const node = src_loc .declRelativeToNodeIndex (node_off );
2194
+ const node_tags = tree .nodes .items (.tag );
2195
+ const full : Ast.full.VarDecl = switch (node_tags [node ]) {
2196
+ .global_var_decl = > tree .globalVarDecl (node ),
2197
+ .local_var_decl = > tree .localVarDecl (node ),
2198
+ .simple_var_decl = > tree .simpleVarDecl (node ),
2199
+ .aligned_var_decl = > tree .alignedVarDecl (node ),
2200
+ else = > unreachable ,
2201
+ };
2202
+ return nodeToSpan (tree , full .ast .section_node );
2203
+ },
2204
+ .node_offset_var_decl_addrspace = > | node_off | {
2205
+ const tree = try src_loc .file_scope .getTree (gpa );
2206
+ const node = src_loc .declRelativeToNodeIndex (node_off );
2207
+ const node_tags = tree .nodes .items (.tag );
2208
+ const full : Ast.full.VarDecl = switch (node_tags [node ]) {
2209
+ .global_var_decl = > tree .globalVarDecl (node ),
2210
+ .local_var_decl = > tree .localVarDecl (node ),
2211
+ .simple_var_decl = > tree .simpleVarDecl (node ),
2212
+ .aligned_var_decl = > tree .alignedVarDecl (node ),
2213
+ else = > unreachable ,
2214
+ };
2215
+ return nodeToSpan (tree , full .ast .addrspace_node );
2216
+ },
2217
+ .node_offset_var_decl_init = > | node_off | {
2218
+ const tree = try src_loc .file_scope .getTree (gpa );
2219
+ const node = src_loc .declRelativeToNodeIndex (node_off );
2220
+ const node_tags = tree .nodes .items (.tag );
2221
+ const full : Ast.full.VarDecl = switch (node_tags [node ]) {
2222
+ .global_var_decl = > tree .globalVarDecl (node ),
2223
+ .local_var_decl = > tree .localVarDecl (node ),
2224
+ .simple_var_decl = > tree .simpleVarDecl (node ),
2225
+ .aligned_var_decl = > tree .alignedVarDecl (node ),
2226
+ else = > unreachable ,
2227
+ };
2228
+ return nodeToSpan (tree , full .ast .init_node );
2229
+ },
2174
2230
.node_offset_builtin_call_arg0 = > | n | return src_loc .byteOffsetBuiltinCallArg (gpa , n , 0 ),
2175
2231
.node_offset_builtin_call_arg1 = > | n | return src_loc .byteOffsetBuiltinCallArg (gpa , n , 1 ),
2176
2232
.node_offset_builtin_call_arg2 = > | n | return src_loc .byteOffsetBuiltinCallArg (gpa , n , 2 ),
@@ -2857,6 +2913,18 @@ pub const LazySrcLoc = union(enum) {
2857
2913
/// to the type expression.
2858
2914
/// The Decl is determined contextually.
2859
2915
node_offset_var_decl_ty : i32 ,
2916
+ /// The source location points to the alignment expression of a var decl.
2917
+ /// The Decl is determined contextually.
2918
+ node_offset_var_decl_align : i32 ,
2919
+ /// The source location points to the linksection expression of a var decl.
2920
+ /// The Decl is determined contextually.
2921
+ node_offset_var_decl_section : i32 ,
2922
+ /// The source location points to the addrspace expression of a var decl.
2923
+ /// The Decl is determined contextually.
2924
+ node_offset_var_decl_addrspace : i32 ,
2925
+ /// The source location points to the initializer of a var decl.
2926
+ /// The Decl is determined contextually.
2927
+ node_offset_var_decl_init : i32 ,
2860
2928
/// The source location points to a for loop condition expression,
2861
2929
/// found by taking this AST node index offset from the containing
2862
2930
/// Decl AST node, which points to a for loop AST node. Next, navigate
@@ -3098,6 +3166,10 @@ pub const LazySrcLoc = union(enum) {
3098
3166
.node_offset ,
3099
3167
.node_offset_initializer ,
3100
3168
.node_offset_var_decl_ty ,
3169
+ .node_offset_var_decl_align ,
3170
+ .node_offset_var_decl_section ,
3171
+ .node_offset_var_decl_addrspace ,
3172
+ .node_offset_var_decl_init ,
3101
3173
.node_offset_for_cond ,
3102
3174
.node_offset_builtin_call_arg0 ,
3103
3175
.node_offset_builtin_call_arg1 ,
@@ -4414,17 +4486,26 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4414
4486
const body = zir .extra [extra .end .. ][0.. extra .data .body_len ];
4415
4487
const result_ref = (try sema .analyzeBodyBreak (& block_scope , body )).? .operand ;
4416
4488
try wip_captures .finalize ();
4417
- const src = LazySrcLoc .nodeOffset (0 );
4418
- const decl_tv = try sema .resolveInstValue (& block_scope , .unneeded , result_ref , undefined );
4489
+ const align_src : LazySrcLoc = .{ .node_offset_var_decl_align = 0 };
4490
+ const section_src : LazySrcLoc = .{ .node_offset_var_decl_section = 0 };
4491
+ const address_space_src : LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
4492
+ const ty_src : LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
4493
+ const init_src : LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
4494
+ const decl_tv = try sema .resolveInstValue (& block_scope , init_src , result_ref , undefined );
4419
4495
const decl_align : u32 = blk : {
4420
4496
const align_ref = decl .zirAlignRef ();
4421
4497
if (align_ref == .none ) break :blk 0 ;
4422
- break :blk try sema .resolveAlign (& block_scope , src , align_ref );
4498
+ break :blk try sema .resolveAlign (& block_scope , align_src , align_ref );
4423
4499
};
4424
4500
const decl_linksection : ? [* :0 ]const u8 = blk : {
4425
4501
const linksection_ref = decl .zirLinksectionRef ();
4426
4502
if (linksection_ref == .none ) break :blk null ;
4427
- const bytes = try sema .resolveConstString (& block_scope , src , linksection_ref , "linksection must be comptime known" );
4503
+ const bytes = try sema .resolveConstString (& block_scope , section_src , linksection_ref , "linksection must be comptime known" );
4504
+ if (mem .indexOfScalar (u8 , bytes , 0 ) != null ) {
4505
+ return sema .fail (& block_scope , section_src , "linksection cannot contain null bytes" , .{});
4506
+ } else if (bytes .len == 0 ) {
4507
+ return sema .fail (& block_scope , section_src , "linksection cannot be empty" , .{});
4508
+ }
4428
4509
break :blk (try decl_arena_allocator .dupeZ (u8 , bytes )).ptr ;
4429
4510
};
4430
4511
const target = sema .mod .getTarget ();
@@ -4442,27 +4523,27 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4442
4523
.constant = > target_util .defaultAddressSpace (target , .global_constant ),
4443
4524
else = > unreachable ,
4444
4525
},
4445
- else = > | addrspace_ref | try sema .analyzeAddrspace (& block_scope , src , addrspace_ref , addrspace_ctx ),
4526
+ else = > | addrspace_ref | try sema .analyzeAddrspace (& block_scope , address_space_src , addrspace_ref , addrspace_ctx ),
4446
4527
};
4447
4528
};
4448
4529
4449
4530
// Note this resolves the type of the Decl, not the value; if this Decl
4450
4531
// is a struct, for example, this resolves `type` (which needs no resolution),
4451
4532
// not the struct itself.
4452
- try sema .resolveTypeLayout (& block_scope , src , decl_tv .ty );
4533
+ try sema .resolveTypeLayout (& block_scope , ty_src , decl_tv .ty );
4453
4534
4454
4535
const decl_arena_state = try decl_arena_allocator .create (std .heap .ArenaAllocator .State );
4455
4536
4456
4537
if (decl .is_usingnamespace ) {
4457
4538
if (! decl_tv .ty .eql (Type .type , mod )) {
4458
- return sema .fail (& block_scope , src , "expected type, found {}" , .{
4539
+ return sema .fail (& block_scope , ty_src , "expected type, found {}" , .{
4459
4540
decl_tv .ty .fmt (mod ),
4460
4541
});
4461
4542
}
4462
4543
var buffer : Value.ToTypeBuffer = undefined ;
4463
4544
const ty = try decl_tv .val .toType (& buffer ).copy (decl_arena_allocator );
4464
4545
if (ty .getNamespace () == null ) {
4465
- return sema .fail (& block_scope , src , "type {} has no namespace" , .{ty .fmt (mod )});
4546
+ return sema .fail (& block_scope , ty_src , "type {} has no namespace" , .{ty .fmt (mod )});
4466
4547
}
4467
4548
4468
4549
decl .ty = Type .type ;
@@ -4508,7 +4589,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4508
4589
decl .analysis = .complete ;
4509
4590
decl .generation = mod .generation ;
4510
4591
4511
- const has_runtime_bits = try sema .fnHasRuntimeBits (& block_scope , src , decl .ty );
4592
+ const has_runtime_bits = try sema .fnHasRuntimeBits (& block_scope , ty_src , decl .ty );
4512
4593
4513
4594
if (has_runtime_bits ) {
4514
4595
// We don't fully codegen the decl until later, but we do need to reserve a global
@@ -4525,7 +4606,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4525
4606
4526
4607
const is_inline = decl .ty .fnCallingConvention () == .Inline ;
4527
4608
if (decl .is_exported ) {
4528
- const export_src = src ; // TODO make this point at `export` token
4609
+ const export_src : LazySrcLoc = .{ . token_offset = @boolToInt ( decl . is_pub ) };
4529
4610
if (is_inline ) {
4530
4611
return sema .fail (& block_scope , export_src , "export of inline function" , .{});
4531
4612
}
@@ -4588,14 +4669,14 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4588
4669
decl .generation = mod .generation ;
4589
4670
4590
4671
const has_runtime_bits = is_extern or
4591
- (queue_linker_work and try sema .typeHasRuntimeBits (& block_scope , src , decl .ty ));
4672
+ (queue_linker_work and try sema .typeHasRuntimeBits (& block_scope , ty_src , decl .ty ));
4592
4673
4593
4674
if (has_runtime_bits ) {
4594
4675
log .debug ("queue linker work for {*} ({s})" , .{ decl , decl .name });
4595
4676
4596
4677
// Needed for codegen_decl which will call updateDecl and then the
4597
4678
// codegen backend wants full access to the Decl Type.
4598
- try sema .resolveTypeFully (& block_scope , src , decl .ty );
4679
+ try sema .resolveTypeFully (& block_scope , ty_src , decl .ty );
4599
4680
4600
4681
try mod .comp .bin_file .allocateDeclIndexes (decl_index );
4601
4682
try mod .comp .work_queue .writeItem (.{ .codegen_decl = decl_index });
@@ -4606,7 +4687,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4606
4687
}
4607
4688
4608
4689
if (decl .is_exported ) {
4609
- const export_src = src ; // TODO point to the export token
4690
+ const export_src : LazySrcLoc = .{ . token_offset = @boolToInt ( decl . is_pub ) };
4610
4691
// The scope needs to have the decl in it.
4611
4692
const options : std.builtin.ExportOptions = .{ .name = mem .sliceTo (decl .name , 0 ) };
4612
4693
try sema .analyzeExport (& block_scope , export_src , options , decl_index );
0 commit comments