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:
parent
1948519604
commit
a9bbfbd85f
|
@ -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>
|
||||
|
||||
|
|
|
@ -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__"));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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" \
|
||||
|
|
Loading…
Reference in New Issue