Add support for __VA_OPT__

C++2a adds a "__VA_OPT__" feature that can be used to control the
pesky "," emission when the final (variable) argument of a variadic
macro is empty.  This patch implements this feature for gdb.  (A patch
to implement it for gcc is pending.)

gdb/ChangeLog
2017-09-27  Tom Tromey  <tom@tromey.com>

	* macroexp.c (get_next_token_for_substitution): New function.
	(substitute_args): Call it.  Check for __VA_OPT__.

gdb/testsuite/ChangeLog
2017-09-27  Tom Tromey  <tom@tromey.com>

	* gdb.base/macscp.exp: Add __VA_OPT__ tests.
This commit is contained in:
Tom Tromey 2017-09-17 20:36:41 -06:00
parent 1948519604
commit a9bbfbd85f
4 changed files with 157 additions and 10 deletions

View File

@ -1,3 +1,8 @@
2017-09-27 Tom Tromey <tom@tromey.com>
* macroexp.c (get_next_token_for_substitution): New function.
(substitute_args): Call it. Check for __VA_OPT__.
2017-09-26 Walfred Tedeschi <walfred.tedeschi@intel.com>
Pedro Alves <palves@redhat.com>

View File

@ -946,6 +946,30 @@ find_parameter (const struct macro_buffer *tok,
return -1;
}
/* Helper function for substitute_args that gets the next token and
updates the passed-in state variables. */
static void
get_next_token_for_substitution (struct macro_buffer *replacement_list,
struct macro_buffer *token,
char **start,
struct macro_buffer *lookahead,
char **lookahead_start,
int *lookahead_valid,
bool *keep_going)
{
if (!*lookahead_valid)
*keep_going = false;
else
{
*keep_going = true;
*token = *lookahead;
*start = *lookahead_start;
*lookahead_start = replacement_list->text;
*lookahead_valid = get_token (lookahead, replacement_list);
}
}
/* Given the macro definition DEF, being invoked with the actual
arguments given by ARGC and ARGV, substitute the arguments into the
replacement list, and store the result in DEST.
@ -996,8 +1020,64 @@ substitute_args (struct macro_buffer *dest,
lookahead_rl_start = replacement_list.text;
lookahead_valid = get_token (&lookahead, &replacement_list);
for (;;)
/* __VA_OPT__ state variable. The states are:
0 - nothing happening
1 - saw __VA_OPT__
>= 2 in __VA_OPT__, the value encodes the parenthesis depth. */
unsigned vaopt_state = 0;
for (bool keep_going = true;
keep_going;
get_next_token_for_substitution (&replacement_list,
&tok,
&original_rl_start,
&lookahead,
&lookahead_rl_start,
&lookahead_valid,
&keep_going))
{
bool token_is_vaopt = (tok.len == 10
&& strncmp (tok.text, "__VA_OPT__", 10) == 0);
if (vaopt_state > 0)
{
if (token_is_vaopt)
error (_("__VA_OPT__ cannot appear inside __VA_OPT__"));
else if (tok.len == 1 && tok.text[0] == '(')
{
++vaopt_state;
/* We just entered __VA_OPT__, so don't emit this
token. */
continue;
}
else if (vaopt_state == 1)
error (_("__VA_OPT__ must be followed by an open parenthesis"));
else if (tok.len == 1 && tok.text[0] == ')')
{
--vaopt_state;
if (vaopt_state == 1)
{
/* Done with __VA_OPT__. */
vaopt_state = 0;
/* Don't emit. */
continue;
}
}
/* If __VA_ARGS__ is empty, then drop the contents of
__VA_OPT__. */
if (argv[argc - 1].len == 0)
continue;
}
else if (token_is_vaopt)
{
if (!is_varargs)
error (_("__VA_OPT__ is only valid in a variadic macro"));
vaopt_state = 1;
/* Don't emit this token. */
continue;
}
/* Just for aesthetics. If we skipped some whitespace, copy
that to DEST. */
if (tok.text > original_rl_start)
@ -1157,16 +1237,10 @@ substitute_args (struct macro_buffer *dest,
if (! substituted)
append_tokens_without_splicing (dest, &tok);
}
if (! lookahead_valid)
break;
tok = lookahead;
original_rl_start = lookahead_rl_start;
lookahead_rl_start = replacement_list.text;
lookahead_valid = get_token (&lookahead, &replacement_list);
}
if (vaopt_state > 0)
error (_("Unterminated __VA_OPT__"));
}

