Skip to content

Commit 21932a0

Browse files
committed
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
1 parent b022db1 commit 21932a0

File tree

3 files changed

+14
-3
lines changed

3 files changed

+14
-3
lines changed

src/ir.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11864,7 +11864,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
1186411864
}
1186511865
assert(wanted_type->data.fn.is_generic ||
1186611866
wanted_type->data.fn.fn_type_id.next_param_index == wanted_type->data.fn.fn_type_id.param_count);
11867-
for (size_t i = 0; i < wanted_type->data.fn.fn_type_id.next_param_index; i += 1) {
11867+
for (size_t i = 0; i < wanted_type->data.fn.fn_type_id.param_count; i += 1) {
1186811868
// note it's reversed for parameters
1186911869
FnTypeParamInfo *actual_param_info = &actual_type->data.fn.fn_type_id.param_info[i];
1187011870
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
3028530285
if (param_is_var_args) {
3028630286
if (fn_type_id.cc == CallingConventionC) {
3028730287
fn_type_id.param_count = fn_type_id.next_param_index;
30288-
continue;
30288+
break;
3028930289
} else if (fn_type_id.cc == CallingConventionUnspecified) {
3029030290
return get_generic_fn_type(ira->codegen, &fn_type_id);
3029130291
} else {

src/parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc) {
806806
if (param_decl->data.param_decl.is_var_args)
807807
res->data.fn_proto.is_var_args = true;
808808
if (i != params.length - 1 && res->data.fn_proto.is_var_args)
809-
ast_error(pc, first, "Function prototype have varargs as a none last paramter.");
809+
ast_error(pc, first, "Function prototype have varargs as a none last parameter.");
810810
}
811811
return res;
812812
}

test/compile_errors.zig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@ const builtin = @import("builtin");
33
const Target = @import("std").Target;
44

55
pub fn addCases(cases: *tests.CompileErrorContext) void {
6+
cases.addTest("type mismatch in C prototype with varargs",
7+
\\const fn_ty = ?fn ([*c]u8, ...) callconv(.C) void;
8+
\\extern fn fn_decl(fmt: [*:0]u8, ...) void;
9+
\\
10+
\\export fn main() void {
11+
\\ const x: fn_ty = fn_decl;
12+
\\}
13+
, &[_][]const u8{
14+
"tmp.zig:5:22: error: expected type 'fn([*c]u8, ...) callconv(.C) void', found 'fn([*:0]u8, ...) callconv(.C) void'",
15+
});
16+
617
cases.addTest("dependency loop in top-level decl with @TypeInfo",
718
\\export const foo = @typeInfo(@This());
819
, &[_][]const u8{

0 commit comments

Comments
 (0)