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.
---
 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

Reply via email to