From: Bart Van Assche <bvanassche@acm.org>
To: linux-sparse@vger.kernel.org
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
Bart Van Assche <bvanassche@acm.org>
Subject: [PATCH 59/73] c23: Treat empty parameter list () as (void) and reject K&R functions
Date: Mon, 9 Nov 2026 12:32:45 -0800 [thread overview]
Message-ID: <20261109203259.362845-60-bvanassche@acm.org> (raw)
In-Reply-To: <20261109203259.362845-1-bvanassche@acm.org>
Treat an empty parameter list '()' in a function declarator as '(void)'
and reject K&R identifier-list function declarations and definitions in
C23 mode per ISO C23 6.7.6.3 and 6.9.1:
- Parse '()' as a zero-parameter prototype in C23 mode so calls with
arguments and conflicting redeclarations are diagnosed.
- Track identifier-list declarators via kr_args on SYM_FN and report an
error in C23 mode on K&R function definitions (with or without
parameter declarations) and K&R function or function-pointer
declarations.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
parse.c | 34 ++++++++++++++++++---
symbol.h | 1 +
validation/c23-empty-parameters.c | 29 ++++++++++++++++++
validation/c23-empty-params-error.c | 47 +++++++++++++++++++++++++++++
validation/c23-knr-error.c | 14 +++++++++
5 files changed, 120 insertions(+), 5 deletions(-)
create mode 100644 validation/c23-empty-parameters.c
create mode 100644 validation/c23-empty-params-error.c
create mode 100644 validation/c23-knr-error.c
diff --git a/parse.c b/parse.c
index f49b3f188c69..782683a84fba 100644
--- a/parse.c
+++ b/parse.c
@@ -2241,9 +2241,14 @@ static enum kind which_func(struct token *token,
if (lookup_type(next) || next != token->next)
return Proto;
/* identifier list not in definition; complain */
- if (prefer_abstract)
- warning(token->pos,
- "identifier list not in definition");
+ if (prefer_abstract || !n) {
+ if (standard >= STANDARD_C23)
+ sparse_error(token->pos,
+ "identifier list not in definition");
+ else
+ warning(token->pos,
+ "identifier list not in definition");
+ }
return K_R;
}
@@ -2251,6 +2256,8 @@ static enum kind which_func(struct token *token,
return Bad_Func;
if (next->special == ')') {
+ if (standard >= STANDARD_C23)
+ return Proto;
/* don't complain about those */
if (!n || match_op(next->next, ';') || match_op(next->next, ','))
return Empty;
@@ -3284,6 +3291,7 @@ static struct token * statement_list(struct token *token, struct statement_list
static struct token *identifier_list(struct token *token, struct symbol *fn)
{
struct symbol_list **list = &fn->arguments;
+ fn->kr_args = 1;
for (;;) {
struct symbol *sym = alloc_symbol(token->pos, SYM_NODE);
sym->ident = token->ident;
@@ -3304,6 +3312,9 @@ static struct token *parameter_type_list(struct token *token, struct symbol *fn)
{
struct symbol_list **list = &fn->arguments;
+ if (match_op(token, ')'))
+ return token;
+
for (;;) {
struct symbol *sym;
@@ -3602,7 +3613,10 @@ static struct token *parse_k_r_arguments(struct token *token, struct symbol *dec
{
struct symbol_list *args = NULL;
- if (Wold_style_definition)
+ if (standard >= STANDARD_C23)
+ sparse_error(token->pos,
+ "old-style function definition is invalid in C23");
+ else if (Wold_style_definition)
warning(token->pos, "non-ANSI definition of function '%s'", show_ident(decl->ident));
do {
@@ -3772,8 +3786,15 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis
}
if (lookup_type(token))
return parse_k_r_arguments(token, decl, list);
- if (match_op(token, '{'))
+ if (match_op(token, '{')) {
+ if (standard >= STANDARD_C23 && base_type->kr_args)
+ sparse_error(decl->pos,
+ "old-style function definition is invalid in C23");
return parse_function_body(token, decl, list);
+ }
+ if (standard >= STANDARD_C23 && base_type->kr_args)
+ sparse_error(decl->pos,
+ "identifier list not in function definition");
if (!(decl->ctype.modifiers & MOD_STATIC))
decl->ctype.modifiers |= MOD_EXTERN;
@@ -3977,6 +3998,9 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis
base_type = decl->ctype.base_type;
if (!is_typedef && base_type && base_type->type == SYM_FN) {
decl->ctype.modifiers |= ctx.f_modifiers;
+ if (standard >= STANDARD_C23 && base_type->kr_args)
+ sparse_error(decl->pos,
+ "identifier list not in function definition");
if (!(decl->ctype.modifiers & MOD_STATIC))
decl->ctype.modifiers |= MOD_EXTERN;
}
diff --git a/symbol.h b/symbol.h
index a072ac8fc739..942baad97df5 100644
--- a/symbol.h
+++ b/symbol.h
@@ -198,6 +198,7 @@ struct symbol {
packed : 1, transparent_union : 1,
fixed_type : 1;
unsigned int has_alignas : 1;
+ unsigned int kr_args : 1;
unsigned int underspecified : 1;
unsigned int c23_auto : 1;
int rank:3; // arithmetic's rank
diff --git a/validation/c23-empty-parameters.c b/validation/c23-empty-parameters.c
new file mode 100644
index 000000000000..9c493256d54b
--- /dev/null
+++ b/validation/c23-empty-parameters.c
@@ -0,0 +1,29 @@
+int f();
+int f(void)
+{
+ return 0;
+}
+
+int g(void);
+int g()
+{
+ return 1;
+}
+
+static int h()
+{
+ return 2;
+}
+
+static int test(void)
+{
+ int (*fp)() = f;
+ int (*fp2)(void) = h;
+
+ return fp() + fp2() + g();
+}
+
+/*
+ * check-name: c23-empty-parameters
+ * check-command: sparse -std=c23 -Wstrict-prototypes -pedantic $file
+ */
diff --git a/validation/c23-empty-params-error.c b/validation/c23-empty-params-error.c
new file mode 100644
index 000000000000..4c0efe972358
--- /dev/null
+++ b/validation/c23-empty-params-error.c
@@ -0,0 +1,47 @@
+int f();
+
+static int h()
+{
+ return 0;
+}
+
+int mismatch();
+int mismatch(int x)
+{
+ return x;
+}
+
+int ident_decl(a, b);
+int (*bad_fp)(a, b);
+
+int old_implicit(a, b)
+{
+ return 0;
+}
+
+static void bad_calls(int (*fp)())
+{
+ f(1);
+ h(1, 2);
+ fp(3);
+}
+
+/*
+ * check-name: c23-empty-params-error
+ * check-command: sparse -std=c23 -Wno-decl $file
+ *
+ * check-error-start
+c23-empty-params-error.c:14:5: error: identifier list not in function definition
+c23-empty-params-error.c:15:14: error: identifier list not in definition
+c23-empty-params-error.c:17:5: error: old-style function definition is invalid in C23
+c23-empty-params-error.c:17:18: error: missing type declaration for parameter 'a'
+c23-empty-params-error.c:17:21: error: missing type declaration for parameter 'b'
+c23-empty-params-error.c:9:5: error: symbol 'mismatch' redeclared with different type (different argument counts):
+c23-empty-params-error.c:9:5: int extern [addressable] [signed] [toplevel] mismatch( ... )
+c23-empty-params-error.c:8:5: note: previously declared as:
+c23-empty-params-error.c:8:5: int extern [addressable] [signed] [toplevel] mismatch( ... )
+c23-empty-params-error.c:24:10: error: too many arguments for function f
+c23-empty-params-error.c:25:10: error: too many arguments for function h
+c23-empty-params-error.c:26:11: error: too many arguments for function fp
+ * check-error-end
+ */
diff --git a/validation/c23-knr-error.c b/validation/c23-knr-error.c
new file mode 100644
index 000000000000..f7ae837815b5
--- /dev/null
+++ b/validation/c23-knr-error.c
@@ -0,0 +1,14 @@
+int old_func(a, b)
+int a, b;
+{
+ return a + b;
+}
+
+/*
+ * check-name: c23-knr-error
+ * check-command: sparse -std=c23 $file
+ *
+ * check-error-start
+c23-knr-error.c:2:1: error: old-style function definition is invalid in C23
+ * check-error-end
+ */
next prev parent reply other threads:[~2026-11-09 20:33 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 20:31 Bart Van Assche
2026-11-09 20:31 ` [PATCH 01/73] Makefile: Pass '--' to rm in clean target to handle dash-prefixed files Bart Van Assche
2026-11-09 20:31 ` [PATCH 02/73] sparse-llvm: Use LLVMCreateBuilderForModule() with LLVM 24 and later Bart Van Assche
2026-11-09 20:31 ` [PATCH 03/73] typeof_unqual: Strip qualifiers and address space from types and arrays Bart Van Assche
2026-11-09 20:31 ` [PATCH 04/73] bitfield: Pack consecutive _Bool bitfields into byte containers Bart Van Assche
2026-11-09 20:31 ` [PATCH 05/73] allocate: Harden slab allocation bounds, zeroing, and mmap checks Bart Van Assche
2026-11-09 20:31 ` [PATCH 06/73] tokenize: Support 4096-byte identifiers and fix escape bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 07/73] pre-process: Fix macro expansion and include directive handling Bart Van Assche
2026-11-09 20:31 ` [PATCH 08/73] options, lib: Harden warning buffers and command-line option parsing Bart Van Assche
2026-11-09 20:31 ` [PATCH 09/73] builtin: Fix atomic builtin type checking and object_size bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 10/73] parse, show-parse: Fix attribute propagation, enum overflow, and bounds Bart Van Assche
2026-11-09 20:31 ` [PATCH 11/73] target-openrisc: Set target_openrisc.mach to MACH_OPENRISC Bart Van Assche
2026-11-09 20:31 ` [PATCH 12/73] evaluate: Fix pointer arithmetic, incomplete types, and qualifiers Bart Van Assche
2026-11-09 20:31 ` [PATCH 13/73] expand: Fix static initializer folding and floating-point casts Bart Van Assche
2026-11-09 20:32 ` [PATCH 14/73] inline: Copy union cast types and VLA bounds when inlining Bart Van Assche
2026-11-09 20:32 ` [PATCH 15/73] linearize, flow: Fix asm operands, switch case bounds, and DSE Bart Van Assche
2026-11-09 20:32 ` [PATCH 16/73] memops, ssa: Walk parent insns in reverse and skip mixed-size SSA Bart Van Assche
2026-11-09 20:32 ` [PATCH 17/73] simplify: Prevent overflow on LLONG_MIN negation and fix simplifications Bart Van Assche
2026-11-09 20:32 ` [PATCH 18/73] sparse: Gate context failure warning on Wcontext and catch underflow Bart Van Assche
2026-11-09 20:32 ` [PATCH 19/73] ast-model: Return AST_N_COLUMNS and inspect child nodes lazily Bart Van Assche
2026-11-09 20:32 ` [PATCH 20/73] c2xml: Guard against recursive symbols and free xmlGetProp() string Bart Van Assche
2026-11-09 20:32 ` [PATCH 21/73] compile-i386: Fix buffer bounds, unsigned '<=' codegen, and null checks Bart Van Assche
2026-11-09 20:32 ` [PATCH 22/73] ctags: Fix line comparison order and handle SYM_RESTRICT and SYM_LABEL Bart Van Assche
2026-11-09 20:32 ` [PATCH 23/73] dissect: Unwrap array element type via base_type() Bart Van Assche
2026-11-09 20:32 ` [PATCH 24/73] example: Fix show_op() rotating buffer dimensions Bart Van Assche
2026-11-09 20:32 ` [PATCH 25/73] graph: Check PSEUDO_SYM before dereferencing insn->func->sym Bart Van Assche
2026-11-09 20:32 ` [PATCH 26/73] scheck: Fix slice() upper bit index calculation Bart Van Assche
2026-11-09 20:32 ` [PATCH 27/73] sparse-llvm: Support arbitrary struct member counts and fix operand types Bart Van Assche
2026-11-09 20:32 ` [PATCH 28/73] inline: Duplicate generic expressions instead of evaluating them Bart Van Assche
2026-11-09 20:32 ` [PATCH 29/73] lib: Avoid mutating fmt before va_start() in warning() Bart Van Assche
2026-11-09 20:32 ` [PATCH 30/73] cse, canon: Cast pointers to uintptr_t before relational comparison Bart Van Assche
2026-11-09 20:32 ` [PATCH 31/73] context: Add "conditional context increment" model Bart Van Assche
2026-11-09 20:32 ` [PATCH 32/73] expand: Simplify signed constants early Bart Van Assche
2026-11-09 20:32 ` [PATCH 33/73] bitwise: Allow all-bits-set as a restricted value Bart Van Assche
2026-11-09 20:32 ` [PATCH 34/73] bitwise: Allow restricted ordered compares with unrestricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 35/73] bitwise: Keep unrestricted values unrestricted after a cast Bart Van Assche
2026-11-09 20:32 ` [PATCH 36/73] bitwise: Don't remove MOD_SPECIFIER from 'bitwise' types Bart Van Assche
2026-11-09 20:32 ` [PATCH 37/73] bitwise: Allow both regular casts and forced casts for restricted values Bart Van Assche
2026-11-09 20:32 ` [PATCH 38/73] clang-format: Add .clang-format configuration file Bart Van Assche
2026-11-09 20:32 ` [PATCH 39/73] options: Add support for -std=c23, -std=c2x and -std=gnu23 Bart Van Assche
2026-11-09 20:32 ` [PATCH 40/73] preprocessor: Add support for #elifdef and #elifndef Bart Van Assche
2026-11-09 20:32 ` [PATCH 41/73] preprocessor: Add support for __has_include and __has_include_next Bart Van Assche
2026-11-09 20:32 ` [PATCH 42/73] c23: Add support for static_assert, alignas, alignof, thread_local Bart Van Assche
2026-11-09 20:32 ` [PATCH 43/73] c23: Add support for bool, true, and false keywords Bart Van Assche
2026-11-09 20:32 ` [PATCH 44/73] c23: Add support for nullptr and nullptr_t Bart Van Assche
2026-11-09 20:32 ` [PATCH 45/73] c23: Add support for digit separators in numeric literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 46/73] c23: Support unnamed parameters in function definitions Bart Van Assche
2026-11-09 20:32 ` [PATCH 47/73] c23: Support variadic functions without named parameters Bart Van Assche
2026-11-09 20:32 ` [PATCH 48/73] c23: Support labels before declarations and at block ends Bart Van Assche
2026-11-09 20:32 ` [PATCH 49/73] c23: Support auto type inference Bart Van Assche
2026-11-09 20:32 ` [PATCH 50/73] c23: Support constexpr object specifier Bart Van Assche
2026-11-09 20:32 ` [PATCH 51/73] c23: Support enumerations with fixed underlying types Bart Van Assche
2026-11-09 20:32 ` [PATCH 52/73] c23: Support standard [[]] attribute syntax Bart Van Assche
2026-11-09 20:32 ` [PATCH 53/73] preprocessor: Add support for __has_c_attribute Bart Van Assche
2026-11-09 20:32 ` [PATCH 54/73] c23: Support empty initializer braces {} Bart Van Assche
2026-11-09 20:32 ` [PATCH 55/73] preprocessor: Add support for __has_embed Bart Van Assche
2026-11-09 20:32 ` [PATCH 56/73] preprocessor: Add support for #embed directive Bart Van Assche
2026-11-09 20:32 ` [PATCH 57/73] c23: Add support for u8 character constants and string literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 58/73] preprocessor: Add support for __VA_OPT__ Bart Van Assche
2026-11-09 20:32 ` Bart Van Assche [this message]
2026-11-09 20:32 ` [PATCH 60/73] c23: Support storage-class specifiers in compound literals Bart Van Assche
2026-11-09 20:32 ` [PATCH 61/73] c23: Add support for _BitInt(N) Bart Van Assche
2026-11-09 20:32 ` [PATCH 62/73] enum: Support machine mode attributes on enumeration types Bart Van Assche
2026-11-09 20:32 ` [PATCH 63/73] enum: Support __attribute__((packed)) " Bart Van Assche
2026-11-09 20:32 ` [PATCH 64/73] expand: Ignore top-level non-array address space in compare_types() Bart Van Assche
2026-11-09 20:32 ` [PATCH 65/73] builtin: Support __builtin_infer_alloc_token() as a size_t ICE Bart Van Assche
2026-11-09 20:32 ` [PATCH 66/73] builtin: Add support for Linux kernel compiler builtins Bart Van Assche
2026-11-09 20:32 ` [PATCH 67/73] builtin: Add support for __builtin_has_attribute() Bart Van Assche
2026-11-09 20:32 ` [PATCH 68/73] cleanup: Support __attribute__((cleanup(...))) in linearize and -Wcontext Bart Van Assche
2026-11-09 20:32 ` [PATCH 69/73] builtin: Do not evaluate __builtin_clz(0) and __builtin_ctz(0) Bart Van Assche
2026-11-09 20:32 ` [PATCH 70/73] pre-process: Support long token and string expansions dynamically Bart Van Assche
2026-11-09 20:32 ` [PATCH 71/73] x86: Undefine conflicting bitness macros when parsing -m flags Bart Van Assche
2026-11-09 20:32 ` [PATCH 72/73] evaluate: Accept conditional expressions with only one void side Bart Van Assche
2026-11-09 20:32 ` [PATCH 73/73] ci: Add Linux kernel GitHub Actions workflow and build script Bart Van Assche
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261109203259.362845-60-bvanassche@acm.org \
--to=bvanassche@acm.org \
--cc=linux-sparse@vger.kernel.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox