[PATCH 5/6] saner collect_arg() code generation

Al Viro <[email protected]> Tue, 31 Mar 2026 09:07:28 +0100
Newsgroups org.kernel.vger.linux-sparse
Message-ID <[email protected]>
1) gently coax gcc code generator away from screwing the bitfields
handling it is so keen to do - pass struct position from the caller
by value, with .newline already cleared (with inlined helper that
does trimming), do *not* let collect_arg() see that it's always
setting ->pos.newline to 0 (otherwise the FPOS tries to peel the damn
thing apart, turning mask-then-or into a bleeding horror).

2) get rid of 'vararg' checks for commas by changing the way we
keep track of nesting parentheses - instead of
	number of '(' - number of ')'
use
	2 * number of '(' - 2 * number of ')' + vararg
That still recognizes the closing parenthesis of argument list
(counter gets negative there, vararg or no vararg) and it does
recognize an argument-terminating comma without having to look
at 'vararg' - just check if counter is zero.
Reduces spills nicely.

3) do *not* use eof_token() as loop termination condition, compare
token_type() with TOKEN_EOF instead.  Yes, it's faster to compare
the pointer with constant instead, but it is *not* going to match
that unless we have an unterminated argument list and we are going
to check for TOKEN_STREAM{BEGIN,END} immediately afterwards anyway,
with the same "leave the loop now" on match, so these checks combine
nicely.

Signed-off-by: Al Viro <[email protected]>
---
 pre-process.c | 44 ++++++++++++++++++++++++++------------------
 1 file changed, 26 insertions(+), 18 deletions(-)

diff --git a/pre-process.c b/pre-process.c
index e62d6379..a368b9ed 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -255,42 +255,41 @@ static void expand_list(struct token **list)
 
 static void preprocessor_line(struct stream *stream, struct token **line);
 
-static struct token *collect_arg(struct token *prev, bool vararg, const struct position *pos)
+static struct token *collect_arg(struct token *prev, bool vararg, struct position pos)
 {
 	struct stream *stream = input_streams + prev->pos.stream;
 	struct token **p = &prev->next;
 	struct token *next;
-	int nesting = 0;
+	int nesting = vararg;
 
-	while (!eof_token(next = scan_next(p))) {
+	while (1) {
+		next = scan_next(p);
+		if (token_type(next) == TOKEN_STREAMBEGIN ||
+		    token_type(next) == TOKEN_STREAMEND ||
+		    token_type(next) == TOKEN_EOF)
+			break;
 		if (token_type(next) == TOKEN_DIRECTIVE) {
 			preprocessor_line(stream, p);
 			__free_token(next);	/* Free the '#' token */
 			continue;
 		}
-		switch (token_type(next)) {
-		case TOKEN_STREAMEND:
-		case TOKEN_STREAMBEGIN:
-			*p = &eof_token_entry;
-			return next;
-		}
 		if (false_nesting) {
 			*p = next->next;
 			__free_token(next);
 			continue;
 		}
 		if (match_op(next, '(')) {
-			nesting++;
+			nesting += 2;
 		} else if (match_op(next, ')')) {
-			if (!nesting--)
+			if ((nesting -= 2) < 0)
 				break;
-		} else if (match_op(next, ',') && !nesting && !vararg) {
+		} else if (match_op(next, ',') && !nesting) {
 			break;
 		}
-		next->pos.stream = pos->stream;
-		next->pos.line = pos->line;
-		next->pos.pos = pos->pos;
-		next->pos.newline = 0;
+		next->pos.stream = pos.stream;
+		next->pos.line = pos.line;
+		next->pos.pos = pos.pos;
+		next->pos.newline = pos.newline;
 		p = &next->next;
 	}
 	*p = &eof_token_entry;
@@ -305,6 +304,15 @@ struct arg {
 	struct token *arg[3];
 };
 
+static inline struct position location(const struct position *p)
+{
+	return (struct position) {
+		.stream = p->stream,
+		.line = p->line,
+		.pos = p->pos
+	};
+}
+
 static int collect_arguments(struct token *what, int fixed, bool vararg, struct arg *args)
 {
 	struct token *start = scan_next(&what->next);
@@ -317,7 +325,7 @@ static int collect_arguments(struct token *what, int fixed, bool vararg, struct
 	if (!match_op(start, '('))
 		return 0;
 	for (commas = 0; commas < fixed; commas++) {
-		next = collect_arg(start, false, &what->pos);
+		next = collect_arg(start, false, location(&what->pos));
 		if (token_type(next) != TOKEN_SPECIAL)
 			goto Eclosing;
 		args[commas + 1].arg[ARG_QUOTED] = start->next;
@@ -329,7 +337,7 @@ static int collect_arguments(struct token *what, int fixed, bool vararg, struct
 		start = next;
 	}
 	if (commas == fixed) {
-		next = collect_arg(start, true, &what->pos);
+		next = collect_arg(start, true, location(&what->pos));
 		if (token_type(next) != TOKEN_SPECIAL)
 			goto Eclosing;
 		v = start->next;
-- 
2.47.3