From 21932a0ef25a7055cd3c0850fa58c2fda2ba383b Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Wed, 5 Feb 2020 20:31:18 +0100 Subject: [PATCH] Fix edge case in cast between fn with varargs * Prevent the next_param_index to become greater than the param_count one as it's expected by every other function. * Fix a typo in a error message. Closes #4381 --- src/ir.cpp | 4 ++-- src/parser.cpp | 2 +- test/compile_errors.zig | 11 +++++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index ef3426d111..0687d18ef2 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -11864,7 +11864,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted } assert(wanted_type->data.fn.is_generic || wanted_type->data.fn.fn_type_id.next_param_index == wanted_type->data.fn.fn_type_id.param_count); - for (size_t i = 0; i < wanted_type->data.fn.fn_type_id.next_param_index; i += 1) { + for (size_t i = 0; i < wanted_type->data.fn.fn_type_id.param_count; i += 1) { // note it's reversed for parameters FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i]; FnTypeParamInfo *expected_param_info = &wanted_type->data.fn.fn_type_id.param_info[i]; @@ -30285,7 +30285,7 @@ static ZigType *ir_resolve_lazy_fn_type(IrAnalyze *ira, AstNode *source_node, La if (param_is_var_args) { if (fn_type_id.cc == CallingConventionC) { fn_type_id.param_count = fn_type_id.next_param_index; - continue; + break; } else if (fn_type_id.cc == CallingConventionUnspecified) { return get_generic_fn_type(ira->codegen, &fn_type_id); } else { diff --git a/src/parser.cpp b/src/parser.cpp index a4dc324b2f..0da7aac639 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -806,7 +806,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) { if (param_decl->data.param_decl.is_var_args) res->data.fn_proto.is_var_args = true; if (i != params.length - 1 && res->data.fn_proto.is_var_args) - ast_error(pc, first, "Function prototype have varargs as a none last paramter."); + ast_error(pc, first, "Function prototype have varargs as a none last parameter."); } return res; } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 341062e161..0af07d3ece 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -3,6 +3,17 @@ const builtin = @import("builtin"); const Target = @import("std").Target; pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.addTest("type mismatch in C prototype with varargs", + \\const fn_ty = ?fn ([*c]u8, ...) callconv(.C) void; + \\extern fn fn_decl(fmt: [*:0]u8, ...) void; + \\ + \\export fn main() void { + \\ const x: fn_ty = fn_decl; + \\} + , &[_][]const u8{ + "tmp.zig:5:22: error: expected type 'fn([*c]u8, ...) callconv(.C) void', found 'fn([*:0]u8, ...) callconv(.C) void'", + }); + cases.addTest("dependency loop in top-level decl with @TypeInfo", \\export const foo = @typeInfo(@This()); , &[_][]const u8{