From 58f2b876425a1f0926d5715188b985562c82c040 Mon Sep 17 00:00:00 2001 From: Timothy Arceri Date: Tue, 24 Feb 2026 13:19:06 +1100 Subject: [PATCH] glcpp: fix paste within macro function expansion Note the tests added in 89cd6df03481 were wrong (confirmed in gcc) I've updated them to the expected outcome and enabled the paste test from 475222b0224c. Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/13863 Fixes: d5cd40343f4a ("Expand macro arguments before performing argument substitution.") Reviewed-by: Eric R. Smith (cherry picked from commit 5f374908555f437ee5945a7d191d1cac6da3dfe2) Part-of: --- .pick_status.json | 2 +- src/compiler/glsl/glcpp/glcpp-parse.y | 25 ++++++++++++++++++- .../tests/114-paste-integer-tokens.c.expected | 8 +++--- .../150-token-accidental-concatenation.c | 2 +- ...-token-accidental-concatenation.c.expected | 2 +- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 17b4fecb84c..62cb42a57f0 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -194,7 +194,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 diff --git a/src/compiler/glsl/glcpp/glcpp-parse.y b/src/compiler/glsl/glcpp/glcpp-parse.y index e6758a6ab98..459856ddef1 100644 --- a/src/compiler/glsl/glcpp/glcpp-parse.y +++ b/src/compiler/glsl/glcpp/glcpp-parse.y @@ -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 diff --git a/src/compiler/glsl/glcpp/tests/114-paste-integer-tokens.c.expected b/src/compiler/glsl/glcpp/tests/114-paste-integer-tokens.c.expected index 5bc14befa67..45f2115491a 100644 --- a/src/compiler/glsl/glcpp/tests/114-paste-integer-tokens.c.expected +++ b/src/compiler/glsl/glcpp/tests/114-paste-integer-tokens.c.expected @@ -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__ diff --git a/src/compiler/glsl/glcpp/tests/150-token-accidental-concatenation.c b/src/compiler/glsl/glcpp/tests/150-token-accidental-concatenation.c index 9e061b68a8c..ae85bebb2af 100644 --- a/src/compiler/glsl/glcpp/tests/150-token-accidental-concatenation.c +++ b/src/compiler/glsl/glcpp/tests/150-token-accidental-concatenation.c @@ -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 diff --git a/src/compiler/glsl/glcpp/tests/150-token-accidental-concatenation.c.expected b/src/compiler/glsl/glcpp/tests/150-token-accidental-concatenation.c.expected index cdaf5949732..bb1a9326308 100644 --- a/src/compiler/glsl/glcpp/tests/150-token-accidental-concatenation.c.expected +++ b/src/compiler/glsl/glcpp/tests/150-token-accidental-concatenation.c.expected @@ -12,5 +12,5 @@ r s rs r s xa xb - +ab xa xb