Consider this test case:
#define EMPTY
int foo = 1+EMPTY+4;
The expression should compile as the sequence of tokens 1, PLUS,
UNARY_POSITIVE, 4. But glcpp has been failing for this case since it
results in the string "1++4" which a compiler correctly sees as a
syntax error, (1, POST_INCREMENT, 4).
We fix this by changing any macro with an empty definition to result
in a single SPACE token rather than nothing. This then gives "1+ +4"
which compiles correctly.
This commit does touch up the two existing test cases which already
have empty macros, (to add the space to the expected result).
It also adds a new test case to exercise the above scenario.
return FUNCTION_STATUS_SUCCESS;
}
return FUNCTION_STATUS_SUCCESS;
}
+static token_list_t *
+_token_list_create_with_one_space (void *ctx)
+{
+ token_list_t *list;
+ token_t *space;
+
+ list = _token_list_create (ctx);
+ space = _token_create_ival (list, SPACE, SPACE);
+ _token_list_append (list, space);
+
+ return list;
+}
+
/* This is a helper function that's essentially part of the
* implementation of _glcpp_parser_expand_node. It shouldn't be called
* except for by that function.
/* This is a helper function that's essentially part of the
* implementation of _glcpp_parser_expand_node. It shouldn't be called
* except for by that function.
+ /* Replace a macro defined as empty with a SPACE token. */
if (macro->replacements == NULL) {
talloc_free (arguments);
if (macro->replacements == NULL) {
talloc_free (arguments);
- return _token_list_create (parser);
+ return _token_list_create_with_one_space (parser);
}
if (! ((_argument_list_length (arguments) ==
}
if (! ((_argument_list_length (arguments) ==
*
* Otherwise, returns the token list that results from the expansion
* and sets *last to the last node in the list that was consumed by
*
* Otherwise, returns the token list that results from the expansion
* and sets *last to the last node in the list that was consumed by
- * the expansion. Specificallty, *last will be set as follows:
+ * the expansion. Specifically, *last will be set as follows:
*
* As 'node' in the case of object-like macro expansion.
*
*
* As 'node' in the case of object-like macro expansion.
*
+ /* Replace a macro defined as empty with a SPACE token. */
if (macro->replacements == NULL)
if (macro->replacements == NULL)
- return _token_list_create (parser);
+ return _token_list_create_with_one_space (parser);
return _token_list_copy (parser, macro->replacements);
}
return _token_list_copy (parser, macro->replacements);
}
--- /dev/null
+#define empty
+<empty<
+<empty=
+>empty>
+>empty=
+=empty=
+!empty=
+&empty&
+|empty|
++empty+
+-empty-
--- /dev/null
+
+< <
+< =
+> >
+> =
+= =
+! =
+& &
+| |
++ +
+- -
+