View File

@ -1,3 +1,7 @@
2017-09-27 Tom Tromey <tom@tromey.com>
* gdb.base/macscp.exp: Add __VA_OPT__ tests.
2017-09-26 Thomas Preud'homme <thomas.preudhomme@arm.com>
Pedro Alves <palves@redhat.com>

View File

@ -620,6 +620,18 @@ gdb_test_no_output "macro define va_gnu(args...) varfunc (fixedarg, args)" \
gdb_test_no_output "macro define va2_gnu(args...) varfunc (fixedarg, ## args)" \
"define fourth varargs helper"
gdb_test_no_output \
"macro define va3_cxx2a(x, ...) varfunc (x __VA_OPT__(,) __VA_ARGS__)" \
"define fifth varargs helper"
gdb_test_no_output \
"macro define va4_cxx2a(x, ...) varfunc (x __VA_OPT__(, __VA_ARGS__))" \
"define sixth varargs helper"
gdb_test_no_output \
"macro define va5_cxx2a(x, ...) varfunc (x __VA_OPT__(,) __VA_OPT__(__VA_ARGS__))" \
"define seventh varargs helper"
gdb_test "macro expand va_c99(one, two, three)" \
"expands to: *varfunc \\(fixedarg, *one, two, three\\)" \
"c99 varargs expansion"
@ -644,6 +656,58 @@ gdb_test "macro expand va2_gnu()" \
"expands to: *varfunc \\(fixedarg\\)" \
"gnu varargs expansion special splicing without an argument"
gdb_test "macro expand va3_cxx2a(23)" \
"expands to: *varfunc \\(23 \\)" \
"C++2a __VA_OPT__ handling without variable argument"
gdb_test "macro expand va3_cxx2a(23, 24, 25)" \
"expands to: *varfunc \\(23, 24, 25\\)" \
"C++2a __VA_OPT__ handling with variable argument"
gdb_test "macro expand va4_cxx2a(23, 24, 25)" \
"expands to: *varfunc \\(23, 24, 25\\)" \
"C++2a __VA_OPT__ conditional __VA_ARGS__ handling with variable argument"
gdb_test "macro expand va4_cxx2a(23)" \
"expands to: *varfunc \\(23\\)" \
"C++2a __VA_OPT__ conditional __VA_ARGS__ handling without variable argument"
gdb_test "macro expand va5_cxx2a(23, 24, 25)" \
"expands to: *varfunc \\(23,24, 25\\)" \
"C++2a double __VA_OPT__ conditional __VA_ARGS__ handling with variable argument"
gdb_test "macro expand va5_cxx2a(23)" \
"expands to: *varfunc \\(23\\)" \
"C++2a double __VA_OPT__ conditional __VA_ARGS__ handling without variable argument"
gdb_test_no_output \
"macro define badopt1(x, ...) __VA_OPT__) x" \
"define first invalid varargs helper"
gdb_test "macro expand badopt1(5)" \
"__VA_OPT__ must be followed by an open parenthesis" \
"__VA_OPT__ without open paren"
gdb_test_no_output \
"macro define badopt2(x, ...) __VA_OPT__(__VA_OPT__(,)) x" \
"define second invalid varargs helper"
gdb_test "macro expand badopt2(5)" \
"__VA_OPT__ cannot appear inside __VA_OPT__" \
"__VA_OPT__ inside __VA_OPT__"
gdb_test_no_output \
"macro define badopt3(x) __VA_OPT__" \
"define third invalid varargs helper"
gdb_test "macro expand badopt3(5)" \
"__VA_OPT__ is only valid in a variadic macro" \
"__VA_OPT__ not in variadic macro"
gdb_test_no_output \
"macro define badopt4(x, ...) __VA_OPT__(x" \
"define fourth invalid varargs helper"
gdb_test "macro expand badopt4(5)" \
"Unterminated __VA_OPT__" \
"__VA_OPT__ without closing paren"
# Stringification tests.
gdb_test_no_output "macro define str(x) #x" \