zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 908b908481260322b60f479ccf4cabff72fcc5d5 (tree)
parent 179423ec2712956e04f188bf8b904e4fb9b48656
Author: Alexandros Naskos <alex_naskos@hotmail.com>
Date:   Mon, 27 Apr 2020 15:22:15 +0300

Added tests.

Diffstat:
Msrc/ir.cpp | 12++++++------
Mtest/stage1/behavior.zig | 1+
Atest/stage1/behavior/bugs/4328.zig | 36++++++++++++++++++++++++++++++++++++
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(); +}