astgen: fix ptrTypeExpr C-pointer allowzero error and source cursor save/restore

Add two fixes from audit of ptrTypeExpr against upstream AstGen.zig ptrType:

1. Reject `[*c]allowzero T` with a compile error matching upstream
   (AstGen.zig:3840-3842). C pointers always allow address zero, so
   the allowzero modifier is invalid on them.

2. Save source_offset/source_line/source_column before typeExpr and
   restore them before evaluating each trailing expression (sentinel,
   addrspace, align). This ensures correct debug info source locations
   matching upstream (AstGen.zig:3844-3846, 3859-3861, 3876-3878,
   3885-3887).

Issue 3 (addrspace RL using addBuiltinValue) is skipped as
addBuiltinValue is not yet implemented.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 22:25:39 +00:00
parent 2fc7e81d49
commit 257236be4c

View File

@@ -3033,6 +3033,18 @@ static uint32_t ptrTypeExpr(GenZir* gz, Scope* scope, uint32_t node) {
} }
} }
// C pointers always allow address zero (AstGen.zig:3840-3842).
if (size == 3 && has_allowzero) {
SET_ERROR(ag);
return ZIR_REF_VOID_VALUE;
}
// Save source cursor before typeExpr so we can restore it before each
// trailing expression (AstGen.zig:3844-3846).
uint32_t saved_source_offset = ag->source_offset;
uint32_t saved_source_line = ag->source_line;
uint32_t saved_source_column = ag->source_column;
// Evaluate element type (AstGen.zig:3847). // Evaluate element type (AstGen.zig:3847).
uint32_t elem_type = typeExpr(gz, scope, child_type_node); uint32_t elem_type = typeExpr(gz, scope, child_type_node);
@@ -3045,6 +3057,10 @@ static uint32_t ptrTypeExpr(GenZir* gz, Scope* scope, uint32_t node) {
uint32_t trailing_count = 0; uint32_t trailing_count = 0;
if (sentinel_node != UINT32_MAX) { if (sentinel_node != UINT32_MAX) {
// Restore source cursor (AstGen.zig:3859-3861).
ag->source_offset = saved_source_offset;
ag->source_line = saved_source_line;
ag->source_column = saved_source_column;
uint32_t reason = (size == 2) ? COMPTIME_REASON_SLICE_SENTINEL uint32_t reason = (size == 2) ? COMPTIME_REASON_SLICE_SENTINEL
: COMPTIME_REASON_POINTER_SENTINEL; : COMPTIME_REASON_POINTER_SENTINEL;
ResultLoc srl = { ResultLoc srl = {
@@ -3054,6 +3070,10 @@ static uint32_t ptrTypeExpr(GenZir* gz, Scope* scope, uint32_t node) {
trailing_count++; trailing_count++;
} }
if (addrspace_node != UINT32_MAX) { if (addrspace_node != UINT32_MAX) {
// Restore source cursor (AstGen.zig:3876-3878).
ag->source_offset = saved_source_offset;
ag->source_line = saved_source_line;
ag->source_column = saved_source_column;
// Upstream creates addrspace_ty via addBuiltinValue, we don't have // Upstream creates addrspace_ty via addBuiltinValue, we don't have
// that yet, so pass RL_NONE (matching previous behavior). // that yet, so pass RL_NONE (matching previous behavior).
addrspace_ref = comptimeExpr( addrspace_ref = comptimeExpr(
@@ -3061,6 +3081,10 @@ static uint32_t ptrTypeExpr(GenZir* gz, Scope* scope, uint32_t node) {
trailing_count++; trailing_count++;
} }
if (align_node != UINT32_MAX) { if (align_node != UINT32_MAX) {
// Restore source cursor (AstGen.zig:3885-3887).
ag->source_offset = saved_source_offset;
ag->source_line = saved_source_line;
ag->source_column = saved_source_column;
ResultLoc arl = { .tag = RL_COERCED_TY, ResultLoc arl = { .tag = RL_COERCED_TY,
.data = ZIR_REF_U29_TYPE, .data = ZIR_REF_U29_TYPE,
.src_node = 0, .src_node = 0,