From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23482 invoked by alias); 21 Sep 2017 03:42:53 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 23472 invoked by uid 89); 21 Sep 2017 03:42:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.8 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 spammy=12256 X-HELO: gproxy10-pub.mail.unifiedlayer.com Received: from gproxy10-pub.mail.unifiedlayer.com (HELO gproxy10-pub.mail.unifiedlayer.com) (69.89.20.226) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 21 Sep 2017 03:42:50 +0000 Received: from CMOut01 (unknown [10.0.90.82]) by gproxy10.mail.unifiedlayer.com (Postfix) with ESMTP id 493AA140435 for ; Wed, 20 Sep 2017 21:42:49 -0600 (MDT) Received: from box522.bluehost.com ([74.220.219.122]) by CMOut01 with id C3il1w00K2f2jeq013iov1; Wed, 20 Sep 2017 21:42:49 -0600 X-Authority-Analysis: v=2.2 cv=K4VSJ2eI c=1 sm=1 tr=0 a=GsOEXm/OWkKvwdLVJsfwcA==:117 a=GsOEXm/OWkKvwdLVJsfwcA==:17 a=2JCJgTwv5E4A:10 a=zstS-IiYAAAA:8 a=20KFwNOVAAAA:8 a=nEstxzMVSIbnmEd0qDgA:9 a=4G6NA9xxw8l3yy4pmD5M:22 Received: from 75-166-76-94.hlrn.qwest.net ([75.166.76.94]:47352 helo=bapiya) by box522.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.87) (envelope-from ) id 1dusNx-0006jB-IH; Wed, 20 Sep 2017 21:42:45 -0600 From: Tom Tromey To: Pedro Alves Cc: Tom Tromey , gdb-patches@sourceware.org Subject: Re: [RFA] Add support for __VA_OPT__ References: <20170918024223.5607-1-tom@tromey.com> <31c997d6-8866-2080-5fd2-ebed0871c98f@redhat.com> Date: Thu, 21 Sep 2017 03:42:00 -0000 In-Reply-To: <31c997d6-8866-2080-5fd2-ebed0871c98f@redhat.com> (Pedro Alves's message of "Wed, 20 Sep 2017 17:43:11 +0100") Message-ID: <874lrwsonf.fsf@tromey.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-BWhitelist: no X-Exim-ID: 1dusNx-0006jB-IH X-Source-Sender: 75-166-76-94.hlrn.qwest.net (bapiya) [75.166.76.94]:47352 X-Source-Auth: tom+tromey.com X-Email-Count: 2 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTIyLmJsdWVob3N0LmNvbQ== X-Local-Domain: yes X-SW-Source: 2017-09/txt/msg00530.txt.bz2 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 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 * 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 * 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 + + * macroexp.c (get_next_token_for_substitution): New function. + (substitute_args): Call it. Check for __VA_OPT__. + 2017-09-20 Pedro Alves * 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 + + * gdb.base/macscp.exp: Add __VA_OPT__ tests. + 2017-09-20 Pedro Alves * 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" \