* [RFA] Add support for __VA_OPT__
@ 2017-09-18 2:42 Tom Tromey
2017-09-20 16:43 ` Pedro Alves
0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2017-09-18 2:42 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
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-17 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-17 Tom Tromey <tom@tromey.com>
* gdb.base/macscp.exp: Add __VA_OPT__ tests.
---
gdb/ChangeLog | 5 +++
gdb/macroexp.c | 73 +++++++++++++++++++++++++++++++++++----
gdb/testsuite/ChangeLog | 4 +++
gdb/testsuite/gdb.base/macscp.exp | 12 +++++++
4 files changed, 87 insertions(+), 7 deletions(-)
diff --git a/gdb/macroexp.c b/gdb/macroexp.c
index e7a0dad..369fc78 100644
--- a/gdb/macroexp.c
+++ b/gdb/macroexp.c
@@ -946,6 +946,22 @@ 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 int
+get_next_token_for_substitution (struct macro_buffer *replacement_list,
+ struct macro_buffer *token,
+ char **start,
+ struct macro_buffer *lookahead,
+ char **lookahead_start)
+{
+ *token = *lookahead;
+ *start = *lookahead_start;
+ *lookahead_start = replacement_list->text;
+ return 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 +1012,57 @@ 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 (;;
+ lookahead_valid = get_next_token_for_substitution (&replacement_list,
+ &tok,
+ &original_rl_start,
+ &lookahead,
+ &lookahead_rl_start))
{
+ if (vaopt_state > 0)
+ {
+ if (tok.len == 1)
+ {
+ if (tok.text[0] == '(')
+ {
+ ++vaopt_state;
+ /* We just entered __VA_OPT__, so don't emit this
+ token. */
+ continue;
+ }
+ else if (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 (is_varargs
+ && tok.len == 10
+ && strncmp (tok.text, "__VA_OPT__", 10) == 0)
+ {
+ 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)
@@ -1160,12 +1225,6 @@ substitute_args (struct macro_buffer *dest,
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);
}
}
diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp
index 54b5ab2..a08ec46 100644
--- a/gdb/testsuite/gdb.base/macscp.exp
+++ b/gdb/testsuite/gdb.base/macscp.exp
@@ -620,6 +620,10 @@ 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 "macro expand va_c99(one, two, three)" \
"expands to: *varfunc \\(fixedarg, *one, two, three\\)" \
"c99 varargs expansion"
@@ -644,6 +648,14 @@ 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"
+
# Stringification tests.
gdb_test_no_output "macro define str(x) #x" \
--
2.9.4
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFA] Add support for __VA_OPT__
2017-09-18 2:42 [RFA] Add support for __VA_OPT__ Tom Tromey
@ 2017-09-20 16:43 ` Pedro Alves
2017-09-21 3:42 ` Tom Tromey
0 siblings, 1 reply; 7+ messages in thread
From: Pedro Alves @ 2017-09-20 16:43 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
W00t, thanks for doing this (and the gcc side as well!)
On 09/18/2017 03:42 AM, Tom Tromey wrote:
> diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp
> index 54b5ab2..a08ec46 100644
> --- a/gdb/testsuite/gdb.base/macscp.exp
> +++ b/gdb/testsuite/gdb.base/macscp.exp
> @@ -620,6 +620,10 @@ 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 "macro expand va_c99(one, two, three)" \
> "expands to: *varfunc \\(fixedarg, *one, two, three\\)" \
> "c99 varargs expansion"
> @@ -644,6 +648,14 @@ 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"
> +
The patch looks good to me, though I think it'd be nice to see
tests that make sure that ill-formed input doesn't send us
to the weeds. Like:
- does the state machine handle "__VA_OPT__)" gracefully?
I.e., ')' before '('.
- similarly: "__VA_OPT__)(,)"
- does the state machine handle multiple occurrences of
__VA_OPT__ in the same macro expansion? It looks like
it, but....
Also, does this handle:
__VA_OPT__(__VA_ARGS__)
correctly? I think so, but...
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFA] Add support for __VA_OPT__
2017-09-20 16:43 ` Pedro Alves
@ 2017-09-21 3:42 ` Tom Tromey
2017-09-21 9:01 ` Pedro Alves
0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2017-09-21 3:42 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches
Pedro> The patch looks good to me, though I think it'd be nice to see
Pedro> tests that make sure that ill-formed input doesn't send us
Pedro> to the weeds. Like:
Pedro> - does the state machine handle "__VA_OPT__)" gracefully?
Pedro> I.e., ')' before '('.
Pedro> - similarly: "__VA_OPT__)(,)"
Pedro> - does the state machine handle multiple occurrences of
Pedro> __VA_OPT__ in the same macro expansion? It looks like
Pedro> it, but....
Pedro> Also, does this handle:
Pedro> __VA_OPT__(__VA_ARGS__)
Pedro> correctly? I think so, but...
I've added all of these.
But I wonder if gdb should just error() on the invalid ones.
My first thought was no, why make life harder -- but at the same time,
the invalid cases really aren't that useful either.
Tom
commit 635411e81e8ce24fcc8887755b1520baf9044205
Author: Tom Tromey <tom@tromey.com>
Date: Sun Sep 17 20:36:41 2017 -0600
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-17 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-17 Tom Tromey <tom@tromey.com>
* gdb.base/macscp.exp: Add __VA_OPT__ tests.
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 4de6da2..34c9810 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2017-09-17 Tom Tromey <tom@tromey.com>
+
+ * macroexp.c (get_next_token_for_substitution): New function.
+ (substitute_args): Call it. Check for __VA_OPT__.
+
2017-09-20 Pedro Alves <palves@redhat.com>
* eval.c (make_params): Delete, refactored as ...
diff --git a/gdb/macroexp.c b/gdb/macroexp.c
index e7a0dad..369fc78 100644
--- a/gdb/macroexp.c
+++ b/gdb/macroexp.c
@@ -946,6 +946,22 @@ 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 int
+get_next_token_for_substitution (struct macro_buffer *replacement_list,
+ struct macro_buffer *token,
+ char **start,
+ struct macro_buffer *lookahead,
+ char **lookahead_start)
+{
+ *token = *lookahead;
+ *start = *lookahead_start;
+ *lookahead_start = replacement_list->text;
+ return 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 +1012,57 @@ 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 (;;
+ lookahead_valid = get_next_token_for_substitution (&replacement_list,
+ &tok,
+ &original_rl_start,
+ &lookahead,
+ &lookahead_rl_start))
{
+ if (vaopt_state > 0)
+ {
+ if (tok.len == 1)
+ {
+ if (tok.text[0] == '(')
+ {
+ ++vaopt_state;
+ /* We just entered __VA_OPT__, so don't emit this
+ token. */
+ continue;
+ }
+ else if (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 (is_varargs
+ && tok.len == 10
+ && strncmp (tok.text, "__VA_OPT__", 10) == 0)
+ {
+ 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)
@@ -1160,12 +1225,6 @@ substitute_args (struct macro_buffer *dest,
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);
}
}
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 721bd81..3e16b5a 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2017-09-17 Tom Tromey <tom@tromey.com>
+
+ * gdb.base/macscp.exp: Add __VA_OPT__ tests.
+
2017-09-20 Pedro Alves <palves@redhat.com>
* gdb.base/list-ambiguous.exp (test_list_ambiguous_symbol): Expect
diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp
index 54b5ab2..96674f3 100644
--- a/gdb/testsuite/gdb.base/macscp.exp
+++ b/gdb/testsuite/gdb.base/macscp.exp
@@ -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,50 @@ 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"
+
+#
+# Invalid __VA_OPT__ tests are not intended to define gdb's output,
+# but rather to ensure that gdb at least doesn't crash when presented
+# with something invalid.
+#
+
+gdb_test_no_output \
+ "macro define badopt1(x, ...) __VA_OPT__) x" \
+ "define first invalid varargs helper"
+gdb_test "macro expand badopt1(5)" \
+ "expands to: 5" \
+ "Test that first invalid __VA_OPT__ doesn't crash"
+
+gdb_test_no_output \
+ "macro define badopt1(x, ...) __VA_OPT__)(,) x" \
+ "define second invalid varargs helper"
+gdb_test "macro expand badopt1(5)" \
+ "expands to: \\(,\\) 5" \
+ "Test that second invalid __VA_OPT__ doesn't crash"
+
# Stringification tests.
gdb_test_no_output "macro define str(x) #x" \
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFA] Add support for __VA_OPT__
2017-09-21 3:42 ` Tom Tromey
@ 2017-09-21 9:01 ` Pedro Alves
2017-09-23 3:03 ` Tom Tromey
0 siblings, 1 reply; 7+ messages in thread
From: Pedro Alves @ 2017-09-21 9:01 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 09/21/2017 04:42 AM, Tom Tromey wrote:
> Pedro> The patch looks good to me, though I think it'd be nice to see
> Pedro> tests that make sure that ill-formed input doesn't send us
> Pedro> to the weeds. Like:
> Pedro> - does the state machine handle "__VA_OPT__)" gracefully?
> Pedro> I.e., ')' before '('.
> Pedro> - similarly: "__VA_OPT__)(,)"
> Pedro> - does the state machine handle multiple occurrences of
> Pedro> __VA_OPT__ in the same macro expansion? It looks like
> Pedro> it, but....
> Pedro> Also, does this handle:
> Pedro> __VA_OPT__(__VA_ARGS__)
> Pedro> correctly? I think so, but...
>
> I've added all of these.
Great, thanks!
>
> But I wonder if gdb should just error() on the invalid ones.
> My first thought was no, why make life harder -- but at the same time,
> the invalid cases really aren't that useful either.
Yeah, error might be better - e.g., for someone trying
to write a "macro define" interactively (without
going via the compiler first), and puzzling about why it
doesn't exactly work [due to some typo]. But we can
decide to do that incrementally. Fine with me to push
as is if you'd like.
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFA] Add support for __VA_OPT__
2017-09-21 9:01 ` Pedro Alves
@ 2017-09-23 3:03 ` Tom Tromey
2017-09-27 11:32 ` Pedro Alves
0 siblings, 1 reply; 7+ messages in thread
From: Tom Tromey @ 2017-09-23 3:03 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches
>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
>> But I wonder if gdb should just error() on the invalid ones.
>> My first thought was no, why make life harder -- but at the same time,
>> the invalid cases really aren't that useful either.
Pedro> Yeah, error might be better - e.g., for someone trying
Pedro> to write a "macro define" interactively (without
Pedro> going via the compiler first), and puzzling about why it
Pedro> doesn't exactly work [due to some typo]. But we can
Pedro> decide to do that incrementally. Fine with me to push
Pedro> as is if you'd like.
I've switched it; and good thing, too, because this caught a bug in the
previous patch that could cause an infinite loop.
Tom
commit dbaa7cadd373972d362c10cedc8f34f5cf1d6e2a
Author: Tom Tromey <tom@tromey.com>
Date: Sun Sep 17 20:36:41 2017 -0600
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.)
ChangeLog
2017-09-17 Tom Tromey <tom@tromey.com>
* macroexp.c (get_next_token_for_substitution): New function.
(substitute_args): Call it. Check for __VA_OPT__.
testsuite/ChangeLog
2017-09-17 Tom Tromey <tom@tromey.com>
* gdb.base/macscp.exp: Add __VA_OPT__ tests.
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index aa50dc9..d660fb0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2017-09-17 Tom Tromey <tom@tromey.com>
+
+ * macroexp.c (get_next_token_for_substitution): New function.
+ (substitute_args): Call it. Check for __VA_OPT__.
+
2017-09-22 Tom Tromey <tom@tromey.com>
* utils.c (class scoped_input_handler) <m_quit_handler>: Change
diff --git a/gdb/macroexp.c b/gdb/macroexp.c
index e7a0dad..7d5b876 100644
--- a/gdb/macroexp.c
+++ b/gdb/macroexp.c
@@ -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,67 @@ 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;
+
+ /* Whether the loop should keep going. */
+ bool keep_going = true;
+
+ for (;
+ 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 +1240,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__"));
}
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 6584a23..ddc17d2 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2017-09-17 Tom Tromey <tom@tromey.com>
+
+ * gdb.base/macscp.exp: Add __VA_OPT__ tests.
+
2017-09-21 Kevin Buettner <kevinb@redhat.com>
* gdb.python/py-thrhandle.c, gdb.python/py-thrhandle.exp: New
diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp
index 54b5ab2..c5cd899 100644
--- a/gdb/testsuite/gdb.base/macscp.exp
+++ b/gdb/testsuite/gdb.base/macscp.exp
@@ -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" \
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFA] Add support for __VA_OPT__
2017-09-23 3:03 ` Tom Tromey
@ 2017-09-27 11:32 ` Pedro Alves
2017-09-27 14:19 ` Tom Tromey
0 siblings, 1 reply; 7+ messages in thread
From: Pedro Alves @ 2017-09-27 11:32 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 09/23/2017 04:03 AM, Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes:
>
>>> But I wonder if gdb should just error() on the invalid ones.
>>> My first thought was no, why make life harder -- but at the same time,
>>> the invalid cases really aren't that useful either.
>
> Pedro> Yeah, error might be better - e.g., for someone trying
> Pedro> to write a "macro define" interactively (without
> Pedro> going via the compiler first), and puzzling about why it
> Pedro> doesn't exactly work [due to some typo]. But we can
> Pedro> decide to do that incrementally. Fine with me to push
> Pedro> as is if you'd like.
>
> I've switched it; and good thing, too, because this caught a bug in the
> previous patch that could cause an infinite loop.
>
Nice. Patch looks good. Please push.
> + /* Whether the loop should keep going. */
> + bool keep_going = true;
'keep_going' doesn't appear used after the loop. Could it be
declared in the for's init statement ?
for (bool keep_going = true;
keep_going;
...
> +
> + for (;
> + keep_going;
> + get_next_token_for_substitution (&replacement_list,
> + &tok,
> + &original_rl_start,
> + &lookahead,
> + &lookahead_rl_start,
> + &lookahead_valid,
> + &keep_going))
> {
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFA] Add support for __VA_OPT__
2017-09-27 11:32 ` Pedro Alves
@ 2017-09-27 14:19 ` Tom Tromey
0 siblings, 0 replies; 7+ messages in thread
From: Tom Tromey @ 2017-09-27 14:19 UTC (permalink / raw)
To: Pedro Alves; +Cc: Tom Tromey, gdb-patches
Pedro> 'keep_going' doesn't appear used after the loop. Could it be
Pedro> declared in the for's init statement ?
Yes. I made this change, and I'm going to push it in now.
thanks,
Tom
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-09-27 14:19 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-09-18 2:42 [RFA] Add support for __VA_OPT__ Tom Tromey
2017-09-20 16:43 ` Pedro Alves
2017-09-21 3:42 ` Tom Tromey
2017-09-21 9:01 ` Pedro Alves
2017-09-23 3:03 ` Tom Tromey
2017-09-27 11:32 ` Pedro Alves
2017-09-27 14:19 ` Tom Tromey
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox