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...@@ -15406,6 +15406,12 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrIns
15406 }15406 }
15407 if (instr_is_comptime(ptr)) {15407 if (instr_is_comptime(ptr)) {
15408 if (ptr->value->special == ConstValSpecialUndef) {15408 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
15409 ir_add_error(ira, &ptr->base, buf_sprintf("attempt to dereference undefined value"));15415 ir_add_error(ira, &ptr->base, buf_sprintf("attempt to dereference undefined value"));
15410 return ira->codegen->invalid_inst_gen;15416 return ira->codegen->invalid_inst_gen;
15411 }15417 }
...@@ -19709,7 +19715,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,...@@ -19709,7 +19715,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
19709 if (modifier == CallModifierCompileTime) {19715 if (modifier == CallModifierCompileTime) {
19710 // If we are evaluating an extern function in a TypeOf call, we can return an undefined value19716 // If we are evaluating an extern function in a TypeOf call, we can return an undefined value
19711 // of its return type.19717 // 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 &&
19713 fn_proto_node->data.fn_proto.is_extern) {19719 fn_proto_node->data.fn_proto.is_extern) {
1971419720
19715 assert(fn_entry->body_node == nullptr);19721 assert(fn_entry->body_node == nullptr);
...@@ -21842,6 +21848,11 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name...@@ -21842,6 +21848,11 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name
21842 return ir_analyze_inferred_field_ptr(ira, field_name, source_instr, container_ptr, bare_type);21848 return ir_analyze_inferred_field_ptr(ira, field_name, source_instr, container_ptr, bare_type);
21843 }21849 }
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
21845 if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown)))21856 if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown)))
21846 return ira->codegen->invalid_inst_gen;21857 return ira->codegen->invalid_inst_gen;
2184721858
...@@ -21849,6 +21860,12 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name...@@ -21849,6 +21860,12 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name
21849 if (bare_type->id == ZigTypeIdStruct) {21860 if (bare_type->id == ZigTypeIdStruct) {
21850 TypeStructField *field = find_struct_type_field(bare_type, field_name);21861 TypeStructField *field = find_struct_type_field(bare_type, field_name);
21851 if (field != nullptr) {21862 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
21852 return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing);21869 return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing);
21853 } else {21870 } else {
21854 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,21871 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}