| ... | @@ -19706,18 +19706,26 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -19706,18 +19706,26 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 19706 | return ira->codegen->invalid_inst_gen; | 19706 | return ira->codegen->invalid_inst_gen; |
| 19707 | } | 19707 | } |
| 19708 | | 19708 | |
| | 19709 | bool extern_fn_in_typeof = false; |
| | 19710 | |
| 19709 | if (modifier == CallModifierCompileTime) { | 19711 | if (modifier == CallModifierCompileTime) { |
| 19710 | // No special handling is needed for compile time evaluation of generic functions. | 19712 | // No special handling is needed for compile time evaluation of generic functions. |
| 19711 | if (!fn_entry || fn_entry->body_node == nullptr) { | 19713 | if (!fn_entry || fn_entry->body_node == nullptr) { |
| 19712 | ir_add_error(ira, &fn_ref->base, buf_sprintf("unable to evaluate constant expression")); | 19714 | // We keep evaluating extern functions in TypeOfs |
| 19713 | return ira->codegen->invalid_inst_gen; | 19715 | if (get_scope_typeof(source_instr->scope) != nullptr && fn_entry) { |
| | 19716 | extern_fn_in_typeof = true; |
| | 19717 | } else { |
| | 19718 | ir_add_error(ira, &fn_ref->base, buf_sprintf("unable to evaluate constant expression")); |
| | 19719 | return ira->codegen->invalid_inst_gen; |
| | 19720 | } |
| 19714 | } | 19721 | } |
| 19715 | | 19722 | |
| 19716 | if (!ir_emit_backward_branch(ira, source_instr)) | 19723 | if (!ir_emit_backward_branch(ira, source_instr)) |
| 19717 | return ira->codegen->invalid_inst_gen; | 19724 | return ira->codegen->invalid_inst_gen; |
| 19718 | | 19725 | |
| 19719 | // Fork a scope of the function with known values for the parameters. | 19726 | // Fork a scope of the function with known values for the parameters. |
| 19720 | Scope *exec_scope = &fn_entry->fndef_scope->base; | 19727 | // If we are evaluating an extern function in a TypeOf, we use the TypeOf's scope instead. |
| | 19728 | Scope *exec_scope = extern_fn_in_typeof ? source_instr->scope : &fn_entry->fndef_scope->base; |
| 19721 | | 19729 | |
| 19722 | size_t next_proto_i = 0; | 19730 | size_t next_proto_i = 0; |
| 19723 | if (first_arg_ptr) { | 19731 | if (first_arg_ptr) { |
| ... | @@ -19766,7 +19774,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -19766,7 +19774,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 19766 | return_type = specified_return_type; | 19774 | return_type = specified_return_type; |
| 19767 | } | 19775 | } |
| 19768 | | 19776 | |
| 19769 | bool cacheable = fn_eval_cacheable(exec_scope, return_type); | 19777 | bool cacheable = !extern_fn_in_typeof && fn_eval_cacheable(exec_scope, return_type); |
| 19770 | ZigValue *result = nullptr; | 19778 | ZigValue *result = nullptr; |
| 19771 | if (cacheable) { | 19779 | if (cacheable) { |
| 19772 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); | 19780 | auto entry = ira->codegen->memoized_fn_eval_table.maybe_get(exec_scope); |
| ... | @@ -19779,12 +19787,16 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, | ... | @@ -19779,12 +19787,16 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr, |
| 19779 | AstNode *body_node = fn_entry->body_node; | 19787 | AstNode *body_node = fn_entry->body_node; |
| 19780 | ZigValue *result_ptr; | 19788 | ZigValue *result_ptr; |
| 19781 | create_result_ptr(ira->codegen, return_type, &result, &result_ptr); | 19789 | create_result_ptr(ira->codegen, return_type, &result, &result_ptr); |
| 19782 | if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr, | 19790 | |
| 19783 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, | 19791 | // If we are evaluating an extern function in a TypeOf, create a value and keep it undefined. |
| 19784 | fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, | 19792 | if (!extern_fn_in_typeof) { |
| 19785 | UndefOk))) | 19793 | if ((err = ir_eval_const_value(ira->codegen, exec_scope, body_node, result_ptr, |
| 19786 | { | 19794 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, |
| 19787 | return ira->codegen->invalid_inst_gen; | 19795 | fn_entry, nullptr, source_instr->source_node, nullptr, ira->new_irb.exec, return_type_node, |
| | 19796 | UndefOk))) |
| | 19797 | { |
| | 19798 | return ira->codegen->invalid_inst_gen; |
| | 19799 | } |
| 19788 | } | 19800 | } |
| 19789 | | 19801 | |
| 19790 | if (inferred_err_set_type != nullptr) { | 19802 | if (inferred_err_set_type != nullptr) { |