authorgravatar for alex_naskos@hotmail.comAlexandros Naskos <alex_naskos@hotmail.com> 2020-05-18 19:15:44+03:00
committergravatar for alex_naskos@hotmail.comAlexandros Naskos <alex_naskos@hotmail.com> 2020-05-18 19:15:44+03:00
log400a91e1c644228a66aa1702b9d800f018712105
treee5c6dc1cba4df2235a88681a6273a8d6bb2aed18
parent37fa418a94fc5da695f8799b6b021b632bb1d500

Add TypeOf resolution of dereferences and struct fields of undefined values


3 files changed, 67 insertions(+), 50 deletions(-)

src/ir.cpp+18-1
......@@ -15406,6 +15406,12 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrIns
1540615406 }
1540715407 if (instr_is_comptime(ptr)) {
1540815408 if (ptr->value->special == ConstValSpecialUndef) {
15409 // If we are in a TypeOf call, we return an undefined value instead of erroring
15410 // since we know the type.
15411 if (get_scope_typeof(source_instruction->scope)) {
15412 return ir_const_undef(ira, source_instruction, child_type);
15413 }
15414
1540915415 ir_add_error(ira, &ptr->base, buf_sprintf("attempt to dereference undefined value"));
1541015416 return ira->codegen->invalid_inst_gen;
1541115417 }
......@@ -19709,7 +19715,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
1970919715 if (modifier == CallModifierCompileTime) {
1971019716 // If we are evaluating an extern function in a TypeOf call, we can return an undefined value
1971119717 // of its return type.
19712 if (fn_entry != nullptr && source_instr->scope->id == ScopeIdTypeOf &&
19718 if (fn_entry != nullptr && get_scope_typeof(source_instr->scope) != nullptr &&
1971319719 fn_proto_node->data.fn_proto.is_extern) {
1971419720
1971519721 assert(fn_entry->body_node == nullptr);
......@@ -21842,6 +21848,11 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name
2184221848 return ir_analyze_inferred_field_ptr(ira, field_name, source_instr, container_ptr, bare_type);
2184321849 }
2184421850
21851 // Tracks wether we should return an undefined value of the correct type.
21852 // We do this if the container pointer is undefined and we are in a TypeOf call.
21853 bool return_undef = container_ptr->value->special == ConstValSpecialUndef && \
21854 get_scope_typeof(source_instr->scope) != nullptr;
21855
2184521856 if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown)))
2184621857 return ira->codegen->invalid_inst_gen;
2184721858
......@@ -21849,6 +21860,12 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name
2184921860 if (bare_type->id == ZigTypeIdStruct) {
2185021861 TypeStructField *field = find_struct_type_field(bare_type, field_name);
2185121862 if (field != nullptr) {
21863 if (return_undef) {
21864 ZigType *field_ptr_type = get_pointer_to_type(ira->codegen, resolve_struct_field_type(ira->codegen, field),
21865 container_ptr->value->type->data.pointer.is_const);
21866 return ir_const_undef(ira, source_instr, field_ptr_type);
21867 }
21868
2185221869 return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing);
2185321870 } else {
2185421871 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
test/stage1/behavior/bugs/4328.zig deleted-49
......@@ -1,49 +0,0 @@
1const expectEqual = @import("std").testing.expectEqual;
2
3const FILE = extern struct {
4 dummy_field: u8,
5};
6extern fn printf([*c]const u8, ...) c_int;
7extern fn fputs([*c]const u8, noalias [*c]FILE) c_int;
8extern fn ftell([*c]FILE) c_long;
9
10const S = extern struct {
11 state: c_short,
12
13 extern fn s_do_thing([*c]S, b: c_int) c_short;
14};
15
16test "Extern function calls in @TypeOf" {
17 const Test = struct {
18 fn test_fn_1(a: var, b: var) @TypeOf(printf("%d %s\n", a, b)) {
19 return 0;
20 }
21
22 fn test_fn_2(a: var) @TypeOf((S{ .state = 0 }).s_do_thing(a)) {
23 return 1;
24 }
25
26 fn doTheTest() void {
27 expectEqual(c_int, @TypeOf(test_fn_1(0, 42)));
28 expectEqual(c_short, @TypeOf(test_fn_2(0)));
29 }
30 };
31
32 Test.doTheTest();
33 comptime Test.doTheTest();
34}
35
36test "Peer resolution of extern function calls in @TypeOf" {
37 const Test = struct {
38 fn test_fn() @TypeOf(ftell(null), fputs(null, null)) {
39 return 0;
40 }
41
42 fn doTheTest() void {
43 expectEqual(c_long, @TypeOf(test_fn()));
44 }
45 };
46
47 Test.doTheTest();
48 comptime Test.doTheTest();
49}
test/stage1/behavior/bugs/4328_5305.zig created+49
......@@ -0,0 +1,49 @@
1const expectEqual = @import("std").testing.expectEqual;
2
3const FILE = extern struct {
4 dummy_field: u8,
5};
6extern fn printf([*c]const u8, ...) c_int;
7extern fn fputs([*c]const u8, noalias [*c]FILE) c_int;
8extern fn ftell([*c]FILE) c_long;
9
10const S = extern struct {
11 state: c_short,
12
13 extern fn s_do_thing([*c]S, b: c_int) c_short;
14};
15
16test "Extern function calls in @TypeOf" {
17 const Test = struct {
18 fn test_fn_1(a: var, b: var) @TypeOf(printf("%d %s\n", a, b)) {
19 return 0;
20 }
21
22 fn test_fn_2(a: var) @TypeOf((S{ .state = 0 }).s_do_thing(a)) {
23 return 1;
24 }
25
26 fn doTheTest() void {
27 expectEqual(c_int, @TypeOf(test_fn_1(0, 42)));
28 expectEqual(c_short, @TypeOf(test_fn_2(0)));
29 }
30 };
31
32 Test.doTheTest();
33 comptime Test.doTheTest();
34}
35
36test "Peer resolution of extern function calls in @TypeOf" {
37 const Test = struct {
38 fn test_fn() @TypeOf(ftell(null), fputs(null, null)) {
39 return 0;
40 }
41
42 fn doTheTest() void {
43 expectEqual(c_long, @TypeOf(test_fn()));
44 }
45 };
46
47 Test.doTheTest();
48 comptime Test.doTheTest();
49}