commit 908b908481260322b60f479ccf4cabff72fcc5d5 (tree)
parent 179423ec2712956e04f188bf8b904e4fb9b48656
Author: Alexandros Naskos <alex_naskos@hotmail.com>
Date: Mon, 27 Apr 2020 15:22:15 +0300
Added tests.
Diffstat:
3 files changed, 43 insertions(+), 6 deletions(-)
diff --git a/src/ir.cpp b/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))
diff --git a/test/stage1/behavior.zig b/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");
diff --git a/test/stage1/behavior/bugs/4328.zig b/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();
+}