Here is some additional stress testing of nested macros where the expansion
of macros involves commas, (and whether those commas are interpreted as
argument separators or not in subsequent function-like macro calls).

Credit to the GCC documentation that directed my attention toward this issue:

        https://gcc.gnu.org/onlinedocs/gcc-3.2/cpp/Argument-Prescan.html

Fixing the bug required only removing code from glcpp. When first testing the
details of expansions involving commas, I had come to the mistaken conclusion
that an expanded comma should never be treated as an argument separator, (so
had introduced the rather ugly COMMA_FINAL token to represent this).

In fact, an expanded comma should be treated as a separator, (as tested here),
and this treatment can be avoided by judicious use of parentheses (as also
tested here).

With this simple removal of the COMMA_FINAL token, the behavior of glcpp
matches that of gcc's preprocessor for all of these hairy cases.
---
 src/glsl/glcpp/glcpp-parse.y                       | 13 +-----------
 .../tests/039-func-arg-obj-macro-with-comma.c      | 21 ++++++++++++++++++++
 .../039-func-arg-obj-macro-with-comma.c.expected   | 23 ++++++++++++++++++++++
 3 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
index 82fba20..8cf9258 100644
--- a/src/glsl/glcpp/glcpp-parse.y
+++ b/src/glsl/glcpp/glcpp-parse.y
@@ -178,7 +178,7 @@ add_builtin_define(glcpp_parser_t *parser, const char 
*name, int value);
        /* We use HASH_TOKEN, DEFINE_TOKEN and VERSION_TOKEN (as opposed to
          * HASH, DEFINE, and VERSION) to avoid conflicts with other symbols,
          * (such as the <HASH> and <DEFINE> start conditions in the lexer). */
-%token COMMA_FINAL DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN 
FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR IF IFDEF IFNDEF LINE 
PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER 
INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS 
MINUS_MINUS
+%token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER 
OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR IF IFDEF IFNDEF LINE PRAGMA UNDEF 
VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING 
LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS
 %token PASTE
 %type <ival> INTEGER operator SPACE integer_constant
 %type <expression_value> expression
@@ -1161,9 +1161,6 @@ _token_print (char **out, size_t *len, token_t *token)
         case MINUS_MINUS:
                ralloc_asprintf_rewrite_tail (out, len, "--");
                break;
-       case COMMA_FINAL:
-               ralloc_asprintf_rewrite_tail (out, len, ",");
-               break;
        case DEFINED:
                ralloc_asprintf_rewrite_tail (out, len, "defined");
                break;
@@ -1846,14 +1843,6 @@ _glcpp_parser_expand_node (glcpp_parser_t *parser,
 
        /* We only expand identifiers */
        if (token->type != IDENTIFIER) {
-               /* We change any COMMA into a COMMA_FINAL to prevent
-                * it being mistaken for an argument separator
-                * later. */
-               if (token->type == ',') {
-                       token->type = COMMA_FINAL;
-                       token->value.ival = COMMA_FINAL;
-               }
-
                return NULL;
        }
 
diff --git a/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c 
b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c
index 0f7fe63..a7c053b 100644
--- a/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c
+++ b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c
@@ -1,3 +1,24 @@
+/* This works. */
 #define foo(a) (a)
 #define bar two,words
 foo(bar)
+
+/* So does this. */
+#define foo2(a,b) (a separate b)
+#define foo2_wrap(a) foo2(a)
+foo2_wrap(bar)
+
+/* But this generates an error. */
+#define foo_wrap(a) foo(a)
+foo_wrap(bar)
+
+/* Adding parentheses to foo_wrap fixes it. */
+#define foo_wrap_parens(a) foo((a))
+foo_wrap_parens(bar)
+
+/* As does adding parentheses to bar */
+#define bar_parens (two,words)
+foo_wrap(bar_parens)
+foo_wrap_parens(bar_parens)
+
+
diff --git a/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected 
b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected
index 8a15397..4cc7953 100644
--- a/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected
+++ b/src/glsl/glcpp/tests/039-func-arg-obj-macro-with-comma.c.expected
@@ -1,3 +1,26 @@
+0:12(21): preprocessor error: Error: macro foo invoked with 2 arguments 
(expected 1)
+
+ 
 
 
 (two,words)
+
+ 
+
+
+(two separate words)
+
+ 
+
+foo(two,words)
+
+ 
+
+((two,words))
+
+ 
+
+((two,words))
+(((two,words)))
+
+
-- 
2.0.0

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to