glcpp: fix paste within macro function expansion
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

Note the tests added in 89cd6df034 were wrong (confirmed in gcc)
I've updated them to the expected outcome and enabled the paste
test from 475222b022.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/13863
Fixes: d5cd40343f ("Expand macro arguments before performing argument substitution.")

Reviewed-by: Eric R. Smith <eric.smith@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40062>
This commit is contained in:
Timothy Arceri 2026-02-24 13:19:06 +11:00 committed by Marge Bot
parent 35eda3f3e2
commit 5f37490855
4 changed files with 30 additions and 7 deletions

View file

@ -1930,6 +1930,7 @@ _glcpp_parser_expand_function(glcpp_parser_t *parser, token_node_t *node,
/* Perform argument substitution on the replacement list. */
substituted = _token_list_create(parser);
bool prev_paste_token = false;
for (node = macro->replacements->head; node; node = node->next) {
if (node->token->type == IDENTIFIER &&
_string_list_contains(macro->parameters, node->token->value.str,
@ -1941,7 +1942,26 @@ _glcpp_parser_expand_function(glcpp_parser_t *parser, token_node_t *node,
if (argument->head) {
token_list_t *expanded_argument;
expanded_argument = _token_list_copy(parser, argument);
_glcpp_parser_expand_token_list(parser, expanded_argument, mode);
/* From the C99 spec Section 10.3.1 (Argument substitution):
* "After the arguments for the invocation of a function-like
* macro have been identified, argument substitution takes
* place. A parameter in the replacement list, unless preceded
* by a # or ## preprocessing token or followed by a ##
* preprocessing token (see below), is replaced by the
* corresponding argument after all macros contained therein
* have been expanded."
*/
/* Look ahead for a PASTE token, skipping space. */
token_node_t *next_non_space = node->next;
while (next_non_space && next_non_space->token->type == SPACE)
next_non_space = next_non_space->next;
if (!prev_paste_token &&
(!next_non_space || next_non_space->token->type != PASTE))
_glcpp_parser_expand_token_list(parser, expanded_argument, mode);
_token_list_append_list(substituted, expanded_argument);
} else {
token_t *new_token;
@ -1953,6 +1973,9 @@ _glcpp_parser_expand_function(glcpp_parser_t *parser, token_node_t *node,
} else {
_token_list_append(parser, substituted, node->token);
}
if (node->token->type != SPACE)
prev_paste_token = node->token->type == PASTE;
}
/* Implement token pasting. */

View file

@ -1,7 +1,7 @@
4. HTTP code for Not Found: 404
5. Hexadecimal for 20560: 5050
6: Zip code for Nortonville, KS: 66060
7. James Bond, as a number: 007
4. HTTP code for Not Found: __LINE____FILE____LINE__
5. Hexadecimal for 20560: __LINE____FILE____LINE____FILE__
6: Zip code for Nortonville, KS: __LINE____LINE____FILE____LINE____FILE__
7. James Bond, as a number: __FILE____FILE____LINE__

View file

@ -12,5 +12,5 @@ A(r, s)
B(r, s)
C(r)s
A(a, b)
//B(a, b) // not working yet; gcc and clang give `ab`, we give `xaxb`
B(a, b)
C(a)b

View file

@ -12,5 +12,5 @@ r s
rs
r s
xa xb
ab
xa xb