Commit 908b908481
Changed files (3)
src
test
stage1
behavior
bugs
src/ir.cpp
@@ -19706,13 +19706,13 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
return ira->codegen->invalid_inst_gen;
}
- bool extern_fn_in_typeof = false;
-
if (modifier == CallModifierCompileTime) {
+ bool extern_fn_in_typeof = false;
+
// No special handling is needed for compile time evaluation of generic functions.
if (!fn_entry || fn_entry->body_node == nullptr) {
- // We keep evaluating extern functions in TypeOfs
- if (get_scope_typeof(source_instr->scope) != nullptr && fn_entry) {
+ // We keep evaluating extern functions directly in TypeOfs
+ if (fn_entry && source_instr->scope->id == ScopeIdTypeOf) {
extern_fn_in_typeof = true;
} else {
ir_add_error(ira, &fn_ref->base, buf_sprintf("unable to evaluate constant expression"));
@@ -19724,7 +19724,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
return ira->codegen->invalid_inst_gen;
// Fork a scope of the function with known values for the parameters.
- // If we are evaluating an extern function in a TypeOf, we use the TypeOf's scope instead.
+ // If we are evaluating an extern function in a TypeOf, we use the current scope instead.
Scope *exec_scope = extern_fn_in_typeof ? source_instr->scope : &fn_entry->fndef_scope->base;
size_t next_proto_i = 0;
@@ -19752,7 +19752,7 @@ static IrInstGen *ir_analyze_fn_call(IrAnalyze *ira, IrInst* source_instr,
return ira->codegen->invalid_inst_gen;
}
- for (size_t call_i = 0; call_i < args_len; call_i += 1) {
+ if (!extern_fn_in_typeof) for (size_t call_i = 0; call_i < args_len; call_i += 1) {
IrInstGen *old_arg = args_ptr[call_i];
if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_proto_i))
test/stage1/behavior/bugs/4328.zig
@@ -0,0 +1,36 @@
+const expectEqual = @import("std").testing.expectEqual;
+
+const FILE = extern struct { dummy_field: u8, };
+extern fn printf([*c]const u8, ...) c_int;
+extern fn fputs([*c]const u8, noalias [*c]FILE) c_int;
+extern fn ftell([*c]FILE) c_long;
+
+test "Extern function call in @TypeOf" {
+ const Test = struct {
+ fn test_fn(a: var, b: var) @TypeOf(printf("%d %s\n", a, b)) {
+ return 0;
+ }
+
+ fn doTheTest() void {
+ expectEqual(c_int, @TypeOf(test_fn(0, 42)));
+ }
+ };
+
+ Test.doTheTest();
+ comptime Test.doTheTest();
+}
+
+test "Peer resolution of extern function calls in @TypeOf" {
+ const Test = struct {
+ fn test_fn() @TypeOf(ftell(null), fputs(null, null)) {
+ return 0;
+ }
+
+ fn doTheTest() void {
+ expectEqual(c_long, @TypeOf(test_fn()));
+ }
+ };
+
+ Test.doTheTest();
+ comptime Test.doTheTest();
+}
test/stage1/behavior.zig
@@ -40,6 +40,7 @@ comptime {
_ = @import("behavior/bugs/3384.zig");
_ = @import("behavior/bugs/3586.zig");
_ = @import("behavior/bugs/3742.zig");
+ _ = @import("behavior/bugs/4328.zig");
_ = @import("behavior/bugs/4560.zig");
_ = @import("behavior/bugs/4769_a.zig");
_ = @import("behavior/bugs/4769_b.zig");