Ping

On Thu, 2017-10-05 at 12:08 -0400, David Malcolm wrote:
> Here's a slight update to this patch, since v2 was made invalid by 
> r253411 ("C: underline parameters in mismatching function calls").
> 
> Both v2 and r253411 added code to c-parser.c/h to track the
> location_t
> of the last consumed token (although I somehow managed to name the
> new
> field in c_parser differently between the two versions...)
> 
> This version (v3) is the same as v2, but removes the copy of the
> above code, updating the usage sites to use the field name from
> r253411.
> 
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu
> in conjunction with patch 1 of the kit:
>   https://gcc.gnu.org/ml/gcc-patches/2017-09/msg01745.html
> 
> OK for trunk?
> 
> Blurb from v2 follows:
> 
> The patch improves our C/C++ frontends' handling of missing
> symbols, by making c_parser_require and cp_parser_require use
> "better" locations for the diagnostic, and insert fix-it hints,
> under certain circumstances (see the comments in the patch for
> full details).
> 
> For example, for this code with a missing semicolon:
> 
>   $ cat test.c
>   int missing_semicolon (void)
>   {
>     return 42
>   }
> 
>   trunk currently emits:
> 
>   test.c:4:1: error: expected ';' before '}' token
>    }
>    ^
> 
> This patch adds a fix-it hint for the missing semicolon, and puts
> the error at the location of the missing semicolon, printing the
> followup token as a secondary location:
> 
>   test.c:3:12: error: expected ';' before '}' token
>      return 42
>               ^
>               ;
>    }
>    ~
> 
> More examples can be seen in the test cases.
> 
> This is a revised version of the patch I posted here:
>   https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00135.html
> 
> Some of the changes in that patch landed in trunk in r251026
> (aka 3fe34694f0990d1d649711ede0326497f8a849dc
> "C/C++: show pertinent open token when missing a close token"),
> so this patch contains the remaining part, updated also for the
> previous patch that reunifies the cloned copies of cp_parser_error
> introduced in r251026.
> 
> It also:
> - fixes the typo seen by Jeff
> - eliminated some unnecessary changes to c-c++-common/missing-
> symbol.c
> - fixes some bugs
> 
> r250133, r250134, and r251026 already incorporated the suggestion
> from
> Richard Sandiford to consolidate note-printing when the matching
> location
> is near the primary location of the diagnostic.
> 
> This patch doesn't address Joseph's requests to tackle PR 7356 and
> PR 18248, but he said that it was OK to leave these for followups.
> 
> Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu
> in conjunction with patch 1 of the kit.
> 
> OK for trunk?
> 
> gcc/c-family/ChangeLog:
>       * c-common.c (enum missing_token_insertion_kind): New enum.
>       (get_missing_token_insertion_kind): New function.
>       (maybe_suggest_missing_token_insertion): New function.
>       * c-common.h (maybe_suggest_missing_token_insertion): New decl.
> 
> gcc/c/ChangeLog:
>       * c-parser.c (c_parser_require): Add "type_is_unique" param and
>       use it to guard calls to maybe_suggest_missing_token_insertion.
>       (c_parser_parms_list_declarator): Override default value of new
>       "type_is_unique" param to c_parser_require.
>       (c_parser_asm_statement): Likewise.
>       * c-parser.h (c_parser_require): Add "type_is_unique" param,
>       defaulting to true.
> 
> gcc/cp/ChangeLog:
>       * parser.c (get_required_cpp_ttype): New function.
>       (cp_parser_error_1): Call it, using the result to call
>       maybe_suggest_missing_token_insertion.
> 
> gcc/testsuite/ChangeLog:
>       * c-c++-common/cilk-plus/AN/parser_errors.c: Update expected
>       output to reflect changes to reported locations of missing
>       symbols.
>       * c-c++-common/cilk-plus/AN/parser_errors2.c: Likewise.
>       * c-c++-common/cilk-plus/AN/parser_errors3.c: Likewise.
>       * c-c++-common/cilk-plus/AN/pr61191.c: Likewise.
>       * c-c++-common/gomp/pr63326.c: Likewise.
>       * c-c++-common/missing-close-symbol.c: Likewise, also update
> for
>       new fix-it hints.
>       * c-c++-common/missing-symbol.c: Likewise, also add test
> coverage
>       for missing colon in ternary operator.
>       * g++.dg/cpp1y/digit-sep-neg.C: Likewise.
>       * g++.dg/cpp1y/pr65202.C: Likewise.
>       * g++.dg/missing-symbol-2.C: New test case.
>       * g++.dg/other/do1.C: Update expected output to reflect
>       changes to reported locations of missing symbols.
>       * g++.dg/parse/error11.C: Likewise.
>       * g++.dg/template/error11.C: Likewise.
>       * gcc.dg/missing-symbol-2.c: New test case.
>       * gcc.dg/missing-symbol-3.c: New test case.
>       * gcc.dg/noncompile/940112-1.c: Update expected output to
> reflect
>       changes to reported locations of missing symbols.
>       * gcc.dg/noncompile/971104-1.c: Likewise.
>       * obj-c++.dg/exceptions-6.mm: Likewise.
>       * obj-c++.dg/pr48187.mm: Likewise.
>       * objc.dg/exceptions-6.m: Likewise.
> ---
>  gcc/c-family/c-common.c                            | 158
> +++++++++++++++++++++
>  gcc/c-family/c-common.h                            |   3 +
>  gcc/c/c-parser.c                                   |  25 +++-
>  gcc/c/c-parser.h                                   |   3 +-
>  gcc/cp/parser.c                                    |  51 ++++++-
>  .../c-c++-common/cilk-plus/AN/parser_errors.c      |   4 +-
>  .../c-c++-common/cilk-plus/AN/parser_errors2.c     |   3 +-
>  .../c-c++-common/cilk-plus/AN/parser_errors3.c     |   3 +-
>  gcc/testsuite/c-c++-common/cilk-plus/AN/pr61191.c  |   3 +-
>  gcc/testsuite/c-c++-common/gomp/pr63326.c          |  22 +--
>  gcc/testsuite/c-c++-common/missing-close-symbol.c  |   2 +
>  gcc/testsuite/c-c++-common/missing-symbol.c        |  35 +++--
>  gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C         |   4 +-
>  gcc/testsuite/g++.dg/cpp1y/pr65202.C               |   4 +-
>  gcc/testsuite/g++.dg/missing-symbol-2.C            |  58 ++++++++
>  gcc/testsuite/g++.dg/other/do1.C                   |   4 +-
>  gcc/testsuite/g++.dg/parse/error11.C               |   2 +-
>  gcc/testsuite/g++.dg/template/error11.C            |   2 +-
>  gcc/testsuite/gcc.dg/missing-symbol-2.c            |  71 +++++++++
>  gcc/testsuite/gcc.dg/missing-symbol-3.c            |  50 +++++++
>  gcc/testsuite/gcc.dg/noncompile/940112-1.c         |   4 +-
>  gcc/testsuite/gcc.dg/noncompile/971104-1.c         |   4 +-
>  gcc/testsuite/obj-c++.dg/exceptions-6.mm           |   6 +-
>  gcc/testsuite/obj-c++.dg/pr48187.mm                |   8 +-
>  gcc/testsuite/objc.dg/exceptions-6.m               |   4 +-
>  25 files changed, 476 insertions(+), 57 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/missing-symbol-2.C
>  create mode 100644 gcc/testsuite/gcc.dg/missing-symbol-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/missing-symbol-3.c
> 
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index b3ec3a0..a23fa5f 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -7946,6 +7946,164 @@ c_flt_eval_method (bool maybe_c11_only_p)
>      return c_ts18661_flt_eval_method ();
>  }
>  
> +/* An enum for get_missing_token_insertion_kind for describing the
> best
> +   place to insert a missing token, if there is one.  */
> +
> +enum missing_token_insertion_kind
> +{
> +  MTIK_IMPOSSIBLE,
> +  MTIK_INSERT_BEFORE_NEXT,
> +  MTIK_INSERT_AFTER_PREV
> +};
> +
> +/* Given a missing token of TYPE, determine if it is reasonable to
> +   emit a fix-it hint suggesting the insertion of the token, and,
> +   if so, where the token should be inserted relative to other
> tokens.
> +
> +   It only makes sense to do this for values of TYPE that are
> symbols.
> +
> +   Some symbols should go before the next token, e.g. in:
> +     if flag)
> +   we want to insert the missing '(' immediately before "flag",
> +   giving:
> +     if (flag)
> +   rather than:
> +     if( flag)
> +   These use MTIK_INSERT_BEFORE_NEXT.
> +
> +   Other symbols should go after the previous token, e.g. in:
> +     if (flag
> +       do_something ();
> +   we want to insert the missing ')' immediately after the "flag",
> +   giving:
> +     if (flag)
> +       do_something ();
> +   rather than:
> +     if (flag
> +       )do_something ();
> +   These use MTIK_INSERT_AFTER_PREV.  */
> +
> +static enum missing_token_insertion_kind
> +get_missing_token_insertion_kind (enum cpp_ttype type)
> +{
> +  switch (type)
> +    {
> +      /* Insert missing "opening" brackets immediately
> +      before the next token.  */
> +    case CPP_OPEN_SQUARE:
> +    case CPP_OPEN_PAREN:
> +      return MTIK_INSERT_BEFORE_NEXT;
> +
> +      /* Insert other missing symbols immediately after
> +      the previous token.  */
> +    case CPP_CLOSE_PAREN:
> +    case CPP_CLOSE_SQUARE:
> +    case CPP_SEMICOLON:
> +    case CPP_COMMA:
> +    case CPP_COLON:
> +      return MTIK_INSERT_AFTER_PREV;
> +
> +      /* Other kinds of token don't get fix-it hints.  */
> +    default:
> +      return MTIK_IMPOSSIBLE;
> +    }
> +}
> +
> +/* Given RICHLOC, a location for a diagnostic describing a missing
> token
> +   of kind TOKEN_TYPE, potentially add a fix-it hint suggesting the
> +   insertion of the token.
> +
> +   The location of the attempted fix-it hint depends on TOKEN_TYPE:
> +   it will either be:
> +     (a) immediately after PREV_TOKEN_LOC, or
> +
> +     (b) immediately before the primary location within RICHLOC
> (taken to
> +      be that of the token following where the token was
> expected).
> +
> +   If we manage to add a fix-it hint, then the location of the
> +   fix-it hint is likely to be more useful as the primary location
> +   of the diagnostic than that of the following token, so we swap
> +   these locations.
> +
> +   For example, given this bogus code:
> +       123456789012345678901234567890
> +   1 | int missing_semicolon (void)
> +   2 | {
> +   3 |   return 42
> +   4 | }
> +
> +   we will emit:
> +
> +     "expected ';' before '}'"
> +
> +   RICHLOC's primary location is at the closing brace, so before
> "swapping"
> +   we would emit the error at line 4 column 1:
> +
> +       123456789012345678901234567890
> +   3 |   return 42  |< fix-it hint emitted for this line
> +     |            ; |
> +   4 | }            |< "expected ';' before '}'" emitted at this
> line
> +     | ^            |
> +
> +   It's more useful for the location of the diagnostic to be at the
> +   fix-it hint, so we swap the locations, so the primary location
> +   is at the fix-it hint, with the old primary location inserted
> +   as a secondary location, giving this, with the error at line 3
> +   column 12:
> +
> +       123456789012345678901234567890
> +   3 |   return 42   |< "expected ';' before '}'" emitted at this
> line,
> +     |            ^  |   with fix-it hint
> +   4 |            ;  |
> +     | }             |< secondary range emitted here
> +     | ~             |.  */
> +
> +void
> +maybe_suggest_missing_token_insertion (rich_location *richloc,
> +                                    enum cpp_ttype token_type,
> +                                    location_t prev_token_loc)
> +{
> +  gcc_assert (richloc);
> +
> +  enum missing_token_insertion_kind mtik
> +    = get_missing_token_insertion_kind (token_type);
> +
> +  switch (mtik)
> +    {
> +    default:
> +      gcc_unreachable ();
> +      break;
> +
> +    case MTIK_IMPOSSIBLE:
> +      return;
> +
> +    case MTIK_INSERT_BEFORE_NEXT:
> +      /* Attempt to add the fix-it hint before the primary location
> +      of RICHLOC.  */
> +      richloc->add_fixit_insert_before (cpp_type2name (token_type,
> 0));
> +      break;
> +
> +    case MTIK_INSERT_AFTER_PREV:
> +      /* Attempt to add the fix-it hint after PREV_TOKEN_LOC.  */
> +      richloc->add_fixit_insert_after (prev_token_loc,
> +                                    cpp_type2name (token_type,
> 0));
> +      break;
> +    }
> +
> +  /* If we were successful, use the fix-it hint's location as the
> +     primary location within RICHLOC, adding the old primary
> location
> +     back as a secondary location.  */
> +  if (!richloc->seen_impossible_fixit_p ())
> +    {
> +      fixit_hint *hint = richloc->get_last_fixit_hint ();
> +      location_t hint_loc = hint->get_start_loc ();
> +      location_t old_loc = richloc->get_loc ();
> +
> +      richloc->set_range (line_table, 0, hint_loc, true);
> +      richloc->add_range (old_loc, false);
> +    }
> +}
> +
>  #if CHECKING_P
>  
>  namespace selftest {
> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> index da6a0be..7e1877e 100644
> --- a/gcc/c-family/c-common.h
> +++ b/gcc/c-family/c-common.h
> @@ -1550,6 +1550,9 @@ extern int c_flt_eval_method (bool ts18661_p);
>  extern void add_no_sanitize_value (tree node, unsigned int flags);
>  
>  extern void maybe_add_include_fixit (rich_location *, const char *);
> +extern void maybe_suggest_missing_token_insertion (rich_location
> *richloc,
> +                                                enum cpp_ttype
> token_type,
> +                                                location_t
> prev_token_loc);
>  
>  #if CHECKING_P
>  namespace selftest {
> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> index 1a5e39e..a5e3ec4 100644
> --- a/gcc/c/c-parser.c
> +++ b/gcc/c/c-parser.c
> @@ -1041,13 +1041,21 @@ get_matching_symbol (enum cpp_ttype type)
>     If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
>     within any error as the location of an "opening" token matching
>     the close token TYPE (e.g. the location of the '(' when TYPE is
> -   CPP_CLOSE_PAREN).  */
> +   CPP_CLOSE_PAREN).
> +
> +   If TYPE_IS_UNIQUE is true (the default) then msgid describes
> exactly
> +   one type (e.g. "expected %<)%>") and thus it may be reasonable to
> +   attempt to generate a fix-it hint for the problem.
> +   Otherwise msgid describes multiple token types (e.g.
> +   "expected %<;%>, %<,%> or %<)%>"), and thus we shouldn't attempt
> to
> +   generate a fix-it hint.  */
>  
>  bool
>  c_parser_require (c_parser *parser,
>                 enum cpp_ttype type,
>                 const char *msgid,
> -               location_t matching_location)
> +               location_t matching_location,
> +               bool type_is_unique)
>  {
>    if (c_parser_next_token_is (parser, type))
>      {
> @@ -1059,6 +1067,13 @@ c_parser_require (c_parser *parser,
>        location_t next_token_loc = c_parser_peek_token (parser)-
> >location;
>        gcc_rich_location richloc (next_token_loc);
>  
> +      /* Potentially supply a fix-it hint, suggesting to add the
> +      missing token immediately after the *previous* token.
> +      This may move the primary location within richloc.  */
> +      if (!parser->error && type_is_unique)
> +     maybe_suggest_missing_token_insertion (&richloc, type,
> +                                            parser-
> >last_token_location);
> +
>        /* If matching_location != UNKNOWN_LOCATION, highlight it.
>        Attempt to consolidate diagnostics by printing it as a
>        secondary range within the main diagnostic.  */
> @@ -3975,7 +3990,8 @@ c_parser_parms_list_declarator (c_parser
> *parser, tree attrs, tree expr)
>           return get_parm_info (false, expr);
>       }
>        if (!c_parser_require (parser, CPP_COMMA,
> -                          "expected %<;%>, %<,%> or %<)%>"))
> +                          "expected %<;%>, %<,%> or %<)%>",
> +                          UNKNOWN_LOCATION, false))
>       {
>         c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
>         return NULL;
> @@ -6429,7 +6445,8 @@ c_parser_asm_statement (c_parser *parser)
>        if (!c_parser_require (parser, CPP_COLON,
>                            is_goto
>                            ? G_("expected %<:%>")
> -                          : G_("expected %<:%> or %<)%>")))
> +                          : G_("expected %<:%> or %<)%>"),
> +                          UNKNOWN_LOCATION, is_goto))
>       goto error_close_paren;
>  
>        /* Once past any colon, we're no longer a simple asm.  */
> diff --git a/gcc/c/c-parser.h b/gcc/c/c-parser.h
> index 01a7b72..21e4054 100644
> --- a/gcc/c/c-parser.h
> +++ b/gcc/c/c-parser.h
> @@ -137,7 +137,8 @@ extern c_token * c_parser_peek_2nd_token
> (c_parser *parser);
>  extern c_token * c_parser_peek_nth_token (c_parser *parser, unsigned
> int n);
>  extern bool c_parser_require (c_parser *parser, enum cpp_ttype type,
>                             const char *msgid,
> -                           location_t matching_location =
> UNKNOWN_LOCATION);
> +                           location_t matching_location =
> UNKNOWN_LOCATION,
> +                           bool type_is_unique=true);
>  extern bool c_parser_error (c_parser *parser, const char *gmsgid);
>  extern void c_parser_consume_token (c_parser *parser);
>  extern void c_parser_skip_until_found (c_parser *parser, enum
> cpp_ttype type,
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index c104612..77e82c9 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -2787,6 +2787,40 @@ get_matching_symbol (required_token
> token_desc)
>      }
>  }
>  
> +/* Attempt to convert TOKEN_DESC from a required_token to an
> +   enum cpp_ttype, returning CPP_EOF if there is no good
> conversion.  */
> +
> +static enum cpp_ttype
> +get_required_cpp_ttype (required_token token_desc)
> +{
> +  switch (token_desc)
> +    {
> +    case RT_SEMICOLON:
> +      return CPP_SEMICOLON;
> +    case RT_OPEN_PAREN:
> +      return CPP_OPEN_PAREN;
> +    case RT_CLOSE_BRACE:
> +      return CPP_CLOSE_BRACE;
> +    case RT_OPEN_BRACE:
> +      return CPP_OPEN_BRACE;
> +    case RT_CLOSE_SQUARE:
> +      return CPP_CLOSE_SQUARE;
> +    case RT_OPEN_SQUARE:
> +      return CPP_OPEN_SQUARE;
> +    case RT_COMMA:
> +      return CPP_COMMA;
> +    case RT_COLON:
> +      return CPP_COLON;
> +    case RT_CLOSE_PAREN:
> +      return CPP_CLOSE_PAREN;
> +
> +    default:
> +      /* Use CPP_EOF as a "no completions possible" code.  */
> +      return CPP_EOF;
> +    }
> +}
> +
> +
>  /* Subroutine of cp_parser_error and cp_parser_required_error.
>  
>     Issue a diagnostic of the form
> @@ -2798,9 +2832,12 @@ get_matching_symbol (required_token
> token_desc)
>     This bypasses the check for tentative passing, and potentially
>     adds material needed by cp_parser_required_error.
>  
> -   If MISSING_TOKEN_DESC is not RT_NONE, and MATCHING_LOCATION is
> not
> -   UNKNOWN_LOCATION, then we have an unmatched symbol at
> -   MATCHING_LOCATION; highlight this secondary location.  */
> +   If MISSING_TOKEN_DESC is not RT_NONE, then potentially add fix-it 
> hints
> +   suggesting insertion of the missing token.
> +
> +   Additionally, if MATCHING_LOCATION is not UNKNOWN_LOCATION, then
> we
> +   have an unmatched symbol at MATCHING_LOCATION; highlight this
> secondary
> +   location.  */
>  
>  static void
>  cp_parser_error_1 (cp_parser* parser, const char* gmsgid,
> @@ -2839,6 +2876,14 @@ cp_parser_error_1 (cp_parser* parser, const
> char* gmsgid,
>  
>    if (missing_token_desc != RT_NONE)
>      {
> +      /* Potentially supply a fix-it hint, suggesting to add the
> +      missing token immediately after the *previous* token.
> +      This may move the primary location within richloc.  */
> +      enum cpp_ttype ttype = get_required_cpp_ttype
> (missing_token_desc);
> +      location_t prev_token_loc
> +     = cp_lexer_previous_token (parser->lexer)->location;
> +      maybe_suggest_missing_token_insertion (&richloc, ttype,
> prev_token_loc);
> +
>        /* If matching_location != UNKNOWN_LOCATION, highlight it.
>        Attempt to consolidate diagnostics by printing it as a
>       secondary range within the main diagnostic.  */
> diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
> b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
> index 18816e0..fd4fe54 100644
> --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
> +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors.c
> @@ -7,5 +7,5 @@ int main (void)
>    
>    array2[:] = array2[: ;  /* { dg-error "expected ']'" } */
>  
> -  return 0;
> -} /* { dg-error "expected ';' before" "" { target c } } */
> +  return 0; /* { dg-error "expected ';' before" "" { target c } } */
> +}
> diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c 
> b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
> index 2bb9134..d003d7c 100644
> --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
> +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors2.c
> @@ -7,6 +7,7 @@ int main (void)
>    
>    array2[:] = array2[1:2:] ;  /* { dg-error "expected expression
> before" "" { target c } } */ 
>    /* { dg-error  "expected primary-expression before" "" { target
> c++ } .-1 } */
> +  /* { dg-error "expected ';' before" "" { target c } .-2 } */
>  
> -  return 0; /* { dg-error "expected ';' before" "" { target c }  }
> */
> +  return 0;
>  }
> diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c 
> b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
> index 9270007..14256e9 100644
> --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
> +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/parser_errors3.c
> @@ -7,6 +7,7 @@ int main (void)
>    
>    array2[:] = array2[1: :] ;  /* { dg-error "expected expression
> before" "" { target c }  } */ 
>    /* { dg-error "expected primary-expression before" "" { target c++
> }  .-1 } */
> +  /* { dg-error "expected ';' before" "" { target c } .-2 } */
>  
> -  return 0; /* { dg-error "expected ';' before" "" { target c } } */
> +  return 0;
>  }
> diff --git a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr61191.c
> b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr61191.c
> index a9a9d66..8c32ad9 100644
> --- a/gcc/testsuite/c-c++-common/cilk-plus/AN/pr61191.c
> +++ b/gcc/testsuite/c-c++-common/cilk-plus/AN/pr61191.c
> @@ -7,4 +7,5 @@ double f(double * A, double * B)
>    return __sec_reduce_add((B[0:500])(; /* { dg-error "called object"
> "" { target c } } */
>  /* { dg-error "expected expression before ';' token" "" { target c }
> .-1 } */
>  /* { dg-error "expected primary-expression before ';' token" "" {
> target c++ } .-2 } */
> -} /* { dg-error "expected" "" { target c } } */
> +/* { dg-error "expected" "" { target c } .-3 } */
> +}
> diff --git a/gcc/testsuite/c-c++-common/gomp/pr63326.c
> b/gcc/testsuite/c-c++-common/gomp/pr63326.c
> index e319f49..3e62723 100644
> --- a/gcc/testsuite/c-c++-common/gomp/pr63326.c
> +++ b/gcc/testsuite/c-c++-common/gomp/pr63326.c
> @@ -156,34 +156,34 @@ f4 (int x)
>    {
>      do
>        #pragma omp barrier                    /* { dg-error "may
> only be used in compound statements" } */
> -    while (0);
> +    while (0); /* { dg-error "before" "" { target c++ } } */
>    } /* { dg-error "before" "" { target c++ } } */
>    {
>      do
>        #pragma omp flush                              /* { dg-error 
> "may only be used in compound statements" } */
> -    while (0);
> +    while (0); /* { dg-error "before" "" { target c++ } } */
>    } /* { dg-error "before" "" { target c++ } } */
>    {
>      do
>        #pragma omp taskwait                   /* { dg-error "may
> only be used in compound statements" } */
> -    while (0);
> +    while (0); /* { dg-error "before" "" { target c++ } } */
>    } /* { dg-error "before" "" { target c++ } } */
>    {
>      do
>        #pragma omp taskyield                  /* { dg-error
> "may only be used in compound statements" } */
> -    while (0);
> +    while (0); /* { dg-error "before" "" { target c++ } } */
>    } /* { dg-error "before" "" { target c++ } } */
>    #pragma omp parallel
>    {
>      do
>        #pragma omp cancel parallel            /* { dg-error "may
> only be used in compound statements" } */
> -    while (0);
> +    while (0); /* { dg-error "before" "" { target c++ } } */
>    } /* { dg-error "before" "" { target c++ } } */
>    #pragma omp parallel
>    {
>      do
>        #pragma omp cancellation point parallel        /* { dg-error
> "may only be used in compound statements" } */
> -    while (0);
> +    while (0); /* { dg-error "before" "" { target c++ } } */
>    } /* { dg-error "before" "" { target c++ } } */
>    #pragma omp for ordered(1)
>    for (i = 0; i < 16; i++)
> @@ -191,28 +191,28 @@ f4 (int x)
>        {
>       do
>         #pragma omp ordered depend(source)    /* { dg-error
> "may only be used in compound statements" } */
> -     while (0);
> +     while (0); /* { dg-error "before" "" { target c++ } } */
>        } /* { dg-error "before" "" { target c++ } } */
>        {
>       do
>         #pragma omp ordered depend(sink: i-1) /* { dg-error 
> "may only be used in compound statements" } */
> -     while (0);
> +     while (0); /* { dg-error "before" "" { target c++ } } */
>        } /* { dg-error "before" "" { target c++ } } */
>      }
>    {
>      do
>        #pragma omp target enter data map(to:i)        /* { dg-error
> "may only be used in compound statements" } */
> -    while (0);
> +    while (0); /* { dg-error "before" "" { target c++ } } */
>    } /* { dg-error "before" "" { target c++ } } */
>    {
>      do
>        #pragma omp target update to(i)                /* { dg-error
> "may only be used in compound statements" } */
> -    while (0);
> +    while (0); /* { dg-error "before" "" { target c++ } } */
>    } /* { dg-error "before" "" { target c++ } } */
>    {
>      do
>        #pragma omp target exit data map(from:i)       /* { dg-error
> "may only be used in compound statements" } */
> -    while (0);
> +    while (0); /* { dg-error "before" "" { target c++ } } */
>    } /* { dg-error "before" "" { target c++ } } */
>  }
>  
> diff --git a/gcc/testsuite/c-c++-common/missing-close-symbol.c
> b/gcc/testsuite/c-c++-common/missing-close-symbol.c
> index 85b96f28..abeb837 100644
> --- a/gcc/testsuite/c-c++-common/missing-close-symbol.c
> +++ b/gcc/testsuite/c-c++-common/missing-close-symbol.c
> @@ -12,6 +12,7 @@ void test_static_assert_same_line (void)
>    /* { dg-begin-multiline-output "" }
>     _Static_assert(sizeof(int) >= sizeof(char), "msg";
>                   ~                                  ^
> +                                                    )
>       { dg-end-multiline-output "" } */
>  }
>  
> @@ -25,6 +26,7 @@ void test_static_assert_different_line (void)
>    /* { dg-begin-multiline-output "" }
>      "msg";
>           ^
> +         )
>       { dg-end-multiline-output "" } */
>    /* { dg-begin-multiline-output "" }
>     _Static_assert(sizeof(int) >= sizeof(char),
> diff --git a/gcc/testsuite/c-c++-common/missing-symbol.c
> b/gcc/testsuite/c-c++-common/missing-symbol.c
> index 33a501b..326b9fa 100644
> --- a/gcc/testsuite/c-c++-common/missing-symbol.c
> +++ b/gcc/testsuite/c-c++-common/missing-symbol.c
> @@ -5,15 +5,14 @@ extern int bar (void);
>  
>  int missing_close_paren_in_switch (int i)
>  {
> -  switch (i /* { dg-message "10: to match this '\\('" } */
> -    { /* { dg-error "5: expected '\\)' before '.' token" } */
> -  /* { dg-begin-multiline-output "" }
> -     {
> -     ^
> -     { dg-end-multiline-output "" } */
> +  switch (i /* { dg-error "12: expected '\\)' before '.' token" } */
> +    {
>    /* { dg-begin-multiline-output "" }
>     switch (i
> -          ^
> +          ~ ^
> +            )
> +     {
> +     ~       
>       { dg-end-multiline-output "" } */
>  
>      case 0:
> @@ -30,21 +29,33 @@ int missing_close_paren_in_switch (int i)
>  void missing_close_paren_in_if (void)
>  {
>    if (foo () /* { dg-line start_of_if } */
> -      && bar () 
> -    { /* { dg-error "5: expected '\\)' before '.' token" } */
> +      && bar () /* { dg-error "16: expected '\\)' before '.' token"
> } */
> +    {
>        /* { dg-begin-multiline-output "" }
> +       && bar ()
> +                ^
> +                )
>       {
> -     ^
> +     ~           
>           { dg-end-multiline-output "" } */
>        /* { dg-message "6: to match this '\\('" "" { target *-*-* }
> start_of_if } */
>        /* { dg-begin-multiline-output "" }
>     if (foo ()
>        ^
> -      { dg-end-multiline-output "" } */
> +         { dg-end-multiline-output "" } */
>      }
> -
>  } /* { dg-error "1: expected" } */
>    /* { dg-begin-multiline-output "" }
>   }
>   ^
>       { dg-end-multiline-output "" } */
> +
> +int missing_colon_in_ternary (int flag)
> +{
> +  return flag ? 42 0; /* { dg-error "expected ':' before numeric
> constant" } */
> +  /* { dg-begin-multiline-output "" }
> +   return flag ? 42 0;
> +                   ^~
> +                   :
> +     { dg-end-multiline-output "" } */
> +}
> diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C
> b/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C
> index 833fab7..727e74e 100644
> --- a/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C
> +++ b/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C
> @@ -26,5 +26,5 @@ main()
>  }
>  
>  // { dg-error "exponent has no digits" "exponent has no digits" {
> target *-*-* } 21 }
> -// { dg-error "expected ';' before" "expected ';' before" { target
> *-*-* } 14 }
> -// { dg-error "expected ';' before" "expected ';' before" { target
> *-*-* } 25 }
> +// { dg-error "expected ';' before" "expected ';' before" { target
> *-*-* } 13 }
> +// { dg-error "expected ';' before" "expected ';' before" { target
> *-*-* } 24 }
> diff --git a/gcc/testsuite/g++.dg/cpp1y/pr65202.C
> b/gcc/testsuite/g++.dg/cpp1y/pr65202.C
> index 602b264..7ce4895 100644
> --- a/gcc/testsuite/g++.dg/cpp1y/pr65202.C
> +++ b/gcc/testsuite/g++.dg/cpp1y/pr65202.C
> @@ -22,5 +22,5 @@ struct bar;
>  int main()
>  {
>      foo<ns::bar> f;
> -    adl::swap(f, f)
> -} // { dg-error "" }
> +    adl::swap(f, f) // { dg-error "expected ';'" }
> +} // { dg-error "expected '.'" "expected end of namespace" }
> diff --git a/gcc/testsuite/g++.dg/missing-symbol-2.C
> b/gcc/testsuite/g++.dg/missing-symbol-2.C
> new file mode 100644
> index 0000000..4a119f8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/missing-symbol-2.C
> @@ -0,0 +1,58 @@
> +/* { dg-options "-fdiagnostics-show-caret" } */
> +
> +extern int foo (void);
> +
> +void missing_open_paren (void)
> +{
> +  if foo ()) /* { dg-error "expected '\\(' before 'foo'" } */
> +    {
> +    }
> +  /* { dg-begin-multiline-output "" }
> +   if foo ())
> +      ^~~
> +      (
> +     { dg-end-multiline-output "" } */
> +}
> +
> +
> +void missing_close_square (void)
> +{
> +  const char test [42;  /* { dg-error "22: expected ']' before ';'
> token" } */
> +  /* { dg-begin-multiline-output "" }
> +   const char test [42;
> +                      ^
> +                      ]
> +     { dg-end-multiline-output "" } */
> +}
> +
> +int missing_semicolon (void)
> +{
> +  return 42 /* { dg-error "expected ';'" } */
> +}
> +/* { dg-begin-multiline-output "" }
> +   return 42
> +            ^
> +            ;
> + }
> + ~           
> +   { dg-end-multiline-output "" } */
> +
> +
> +int missing_colon_in_switch (int val)
> +{
> +  switch (val)
> +    {
> +    case 42 /* { dg-error "expected ':' before 'return'" } */
> +      return 42;
> +    /* { dg-begin-multiline-output "" }
> +     case 42
> +            ^
> +            :
> +       return 42;
> +       ~~~~~~
> +       { dg-end-multiline-output "" } */
> +
> +    default:
> +      return val;
> +    }
> +}
> diff --git a/gcc/testsuite/g++.dg/other/do1.C
> b/gcc/testsuite/g++.dg/other/do1.C
> index b3a9daf..db65e7d 100644
> --- a/gcc/testsuite/g++.dg/other/do1.C
> +++ b/gcc/testsuite/g++.dg/other/do1.C
> @@ -7,7 +7,7 @@
>  
>  void init ()
>  {
> -  do {  } while (0)
> -         obj = 0; // { dg-error "expected|not declared" }
> +  do {  } while (0) // { dg-error "expected ';'" }
> +         obj = 0; // { dg-error "not declared" }
>       
>  }
> diff --git a/gcc/testsuite/g++.dg/parse/error11.C
> b/gcc/testsuite/g++.dg/parse/error11.C
> index d118c19..1a49d6e 100644
> --- a/gcc/testsuite/g++.dg/parse/error11.C
> +++ b/gcc/testsuite/g++.dg/parse/error11.C
> @@ -52,7 +52,7 @@ void func(void)
>    Foo[:B> k1;       // { dg-bogus "cannot begin|alternate spelling"
> "smart error should not be triggered here" } 
>  // { dg-error "6:missing template arguments before" "template" {
> target *-*-* } 51 }
>  // { dg-error "9:expected primary-expression before ':' token"
> "primary" { target *-*-* } 51 }
> -// { dg-error "9:expected '\]' before ':' token" "backslash" {
> target *-*-* } 51 }
> +// { dg-error "8:expected '\]' before ':' token" "backslash" {
> target *-*-* } 51 }
>  // { dg-error "6:missing template arguments before" "template" {
> target *-*-* } 52 }
>  // { dg-error "7:expected primary-expression before ':' token"
> "primary" { target *-*-* } 52 }
>  // { dg-error "7:expected '\]' before ':' token" "backslash" {
> target *-*-* } 52 }
> diff --git a/gcc/testsuite/g++.dg/template/error11.C
> b/gcc/testsuite/g++.dg/template/error11.C
> index 3a469fd..1640298 100644
> --- a/gcc/testsuite/g++.dg/template/error11.C
> +++ b/gcc/testsuite/g++.dg/template/error11.C
> @@ -1,4 +1,4 @@
>  // PR c++/12132
>  
>  inline template <int> void foo () {} // { dg-error "<" }
> -void abort (); // { dg-error ";" }
> +void abort (); // { dg-error ";" "" { target *-*-* } .-1 }
> diff --git a/gcc/testsuite/gcc.dg/missing-symbol-2.c
> b/gcc/testsuite/gcc.dg/missing-symbol-2.c
> new file mode 100644
> index 0000000..7ee795d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/missing-symbol-2.c
> @@ -0,0 +1,71 @@
> +/* { dg-options "-fdiagnostics-show-caret -Wno-switch-unreachable" }
> */
> +
> +extern int foo (void);
> +
> +void missing_open_paren (void)
> +{
> +  if foo ()) /* { dg-line missing_open_paren } */
> +    {
> +    }
> +  /* { dg-error "expected '\\(' before 'foo'" "" { target c }
> missing_open_paren } */
> +  /* { dg-begin-multiline-output "" }
> +   if foo ())
> +      ^~~
> +      (
> +     { dg-end-multiline-output "" } */
> +  /* { dg-error "expected statement before '\\)' token"  "" { target
> c } missing_open_paren } */
> +  /* { dg-begin-multiline-output "" }
> +   if foo ())
> +            ^
> +     { dg-end-multiline-output "" } */
> +}
> +
> +void missing_close_square (void)
> +{
> +  const char test [42;  /* { dg-error "22: expected ']' before ';'
> token" } */
> +  /* { dg-begin-multiline-output "" }
> +   const char test [42;
> +                      ^
> +                      ]
> +     { dg-end-multiline-output "" } */
> +}
> +
> +int missing_semicolon (void)
> +{
> +  return 42 /* { dg-error "expected ';'" } */
> +}
> +/* { dg-begin-multiline-output "" }
> +   return 42
> +            ^
> +            ;
> + }
> + ~           
> +   { dg-end-multiline-output "" } */
> +
> +
> +/* We don't offer a fix-it hint for this case in C, as it could be
> +   colon or ellipsis.
> +   TODO: we could be smarter about error-recovery here; given the
> +   return perhaps we could assume a missing colon.  */
> +
> +int missing_colon_in_switch (int val)
> +{
> +  switch (val)
> +    {
> +    case 42
> +      return 42; /* { dg-error "expected ':' or '...' before
> 'return'" } */
> +    /* { dg-begin-multiline-output "" }
> +       return 42;
> +       ^~~~~~
> +       { dg-end-multiline-output "" } */
> +
> +    default:
> +      return val;
> +    }
> +}
> +
> +/* { dg-begin-multiline-output "" }
> + int dummy;
> + ^~~
> +   { dg-end-multiline-output "" } */
> +int dummy;/* { dg-error "expected declaration or statement at end of
> input" "" { target c } } */
> diff --git a/gcc/testsuite/gcc.dg/missing-symbol-3.c
> b/gcc/testsuite/gcc.dg/missing-symbol-3.c
> new file mode 100644
> index 0000000..e2d00df
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/missing-symbol-3.c
> @@ -0,0 +1,50 @@
> +/* { dg-options "-fdiagnostics-show-caret" } */
> +
> +/* A sequence of bogus _Static_assert.
> +   We can offer fix-it hints for some of these, but not all.  */
> +
> +void test_static_assert_1 (void)
> +{
> +  _Static_assert sizeof(int) >= sizeof(char); /* { dg-error
> "expected '\\(' before 'sizeof'" } */
> +  /* { dg-begin-multiline-output "" }
> +   _Static_assert sizeof(int) >= sizeof(char);
> +                  ^~~~~~
> +                  (
> +     { dg-end-multiline-output "" } */
> +}
> +
> +void test_static_assert_2 (void)
> +{
> +  _Static_assert(sizeof(int) >= sizeof(char); /* { dg-error
> "expected ',' before ';' token" } */
> +  /* { dg-begin-multiline-output "" }
> +   _Static_assert(sizeof(int) >= sizeof(char);
> +                                             ^
> +                                             ,
> +     { dg-end-multiline-output "" } */
> +}
> +
> +void test_static_assert_3 (void)
> +{
> +  _Static_assert(sizeof(int) >= sizeof(char),; /* { dg-error
> "expected string literal before ';' token" } */
> +  /* { dg-begin-multiline-output "" }
> +   _Static_assert(sizeof(int) >= sizeof(char),;
> +                                              ^
> +     { dg-end-multiline-output "" } */
> +}
> +
> +void test_static_assert_4 (void)
> +{
> +  _Static_assert(sizeof(int) >= sizeof(char), "msg"; /* { dg-error
> "expected '\\)' before ';' token" } */
> +  /* { dg-begin-multiline-output "" }
> +   _Static_assert(sizeof(int) >= sizeof(char), "msg";
> +                 ~                                  ^
> +                                                    )
> +     { dg-end-multiline-output "" } */
> +}
> +
> +/* The final one is correct.  */
> +
> +void test_static_assert_5 (void)
> +{
> +  _Static_assert(sizeof(int) >= sizeof(char), "msg");
> +}
> diff --git a/gcc/testsuite/gcc.dg/noncompile/940112-1.c
> b/gcc/testsuite/gcc.dg/noncompile/940112-1.c
> index bb5e0f6..0a9e07d 100644
> --- a/gcc/testsuite/gcc.dg/noncompile/940112-1.c
> +++ b/gcc/testsuite/gcc.dg/noncompile/940112-1.c
> @@ -3,5 +3,5 @@ f (int x)
>  {
>    double e = 1;
>    e = 1;
> -  return (e)
> -}    /* { dg-error "parse error|syntax error|expected" } */
> +  return (e) /* { dg-error "parse error|syntax error|expected" } */
> +}    
> diff --git a/gcc/testsuite/gcc.dg/noncompile/971104-1.c
> b/gcc/testsuite/gcc.dg/noncompile/971104-1.c
> index 39e00c6..4a04dad 100644
> --- a/gcc/testsuite/gcc.dg/noncompile/971104-1.c
> +++ b/gcc/testsuite/gcc.dg/noncompile/971104-1.c
> @@ -27,6 +27,6 @@ static void up(int sem){
>      printf("%s had processes sleeping on it!\n",
>      ({ "MUTEX     ", "BARB_SEM 1", "BARB_SEM 2", "CUST_SEM 1",
>         "CUST_SEM 2", "WAIT_SEM 1", "WAIT_SEM 2", "WAIT_SEM 3",
> -       "WAIT_SEM 4"}  /* { dg-error "parse error|syntax
> error|expected" } */
> -     [( sb.sem_num )]) ); /* { dg-error "expected" } */
> +       "WAIT_SEM 4"}  /* { dg-error "expected" } */
> +     [( sb.sem_num )]) );
>  }
> diff --git a/gcc/testsuite/obj-c++.dg/exceptions-6.mm
> b/gcc/testsuite/obj-c++.dg/exceptions-6.mm
> index 58882fe..6f6ba78 100644
> --- a/gcc/testsuite/obj-c++.dg/exceptions-6.mm
> +++ b/gcc/testsuite/obj-c++.dg/exceptions-6.mm
> @@ -11,15 +11,15 @@ void test (id object)
>    @throw object;   /* Ok */
>    @throw;          /* { dg-error ".@throw. .rethrow. used outside of
> a @catch block" } */
>    @throw (object); /* Ok.  */
> -  @throw (id)0
> -}                  /* { dg-error "expected" } */
> +  @throw (id)0     /* { dg-error "expected" } */
> +}
>  
>  void test2 (id object)
>  {
>    @throw object);  /* { dg-error "expected" } */
>    @throw (...);    /* { dg-error "expected" } */
>    @throw ();       /* { dg-error "expected" } */
> -  @throw           
> +  @throw           /* { dg-error "expected" } */
>  }                  /* { dg-error "expected" } */
>  
>  void test3 (id object1, id object2)
> diff --git a/gcc/testsuite/obj-c++.dg/pr48187.mm b/gcc/testsuite/obj-
> c++.dg/pr48187.mm
> index 750710b..99677a5 100644
> --- a/gcc/testsuite/obj-c++.dg/pr48187.mm
> +++ b/gcc/testsuite/obj-c++.dg/pr48187.mm
> @@ -1,19 +1,19 @@
>  /* { dg-do compile } */
>  
>  @interface A
> -{
> +{    /* { dg-error "xpected" } */
>    ]  /* { dg-error "xpected" } */
>  }
>  @end
>  
>  @interface B
> -{
> +{     /* { dg-error "xpected" } */
>    ];  /* { dg-error "xpected" } */
>  }
>  @end
>  
>  @interface C
> -{
> +{     /* { dg-error "xpected" } */
>    ];  /* { dg-error "xpected" } */
>    int x;
>  }
> @@ -21,7 +21,7 @@
>  
>  @interface D
>  {
> -  (
> +  (  /* { dg-error "xpected" } */
>  }  /* { dg-error "xpected" } */
>  @end
>  
> diff --git a/gcc/testsuite/objc.dg/exceptions-6.m
> b/gcc/testsuite/objc.dg/exceptions-6.m
> index 58882fe..74be98d 100644
> --- a/gcc/testsuite/objc.dg/exceptions-6.m
> +++ b/gcc/testsuite/objc.dg/exceptions-6.m
> @@ -11,8 +11,8 @@ void test (id object)
>    @throw object;   /* Ok */
>    @throw;          /* { dg-error ".@throw. .rethrow. used outside of
> a @catch block" } */
>    @throw (object); /* Ok.  */
> -  @throw (id)0
> -}                  /* { dg-error "expected" } */
> +  @throw (id)0     /* { dg-error "expected" } */
> +}
>  
>  void test2 (id object)
>  {

Reply via email to