mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-05 06:23:58 +08:00
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:
@ -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>
|
2017-09-26 Walfred Tedeschi <walfred.tedeschi@intel.com>
|
||||||
Pedro Alves <palves@redhat.com>
|
Pedro Alves <palves@redhat.com>
|
||||||
|
|
||||||
|
@ -946,6 +946,30 @@ find_parameter (const struct macro_buffer *tok,
|
|||||||
return -1;
|
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
|
/* Given the macro definition DEF, being invoked with the actual
|
||||||
arguments given by ARGC and ARGV, substitute the arguments into the
|
arguments given by ARGC and ARGV, substitute the arguments into the
|
||||||
replacement list, and store the result in DEST.
|
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_rl_start = replacement_list.text;
|
||||||
lookahead_valid = get_token (&lookahead, &replacement_list);
|
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
|
/* Just for aesthetics. If we skipped some whitespace, copy
|
||||||
that to DEST. */
|
that to DEST. */
|
||||||
if (tok.text > original_rl_start)
|
if (tok.text > original_rl_start)
|
||||||
@ -1157,16 +1237,10 @@ substitute_args (struct macro_buffer *dest,
|
|||||||
if (! substituted)
|
if (! substituted)
|
||||||
append_tokens_without_splicing (dest, &tok);
|
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>
|
2017-09-26 Thomas Preud'homme <thomas.preudhomme@arm.com>
|
||||||
Pedro Alves <palves@redhat.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)" \
|
gdb_test_no_output "macro define va2_gnu(args...) varfunc (fixedarg, ## args)" \
|
||||||
"define fourth varargs helper"
|
"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)" \
|
gdb_test "macro expand va_c99(one, two, three)" \
|
||||||
"expands to: *varfunc \\(fixedarg, *one, two, three\\)" \
|
"expands to: *varfunc \\(fixedarg, *one, two, three\\)" \
|
||||||
"c99 varargs expansion"
|
"c99 varargs expansion"
|
||||||
@ -644,6 +656,58 @@ gdb_test "macro expand va2_gnu()" \
|
|||||||
"expands to: *varfunc \\(fixedarg\\)" \
|
"expands to: *varfunc \\(fixedarg\\)" \
|
||||||
"gnu varargs expansion special splicing without an argument"
|
"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.
|
# Stringification tests.
|
||||||
|
|
||||||
gdb_test_no_output "macro define str(x) #x" \
|
gdb_test_no_output "macro define str(x) #x" \
|
||||||
|
Reference in New Issue
Block a user