linux-sparse.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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 46/73] c23: Support unnamed parameters in function definitions
Date: Mon,  9 Nov 2026 12:32:32 -0800	[thread overview]
Message-ID: <20261109203259.362845-47-bvanassche@acm.org> (raw)
In-Reply-To: <20261109203259.362845-1-bvanassche@acm.org>

Allow function definitions to omit parameter names in C23 mode per ISO
C23 6.9.1 while rejecting unnamed parameters as an error in pre-C23
standards:
- Check for missing type specifiers before skipping local scope binding
  for unnamed parameters.
- Preserve argument side effects when inlining calls to functions with
  unnamed parameters without triggering unreplaced-symbol warnings.
- Advance parameter slot indices across unnamed parameters during
  linearization so subsequent named parameters keep their ABI slot index.
- Reject qualified, named, or multi-parameter uses of 'void'.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 inline.c                                 |  6 ++-
 linearize.c                              |  8 ++--
 parse.c                                  | 27 +++++++++-----
 validation/c23-unnamed-params-error.c    | 27 ++++++++++++++
 validation/c23-unnamed-params-pedantic.c | 12 ++++++
 validation/c23-unnamed-params.c          | 47 ++++++++++++++++++++++++
 validation/linear/c23-unnamed-params.c   | 27 ++++++++++++++
 7 files changed, 141 insertions(+), 13 deletions(-)
 create mode 100644 validation/c23-unnamed-params-error.c
 create mode 100644 validation/c23-unnamed-params-pedantic.c
 create mode 100644 validation/c23-unnamed-params.c
 create mode 100644 validation/linear/c23-unnamed-params.c

diff --git a/inline.c b/inline.c
index d94fba807d19..d3f27952138b 100644
--- a/inline.c
+++ b/inline.c
@@ -631,7 +631,7 @@ int inline_function(struct expression *expr, struct symbol *sym)
 	FOR_EACH_PTR(expr->args, arg) {
 		struct symbol *a = alloc_symbol(arg->pos, SYM_NODE);
 
-		if (name) {
+		if (name && name->ident) {
 			*a = *name;
 			a->bb_target = NULL;
 			a->pseudo = NULL;
@@ -639,6 +639,10 @@ int inline_function(struct expression *expr, struct symbol *sym)
 			add_symbol(&fn_symbol_list, a);
 			a->initializer = arg;
 			add_symbol(&arg_decl, a);
+		} else if (name) {
+			*a = *name;
+			a->initializer = arg;
+			add_symbol(&arg_decl, a);
 		} else {
 			// This may create a node of a node but it will
 			// be resolved later when the corresponding
diff --git a/linearize.c b/linearize.c
index 422cee820ddb..4179aea03af1 100644
--- a/linearize.c
+++ b/linearize.c
@@ -2607,12 +2607,14 @@ static struct entrypoint *linearize_fn(struct symbol *sym, struct symbol *base_t
 	add_one_insn(ep, entry);
 	ep->entry = entry;
 
-	concat_symbol_list(base_type->arguments, &ep->syms);
-
 	/* FIXME!! We should do something else about varargs.. */
 	i = 0;
 	FOR_EACH_PTR(base_type->arguments, arg) {
-		linearize_argument(ep, arg, ++i);
+		++i;
+		if (!arg->ident)
+			continue;
+		add_symbol(&ep->syms, arg);
+		linearize_argument(ep, arg, i);
 	} END_FOR_EACH_PTR(arg);
 
 	result = linearize_fn_statement(ep, stmt);
diff --git a/parse.c b/parse.c
index 5e526b0cc840..6af5bfba2392 100644
--- a/parse.c
+++ b/parse.c
@@ -1702,6 +1702,8 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta
 				specifier_conflict(token->pos,
 						   seen & s->op->test,
 						   token->ident);
+				ctx->ctype.base_type = &bad_ctype;
+				seen |= Set_S;
 				break;
 			}
 			seen |= s->op->set;
@@ -2772,10 +2774,12 @@ static struct token *parameter_type_list(struct token *token, struct symbol *fn)
 		sym = alloc_symbol(token->pos, SYM_NODE);
 		token = parameter_declaration(token, sym);
 		if (sym->ctype.base_type == &void_ctype) {
-			/* Special case: (void) */
-			if (!*list && !sym->ident)
+			/* Special case: sole unnamed unqualified (void) */
+			if (!*list && !sym->ident && match_op(token, ')') &&
+			    !(sym->ctype.modifiers & (MOD_QUALIFIER | MOD_STORAGE | MOD_ATOMIC)))
 				break;
-			warning(token->pos, "void parameter");
+			sparse_error(sym->pos, "'void' must be the only parameter");
+			sym->ctype.base_type = &bad_ctype;
 		}
 		add_symbol(list, sym);
 		if (!match_op(token, ','))
@@ -2917,18 +2921,23 @@ struct token *initializer(struct expression **tree, struct token *token)
 
 static void declare_argument(struct symbol *sym, struct symbol *fn)
 {
-	if (!sym->ident) {
-		sparse_error(sym->pos, "no identifier for function argument");
-		return;
-	}
 	if (sym->ctype.base_type == &incomplete_ctype) {
 		sym->ctype.base_type = &int_ctype;
 
 		if (Wimplicit_int) {
-			sparse_error(sym->pos, "missing type declaration for parameter '%s'",
-				show_ident(sym->ident));
+			if (sym->ident)
+				sparse_error(sym->pos, "missing type declaration for parameter '%s'",
+					show_ident(sym->ident));
+			else
+				sparse_error(sym->pos, "missing type declaration for parameter");
 		}
 	}
+	if (!sym->ident) {
+		if (standard < STANDARD_C23 && sym->ctype.base_type != &bad_ctype)
+			sparse_error(sym->pos,
+				     "omitting parameter name in function definition is a C23 feature");
+		return;
+	}
 	bind_symbol(sym, sym->ident, NS_SYMBOL);
 }
 
diff --git a/validation/c23-unnamed-params-error.c b/validation/c23-unnamed-params-error.c
new file mode 100644
index 000000000000..6630f96b53b5
--- /dev/null
+++ b/validation/c23-unnamed-params-error.c
@@ -0,0 +1,27 @@
+static void f_implicit(const)
+{
+}
+
+static void f_void1(void, int)
+{
+}
+
+static void f_void2(int, void)
+{
+}
+
+static void f_cvoid(const void)
+{
+}
+
+/*
+ * check-name: c23-unnamed-params-error
+ * check-command: sparse -std=c23 $file
+ *
+ * check-error-start
+c23-unnamed-params-error.c:1:24: error: missing type declaration for parameter
+c23-unnamed-params-error.c:5:21: error: 'void' must be the only parameter
+c23-unnamed-params-error.c:9:26: error: 'void' must be the only parameter
+c23-unnamed-params-error.c:13:21: error: 'void' must be the only parameter
+ * check-error-end
+ */
diff --git a/validation/c23-unnamed-params-pedantic.c b/validation/c23-unnamed-params-pedantic.c
new file mode 100644
index 000000000000..aa2a204628fe
--- /dev/null
+++ b/validation/c23-unnamed-params-pedantic.c
@@ -0,0 +1,12 @@
+static void f1(int)
+{
+}
+
+/*
+ * check-name: c23-unnamed-params-pedantic
+ * check-command: sparse -std=c11 $file
+ *
+ * check-error-start
+c23-unnamed-params-pedantic.c:1:16: error: omitting parameter name in function definition is a C23 feature
+ * check-error-end
+ */
diff --git a/validation/c23-unnamed-params.c b/validation/c23-unnamed-params.c
new file mode 100644
index 000000000000..ddecb8e9e0b9
--- /dev/null
+++ b/validation/c23-unnamed-params.c
@@ -0,0 +1,47 @@
+static void f1(int)
+{
+}
+
+static void f2(int, double)
+{
+}
+
+static int f3(int a, double, int b)
+{
+	return a + b;
+}
+
+static void f4(void (*)(int))
+{
+}
+
+static void f5(int [static 4], const int)
+{
+}
+
+static inline int inl_unnamed(int a, int, int b)
+{
+	return a + b;
+}
+
+static int bump(int *cnt)
+{
+	return (*cnt)++;
+}
+
+static int test_calls(void)
+{
+	int arr[4] = { 1, 2, 3, 4 };
+	int cnt = 0;
+
+	f1(1);
+	f2(2, 3.0);
+	f4(f1);
+	f5(arr, 7);
+	return f3(10, 0.5, 20) + inl_unnamed(1, bump(&cnt), 2) + cnt;
+}
+
+/*
+ * check-name: c23-unnamed-params
+ * check-command: sparse -std=c23 -pedantic $file
+ */
diff --git a/validation/linear/c23-unnamed-params.c b/validation/linear/c23-unnamed-params.c
new file mode 100644
index 000000000000..add966d3ea71
--- /dev/null
+++ b/validation/linear/c23-unnamed-params.c
@@ -0,0 +1,27 @@
+int f3(int a, double, int b);
+int f3(int a, double, int b)
+{
+	return a + b;
+}
+
+static inline int inl(int a, int, int b)
+{
+	return a + b;
+}
+
+extern int side_effect(void);
+
+int caller(void);
+int caller(void)
+{
+	return inl(10, side_effect(), 20);
+}
+
+/*
+ * check-name: linear-c23-unnamed-params
+ * check-command: test-linearize -m64 -std=c23 $file
+ *
+ * check-output-ignore
+ * check-output-contains: add\\.32 *%r[0-9]* <- %arg1, %arg3
+ * check-output-contains: call\\.32 *%r[0-9]* <- side_effect
+ */

  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 ` Bart Van Assche [this message]
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 ` [PATCH 59/73] c23: Treat empty parameter list () as (void) and reject K&R functions Bart Van Assche
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-47-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;
as well as URLs for NNTP newsgroup(s).