From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13357 invoked by alias); 11 Oct 2017 17:26:29 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 12244 invoked by uid 89); 11 Oct 2017 17:26:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=underline, Here's, Heres X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 11 Oct 2017 17:26:24 +0000 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C3D727F6A2 for ; Wed, 11 Oct 2017 17:26:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com C3D727F6A2 Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx01.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=dmalcolm@redhat.com Received: from ovpn-116-23.phx2.redhat.com (ovpn-116-23.phx2.redhat.com [10.3.116.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id 54D9A784CA for ; Wed, 11 Oct 2017 17:26:22 +0000 (UTC) Message-ID: <1507742781.29092.35.camel@redhat.com> Subject: PING Re: [PATCH 2/2] C/C++: add fix-it hints for various missing symbols (v3) From: David Malcolm To: gcc-patches@gcc.gnu.org Date: Wed, 11 Oct 2017 17:27:00 -0000 In-Reply-To: <1507219711-60081-1-git-send-email-dmalcolm@redhat.com> References: <1506434179-2736-3-git-send-email-dmalcolm@redhat.com> <1507219711-60081-1-git-send-email-dmalcolm@redhat.com> Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2017-10/txt/msg00689.txt.bz2 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 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 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) > {