diff options
| author | Veikka Tuominen <git@vexu.eu> | 2020-05-30 01:11:22 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-30 01:11:22 +0300 |
| commit | 4c8b937fb016a54b09d7447ca634b7cf1af78fce (patch) | |
| tree | be94b0dad5a43376417c308163ade104c9055b7e /src/ir.cpp | |
| parent | 65c3833ec2793747961f532510feb4fbb52fd6a6 (diff) | |
| parent | d88db4d34bad1f4e140217f425300b417b448b64 (diff) | |
| download | zig-4c8b937fb016a54b09d7447ca634b7cf1af78fce.tar.gz zig-4c8b937fb016a54b09d7447ca634b7cf1af78fce.zip | |
Merge pull request #5184 from alexnask/typeof_extern_call
Extern functions are now evaluated to undefined values at comptime in TypeOf calls.
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index e956dec2f6..84c8002d7c 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -15419,6 +15419,12 @@ static IrInstGen *ir_get_deref(IrAnalyze *ira, IrInst* source_instruction, IrIns } if (instr_is_comptime(ptr)) { if (ptr->value->special == ConstValSpecialUndef) { + // If we are in a TypeOf call, we return an undefined value instead of erroring + // since we know the type. + if (get_scope_typeof(source_instruction->scope)) { + return ir_const_undef(ira, source_instruction, child_type); + } + ir_add_error(ira, &ptr->base, buf_sprintf("attempt to dereference undefined value")); return ira->codegen->invalid_inst_gen; } @@ -19720,6 +19726,20 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, } if (modifier == CallModifierCompileTime) { + // If we are evaluating an extern function in a TypeOf call, we can return an undefined value + // of its return type. + if (fn_entry != nullptr && get_scope_typeof(source_instr->scope) != nullptr && + fn_proto_node->data.fn_proto.is_extern) { + + assert(fn_entry->body_node == nullptr); + AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; + ZigType *return_type = ir_analyze_type_expr(ira, source_instr->scope, return_type_node); + if (type_is_invalid(return_type)) + return ira->codegen->invalid_inst_gen; + + return ir_const_undef(ira, source_instr, return_type); + } + // No special handling is needed for compile time evaluation of generic functions. if (!fn_entry || fn_entry->body_node == nullptr) { ir_add_error(ira, &fn_ref->base, buf_sprintf("unable to evaluate constant expression")); @@ -19792,6 +19812,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, AstNode *body_node = fn_entry->body_node; ZigValue *result_ptr; create_result_ptr(ira->codegen, return_type, &result, &result_ptr); + if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, @@ -21862,6 +21883,11 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name return ir_analyze_inferred_field_ptr(ira, field_name, source_instr, container_ptr, bare_type); } + // Tracks wether we should return an undefined value of the correct type. + // We do this if the container pointer is undefined and we are in a TypeOf call. + bool return_undef = container_ptr->value->special == ConstValSpecialUndef && \ + get_scope_typeof(source_instr->scope) != nullptr; + if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown))) return ira->codegen->invalid_inst_gen; @@ -21869,6 +21895,12 @@ static IrInstGen *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_name if (bare_type->id == ZigTypeIdStruct) { TypeStructField *field = find_struct_type_field(bare_type, field_name); if (field != nullptr) { + if (return_undef) { + ZigType *field_ptr_type = get_pointer_to_type(ira->codegen, resolve_struct_field_type(ira->codegen, field), + container_ptr->value->type->data.pointer.is_const); + return ir_const_undef(ira, source_instr, field_ptr_type); + } + return ir_analyze_struct_field_ptr(ira, source_instr, field, container_ptr, bare_type, initializing); } else { return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
