Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1687,16 +1687,18 @@ static bool emit_getfield_unknownidx(jl_codectx_t &ctx,
else if (is_tupletype_homogeneous(stt->types)) {
assert(nfields > 0); // nf == 0 trapped by all_pointers case
jl_value_t *jft = jl_svecref(stt->types, 0);
assert(jl_is_concrete_type(jft));
idx = idx0();
Value *ptr = maybe_decay_tracked(ctx, data_pointer(ctx, strct));
if (!stt->mutabl && !(maybe_null && jft == (jl_value_t*)jl_bool_type)) {
if (!stt->mutabl && !(maybe_null && (jft == (jl_value_t*)jl_bool_type ||
((jl_datatype_t*)jft)->layout->npointers))) {
// just compute the pointer and let user load it when necessary
Type *fty = julia_type_to_llvm(ctx, jft);
Value *addr = ctx.builder.CreateInBoundsGEP(fty, emit_bitcast(ctx, ptr, PointerType::get(fty, 0)), idx);
*ret = mark_julia_slot(addr, jft, NULL, strct.tbaa);
return true;
}
*ret = typed_load(ctx, ptr, idx, jft, strct.tbaa, nullptr, false);
*ret = typed_load(ctx, ptr, idx, jft, strct.tbaa, nullptr, maybe_null);
return true;
}
else if (strct.isboxed) {
Expand Down Expand Up @@ -1787,12 +1789,14 @@ static jl_cgval_t emit_getfield_knownidx(jl_codectx_t &ctx, const jl_cgval_t &st
}
return mark_julia_slot(addr, jfty, tindex, tbaa);
}
else if (!jt->mutabl && !(maybe_null && jfty == (jl_value_t*)jl_bool_type)) {
assert(jl_is_concrete_type(jfty));
if (!jt->mutabl && !(maybe_null && (jfty == (jl_value_t*)jl_bool_type ||
((jl_datatype_t*)jfty)->layout->npointers))) {
// just compute the pointer and let user load it when necessary
return mark_julia_slot(addr, jfty, NULL, tbaa);
}
unsigned align = jl_field_align(jt, idx);
return typed_load(ctx, addr, NULL, jfty, tbaa, nullptr, true, align);
return typed_load(ctx, addr, NULL, jfty, tbaa, nullptr, maybe_null, align);
}
else if (isa<UndefValue>(strct.V)) {
return jl_cgval_t();
Expand Down
66 changes: 66 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7330,3 +7330,69 @@ function c37265_2(d)
e
end
@test_throws TypeError c37265_2(0)

struct PointerImmutable
a::Any
b::Int
end
struct NullableHomogeneousPointerImmutable
x1::PointerImmutable
x2::PointerImmutable
x3::PointerImmutable
NullableHomogeneousPointerImmutable() = new()
NullableHomogeneousPointerImmutable(x1) = new(x1)
NullableHomogeneousPointerImmutable(x1, x2) = new(x1, x2)
NullableHomogeneousPointerImmutable(x1, x2, x3) = new(x1, x2, x3)
end

function getfield_knownindex_unused(v)
v.x1
return
end

function getfield_unknownindex_unused(v, n)
getfield(v, n)
return
end

function getfield_knownindex_used1(r, v)
fld = v.x1
r[] += 1
return fld
end

function getfield_knownindex_used2(r, v)
fld = v.x1
r[] += 1
return fld.a
end

function getfield_knownindex_used3(r, v)
fld = v.x1
r[] += 1
return fld.b
end

let v = NullableHomogeneousPointerImmutable(),
v2 = NullableHomogeneousPointerImmutable(PointerImmutable(1, 2)),
r = Ref(0)
@test_throws UndefRefError getfield_knownindex_unused(v)
@test_throws UndefRefError getfield_unknownindex_unused(v, 1)
@test_throws UndefRefError getfield_unknownindex_unused(v, :x1)
@test_throws UndefRefError getfield_knownindex_used1(r, v)
@test r[] == 0
@test_throws UndefRefError getfield_knownindex_used2(r, v)
@test r[] == 0
@test_throws UndefRefError getfield_knownindex_used3(r, v)
@test r[] == 0

@test getfield_knownindex_unused(v2) === nothing
@test getfield_unknownindex_unused(v2, 1) === nothing
@test getfield_unknownindex_unused(v2, :x1) === nothing
@test getfield_knownindex_used1(r, v2) === PointerImmutable(1, 2)
@test r[] == 1
@test getfield_knownindex_used2(r, v2) === 1
@test r[] == 2
@test getfield_knownindex_used3(r, v2) === 2
@test r[] == 3
end