Commit be17a4b6c1
Changed files (2)
src
test
stage1
behavior
src/codegen.cpp
@@ -4113,6 +4113,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable,
IrInstructionStructFieldPtr *instruction)
{
+ Error err;
+
if (instruction->base.value.special != ConstValSpecialRuntime)
return nullptr;
@@ -4130,6 +4132,11 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
return struct_ptr;
}
+ ZigType *struct_type = (struct_ptr_type->id == ZigTypeIdPointer) ?
+ struct_ptr_type->data.pointer.child_type : struct_ptr_type;
+ if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
+ report_errors_and_exit(g);
+
assert(field->gen_index != SIZE_MAX);
return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
}
test/stage1/behavior/struct.zig
@@ -599,3 +599,36 @@ test "extern fn returns struct by value" {
S.entry();
comptime S.entry();
}
+
+test "for loop over pointers to struct, getting field from struct pointer" {
+ const S = struct {
+ const Foo = struct {
+ name: []const u8,
+ };
+
+ var ok = true;
+
+ fn eql(a: []const u8) bool {
+ return true;
+ }
+
+ const ArrayList = struct {
+ fn toSlice(self: *ArrayList) []*Foo {
+ return ([*]*Foo)(undefined)[0..0];
+ }
+ };
+
+ fn doTheTest() void {
+ var objects: ArrayList = undefined;
+
+ for (objects.toSlice()) |obj| {
+ if (eql(obj.name)) {
+ ok = false;
+ }
+ }
+
+ expect(ok);
+ }
+ };
+ S.doTheTest();
+}