diff --git a/src/aro/Diagnostics.zig b/src/aro/Diagnostics.zig index c018a4ca..29076f08 100644 --- a/src/aro/Diagnostics.zig +++ b/src/aro/Diagnostics.zig @@ -216,6 +216,7 @@ pub const Options = struct { @"shift-count-overflow": Kind = .default, @"constant-conversion": Kind = .default, @"sign-conversion": Kind = .default, + nonnull: Kind = .default, }; const Diagnostics = @This(); diff --git a/src/aro/Diagnostics/messages.def b/src/aro/Diagnostics/messages.def index 119e72a2..d9e8872b 100644 --- a/src/aro/Diagnostics/messages.def +++ b/src/aro/Diagnostics/messages.def @@ -446,6 +446,21 @@ expected_arguments .extra = .arguments .kind = .@"error" +callee_with_static_array + .msg = "callee declares array parameter as static here" + .kind = .note + +array_argument_too_small + .msg = "array argument is too small; contains {d} elements, callee requires at least {d}" + .extra = .arguments + .kind = .warning + .opt = W("array-bounds") + +non_null_argument + .msg = "null passed to a callee that requires a non-null argument" + .kind = .warning + .opt = W("nonnull") + expected_arguments_old .msg = expected_arguments .extra = .arguments diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index db2c0c61..f43990d0 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -3079,7 +3079,7 @@ fn directDeclarator(p: *Parser, base_type: Type, d: *Declarator, kind: Declarato arr_ty.len = max_elems; } res_ty.data = .{ .array = arr_ty }; - res_ty.specifier = .array; + res_ty.specifier = if (static != null) .static_array else .array; } try res_ty.combine(outer); @@ -7683,6 +7683,23 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result { continue; } const p_ty = params[arg_count].ty; + if (p_ty.specifier == .static_array) { + const arg_array_len: u64 = arg.ty.arrayLen() orelse std.math.maxInt(u64); + const param_array_len: u64 = p_ty.arrayLen().?; + if (arg_array_len < param_array_len) { + const extra = Diagnostics.Message.Extra{ .arguments = .{ + .expected = @intCast(arg_array_len), + .actual = @intCast(param_array_len), + } }; + try p.errExtra(.array_argument_too_small, param_tok, extra); + try p.errTok(.callee_with_static_array, params[arg_count].name_tok); + } + if (arg.val.isZero(p.comp)) { + try p.errTok(.non_null_argument, param_tok); + try p.errTok(.callee_with_static_array, params[arg_count].name_tok); + } + } + if (call_expr.shouldCoerceArg(arg_count)) { try arg.coerce(p, p_ty, param_tok, .{ .arg = params[arg_count].name_tok }); } diff --git a/test/cases/array argument is null.c b/test/cases/array argument is null.c new file mode 100644 index 00000000..a7945bf3 --- /dev/null +++ b/test/cases/array argument is null.c @@ -0,0 +1,19 @@ +//aro-args -std=c23 +#include +void foo(int x[static 10]) { + +} + +void bar(void) { + foo(NULL); + foo(nullptr); + foo(0); +} + +#define EXPECTED_ERRORS "array argument is null.c:8:9: warning: null passed to a callee that requires a non-null argument [-Wnonnull]"\ + "stddef.h:17:14: note: expanded from here"\ + "array argument is null.c:3:14: note: callee declares array parameter as static here"\ + "array argument is null.c:9:9: warning: null passed to a callee that requires a non-null argument [-Wnonnull]"\ + "array argument is null.c:3:14: note: callee declares array parameter as static here"\ + "array argument is null.c:10:9: warning: null passed to a callee that requires a non-null argument [-Wnonnull]"\ + "array argument is null.c:3:14: note: callee declares array parameter as static here" diff --git a/test/cases/array argument too small.c b/test/cases/array argument too small.c new file mode 100644 index 00000000..5168c2dc --- /dev/null +++ b/test/cases/array argument too small.c @@ -0,0 +1,11 @@ +void foo(int x[static 10]) { + +} + +void bar(void) { + int x[5]; + foo(x); +} + +#define EXPECTED_ERRORS "array argument too small.c:7:9: warning: array argument is too small; contains 5 elements, callee requires at least 10 [-Warray-bounds]"\ + "array argument too small.c:1:14: note: callee declares array parameter as static here"