From: Tom Tromey <tom@tromey.com>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tom@tromey.com>
Subject: [RFA] Add support for __VA_OPT__
Date: Mon, 18 Sep 2017 02:42:00 -0000 [thread overview]
Message-ID: <20170918024223.5607-1-tom@tromey.com> (raw)
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
next reply other threads:[~2017-09-18 2:42 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-18 2:42 Tom Tromey [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170918024223.5607-1-tom@tromey.com \
--to=tom@tromey.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox