Fix bug (and add tests) for a function-like macro defined as itself.
This case worked previously, but broke in the recent rewrite of
function- like macro expansion. The recursion was still terminated
correctly, but any parenthesized expression after the macro name was
still being swallowed even though the identifier was not being
expanded as a macro.
The fix is to notice earlier that the identifier is an
already-expanding macro. We let the lexer know this through the
classify_token function so that an already-expanding macro is lexed as
an identifier, not a FUNC_MACRO.
diff --git a/glcpp-parse.y b/glcpp-parse.y
index 9f1075a..8dc0748 100644
--- a/glcpp-parse.y
+++ b/glcpp-parse.y
@@ -427,6 +427,22 @@
talloc_free (parser);
}
+static int
+glcpp_parser_is_expanding (glcpp_parser_t *parser, const char *member)
+{
+ expansion_node_t *node;
+
+ for (node = parser->expansions; node; node = node->next) {
+ if (node->macro &&
+ strcmp (node->macro->identifier, member) == 0)
+ {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
token_class_t
glcpp_parser_classify_token (glcpp_parser_t *parser,
const char *identifier,
@@ -457,6 +473,12 @@
if (macro == NULL)
return TOKEN_CLASS_IDENTIFIER;
+ /* Don't consider this a macro if we are already actively
+ * expanding this macro. */
+ if (glcpp_parser_is_expanding (parser, identifier))
+ return TOKEN_CLASS_IDENTIFIER;
+
+ /* Definitely a macro. Just need to check if it's function-like. */
if (macro->is_function)
return TOKEN_CLASS_FUNC_MACRO;
else
@@ -580,37 +602,6 @@
talloc_free (node);
}
-int
-glcpp_parser_is_expanding (glcpp_parser_t *parser, const char *member)
-{
- expansion_node_t *node;
-
- for (node = parser->expansions; node; node = node->next) {
- if (node->macro &&
- strcmp (node->macro->identifier, member) == 0)
- {
- return 1;
- }
- }
-
- return 0;
-}
-
-static void
-_expand_macro (glcpp_parser_t *parser,
- const char *token,
- macro_t *macro,
- argument_list_t *arguments)
-{
- /* Don't recurse if we're already actively expanding this token. */
- if (glcpp_parser_is_expanding (parser, token)) {
- printf ("%s", token);
- return;
- }
-
- glcpp_parser_push_expansion_macro (parser, macro, arguments);
-}
-
void
_expand_object_macro (glcpp_parser_t *parser, const char *identifier)
{
@@ -618,8 +609,9 @@
macro = hash_table_find (parser->defines, identifier);
assert (! macro->is_function);
+ assert (! glcpp_parser_is_expanding (parser, identifier));
- _expand_macro (parser, identifier, macro, NULL);
+ glcpp_parser_push_expansion_macro (parser, macro, NULL);
}
void
@@ -631,6 +623,7 @@
macro = hash_table_find (parser->defines, identifier);
assert (macro->is_function);
+ assert (! glcpp_parser_is_expanding (parser, identifier));
if (_argument_list_length (arguments) !=
_string_list_length (macro->parameters))
@@ -643,5 +636,5 @@
return;
}
- _expand_macro (parser, identifier, macro, arguments);
+ glcpp_parser_push_expansion_macro (parser, macro, arguments);
}