glcpp: fix paste within macro function expansion

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>
(cherry picked from commit 5f37490855)

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41269>
This commit is contained in:
Timothy Arceri 2026-02-24 13:19:06 +11:00 committed by Eric Engestrom
parent 8a70e47d22
commit c0c2df0d0e
5 changed files with 31 additions and 8 deletions

View file

@ -3094,7 +3094,7 @@
"description": "glcpp: fix paste within macro function expansion",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "d5cd40343f4a83d3270cb87ef38e85dcb9682e8c",
"notes": null

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;
}
/* After argument substitution, and before further expansion

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