chained dereference

This commit is contained in:
agra
2026-02-24 17:42:13 +02:00
parent 566121c45a
commit 630e76c319

View File

@@ -3912,7 +3912,7 @@ pub const CodeGen = struct {
fn genFieldAssignment(self: *CodeGen, asgn: ast.Assignment) !c.LLVMValueRef {
const fa = asgn.target.data.field_access;
// Non-identifier object (e.g. a.first.next = val — chained pointer field assignment)
// Non-identifier object (e.g. a.b.c = val — chained field assignment)
if (fa.object.data != .identifier) {
const obj_ty = self.inferType(fa.object);
if (obj_ty.isPointer()) {
@@ -3931,6 +3931,18 @@ pub const CodeGen = struct {
return null;
}
}
if (obj_ty.isStruct()) {
// Chained struct field: expr.field = val where expr is a struct (e.g. self.inner.len = 0)
const sname = obj_ty.struct_type;
const info = try self.getStructInfo(sname);
const fi = try self.findFieldIndex(info.field_names, fa.field, sname);
const field_ty = info.field_types[fi];
const intermediate_ptr = try self.genAddressOf(fa.object);
const gep = self.structGEP(info.llvm_type, intermediate_ptr, @intCast(fi), "chain_sfield_ptr");
const rhs = try self.genExprAsType(asgn.value, field_ty);
self.storeOrCompound(asgn.op, gep, rhs, field_ty, "chain_scur");
return null;
}
return self.emitError("field assignment target must be a variable");
}
const obj_name = fa.object.data.identifier.name;
@@ -4604,6 +4616,25 @@ pub const CodeGen = struct {
}
}
}
} else {
// Chained field access: a.b.c — recursively get address of intermediate
const intermediate_ptr = try self.genAddressOf(fa.object);
const obj_ty = self.inferType(fa.object);
if (obj_ty.isStruct()) {
const sname = obj_ty.struct_type;
const info = try self.getStructInfo(sname);
const idx = try self.findFieldIndex(info.field_names, fa.field, sname);
return self.structGEP(info.llvm_type, intermediate_ptr, @intCast(idx), "addr_chain_field");
}
if (obj_ty.isPointer()) {
const pointee_name = obj_ty.pointer_type.pointee_name;
if (self.lookupStructInfo(pointee_name)) |info| {
const loaded_ptr = c.LLVMBuildLoad2(self.builder,
self.ptrType(), intermediate_ptr, "chain_ptr_load");
const idx = try self.findFieldIndex(info.field_names, fa.field, pointee_name);
return self.structGEP(info.llvm_type, loaded_ptr, @intCast(idx), "addr_chain_pfield");
}
}
}
}
return self.emitError("address-of requires a variable, index, or field expression");