On Sun, May 24, 2020 at 11:46:34PM +0200, Mark Wielaard wrote:
> The C++ parser already tracks function call parens matching, but the C
> parser doesn't. This adds the same functionality to the C parser and adds
> a testcase showing the C++ and C parser matching function call parens
> in an error message.
>
> gcc/c/ChangeLog:
>
> * c-parser.c (c_parser_postfix_expression_after_primary): Add
> scope with matching_parens after CPP_OPEN_PAREN.
>
> gcc/testsuite/ChangeLog:
>
> * c-c++-common/missing-close-func-paren.c: New test.
Ping.
> ---
> gcc/c/c-parser.c | 32 ++++++++-------
> .../c-c++-common/missing-close-func-paren.c | 40 +++++++++++++++++++
> 2 files changed, 57 insertions(+), 15 deletions(-)
> create mode 100644 gcc/testsuite/c-c++-common/missing-close-func-paren.c
>
> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> index 5d11e7e73c16..23d6fa22b685 100644
> --- a/gcc/c/c-parser.c
> +++ b/gcc/c/c-parser.c
> @@ -10458,21 +10458,23 @@ c_parser_postfix_expression_after_primary (c_parser
> *parser,
> break;
> case CPP_OPEN_PAREN:
> /* Function call. */
> - c_parser_consume_token (parser);
> - for (i = 0; i < 3; i++)
> - {
> - sizeof_arg[i] = NULL_TREE;
> - sizeof_arg_loc[i] = UNKNOWN_LOCATION;
> - }
> - literal_zero_mask = 0;
> - if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
> - exprlist = NULL;
> - else
> - exprlist = c_parser_expr_list (parser, true, false, &origtypes,
> - sizeof_arg_loc, sizeof_arg,
> - &arg_loc, &literal_zero_mask);
> - c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
> - "expected %<)%>");
> + {
> + matching_parens parens;
> + parens.consume_open (parser);
> + for (i = 0; i < 3; i++)
> + {
> + sizeof_arg[i] = NULL_TREE;
> + sizeof_arg_loc[i] = UNKNOWN_LOCATION;
> + }
> + literal_zero_mask = 0;
> + if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
> + exprlist = NULL;
> + else
> + exprlist = c_parser_expr_list (parser, true, false, &origtypes,
> + sizeof_arg_loc, sizeof_arg,
> + &arg_loc, &literal_zero_mask);
> + parens.skip_until_found_close (parser);
> + }
> orig_expr = expr;
> mark_exp_read (expr.value);
> if (warn_sizeof_pointer_memaccess)
> diff --git a/gcc/testsuite/c-c++-common/missing-close-func-paren.c
> b/gcc/testsuite/c-c++-common/missing-close-func-paren.c
> new file mode 100644
> index 000000000000..3177e250e1c3
> --- /dev/null
> +++ b/gcc/testsuite/c-c++-common/missing-close-func-paren.c
> @@ -0,0 +1,40 @@
> +/* { dg-options "-fdiagnostics-show-caret" } */
> +
> +/* Verify that the C/C++ frontends show the pertinent opening symbol when
> + a closing symbol is missing for a function call. */
> +
> +/* Verify that, when they are on the same line, that the opening symbol is
> + shown as a secondary range within the main diagnostic. */
> +
> +extern int __attribute__((const)) foo (int a, int b, int c);
> +
> +void single_func ()
> +{
> + int single =
> + foo (1, (1 + 2), (1 + 2 + 3):); /* { dg-error "expected '\\)' before ':'
> token" } */
> + /* { dg-begin-multiline-output "" }
> + foo (1, (1 + 2), (1 + 2 + 3):);
> + ~ ^
> + )
> + { dg-end-multiline-output "" } */
> +}
> +
> +/* Verify that, when they are on different lines, that the opening symbol is
> + shown via a secondary diagnostic. */
> +
> +void multi_func ()
> +{
> + int multi =
> + foo (1, /* { dg-message "to match this '\\('" } */
> + (1 + 2),
> + (1 + 2 + 3):); /* { dg-error "expected '\\)' before ':' token" } */
> + /* { dg-begin-multiline-output "" }
> + (1 + 2 + 3):);
> + ^
> + )
> + { dg-end-multiline-output "" } */
> + /* { dg-begin-multiline-output "" }
> + foo (1,
> + ^
> + { dg-end-multiline-output "" } */
> +}
> --
> 2.20.1
>