From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 123771 invoked by alias); 26 Sep 2017 13:56:24 -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 123709 invoked by uid 89); 26 Sep 2017 13:56:23 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= 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; Tue, 26 Sep 2017 13:56:18 +0000 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9404B81DFD for ; Tue, 26 Sep 2017 13:56:17 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 9404B81DFD 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 c64.redhat.com (ovpn-112-11.phx2.redhat.com [10.3.112.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id 981726F95E; Tue, 26 Sep 2017 13:56:16 +0000 (UTC) From: David Malcolm To: Jeff Law , gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH 2/2] C/C++: add fix-it hints for various missing symbols (v2) Date: Tue, 26 Sep 2017 13:56:00 -0000 Message-Id: <1506434179-2736-3-git-send-email-dmalcolm@redhat.com> In-Reply-To: <1506434179-2736-1-git-send-email-dmalcolm@redhat.com> References: <1499107059-28855-1-git-send-email-dmalcolm@redhat.com> <1506434179-2736-1-git-send-email-dmalcolm@redhat.com> X-IsSubscribed: yes X-SW-Source: 2017-09/txt/msg01746.txt.bz2 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 copiesc 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 (struct c_parser): Add "previous_token_loc" field. (c_parser_consume_token): Set parser->previous_token_loc. (get_matching_symbol): Likewise. (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 | 29 +++- 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, 480 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 a36397b..20f9ed7 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -206,6 +206,9 @@ struct GTY(()) c_parser { /* Buffer to hold all the tokens from parsing the vector attribute for the SIMD-enabled functions (formerly known as elemental functions). */ vec *cilk_simd_fn_tokens; + + /* Location of the most-recently consumed token. */ + location_t previous_token_loc; }; /* Return a pointer to the Nth token in PARSERs tokens_buf. */ @@ -770,6 +773,7 @@ c_parser_consume_token (c_parser *parser) gcc_assert (parser->tokens[0].type != CPP_EOF); gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL); gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA); + parser->previous_token_loc = parser->tokens[0].location; if (parser->tokens != &parser->tokens_buf[0]) parser->tokens++; else if (parser->tokens_avail == 2) @@ -1037,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)) { @@ -1055,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->previous_token_loc); + /* If matching_location != UNKNOWN_LOCATION, highlight it. Attempt to consolidate diagnostics by printing it as a secondary range within the main diagnostic. */ @@ -3967,7 +3986,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; @@ -6393,7 +6413,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 56d9442..d831d66 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2785,6 +2785,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 @@ -2796,9 +2830,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, @@ -2837,6 +2874,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) { -- 1.8.5.3