diff options
author | David Malcolm <dmalcolm@redhat.com> | 2015-12-16 18:15:01 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2015-12-16 18:15:01 +0000 |
commit | de67c4c37913cb4f30cc0d5163665ab8419ac2ed (patch) | |
tree | 631c0d4e81b08a923db1179b2753d0d62d53bd9c /gcc/cp | |
parent | 8a69b8590383788dc5da60693b3a48f8222a2893 (diff) | |
download | gcc-de67c4c37913cb4f30cc0d5163665ab8419ac2ed.zip gcc-de67c4c37913cb4f30cc0d5163665ab8419ac2ed.tar.gz gcc-de67c4c37913cb4f30cc0d5163665ab8419ac2ed.tar.bz2 |
Better error recovery for merge-conflict markers
gcc/c-family/ChangeLog:
* c-common.h (conflict_marker_get_final_tok_kind): New prototype.
* c-lex.c (conflict_marker_get_final_tok_kind): New function.
gcc/c/ChangeLog:
* c-parser.c (struct c_parser): Expand array "tokens_buf" from 2
to 4.
(c_parser_peek_nth_token): New function.
(c_parser_peek_conflict_marker): New function.
(c_parser_error): Detect conflict markers and report them as such.
gcc/cp/ChangeLog:
* parser.c (cp_lexer_peek_conflict_marker): New function.
(cp_parser_error): Detect conflict markers and report them as
such.
gcc/testsuite/ChangeLog:
* c-c++-common/conflict-markers-1.c: New testcase.
* c-c++-common/conflict-markers-2.c: Likewise.
* c-c++-common/conflict-markers-3.c: Likewise.
* c-c++-common/conflict-markers-4.c: Likewise.
* c-c++-common/conflict-markers-5.c: Likewise.
* c-c++-common/conflict-markers-6.c: Likewise.
* c-c++-common/conflict-markers-7.c: Likewise.
* c-c++-common/conflict-markers-8.c: Likewise.
* c-c++-common/conflict-markers-9.c: Likewise.
* c-c++-common/conflict-markers-10.c: Likewise.
* c-c++-common/conflict-markers-11.c: Likewise.
* g++.dg/conflict-markers-1.C: Likewise.
From-SVN: r231712
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/parser.c | 53 |
2 files changed, 59 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a23d05f..a3a73a3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2015-12-16 David Malcolm <dmalcolm@redhat.com> + + * parser.c (cp_lexer_peek_conflict_marker): New function. + (cp_parser_error): Detect conflict markers and report them as + such. + 2015-12-15 Martin Sebor <msebor@redhat.com> c++/42121 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a420cf1..c1948c4 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2689,6 +2689,46 @@ cp_parser_is_keyword (cp_token* token, enum rid keyword) return token->keyword == keyword; } +/* Helper function for cp_parser_error. + Having peeked a token of kind TOK1_KIND that might signify + a conflict marker, peek successor tokens to determine + if we actually do have a conflict marker. + Specifically, we consider a run of 7 '<', '=' or '>' characters + at the start of a line as a conflict marker. + These come through the lexer as three pairs and a single, + e.g. three CPP_LSHIFT tokens ("<<") and a CPP_LESS token ('<'). + If it returns true, *OUT_LOC is written to with the location/range + of the marker. */ + +static bool +cp_lexer_peek_conflict_marker (cp_lexer *lexer, enum cpp_ttype tok1_kind, + location_t *out_loc) +{ + cp_token *token2 = cp_lexer_peek_nth_token (lexer, 2); + if (token2->type != tok1_kind) + return false; + cp_token *token3 = cp_lexer_peek_nth_token (lexer, 3); + if (token3->type != tok1_kind) + return false; + cp_token *token4 = cp_lexer_peek_nth_token (lexer, 4); + if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind)) + return false; + + /* It must be at the start of the line. */ + location_t start_loc = cp_lexer_peek_token (lexer)->location; + if (LOCATION_COLUMN (start_loc) != 1) + return false; + + /* We have a conflict marker. Construct a location of the form: + <<<<<<< + ^~~~~~~ + with start == caret, finishing at the end of the marker. */ + location_t finish_loc = get_finish (token4->location); + *out_loc = make_location (start_loc, start_loc, finish_loc); + + return true; +} + /* If not parsing tentatively, issue a diagnostic of the form FILE:LINE: MESSAGE before TOKEN where TOKEN is the next token in the input stream. MESSAGE @@ -2713,6 +2753,19 @@ cp_parser_error (cp_parser* parser, const char* gmsgid) return; } + /* If this is actually a conflict marker, report it as such. */ + if (token->type == CPP_LSHIFT + || token->type == CPP_RSHIFT + || token->type == CPP_EQ_EQ) + { + location_t loc; + if (cp_lexer_peek_conflict_marker (parser->lexer, token->type, &loc)) + { + error_at (loc, "version control conflict marker in file"); + return; + } + } + c_parse_error (gmsgid, /* Because c_parser_error does not understand CPP_KEYWORD, keywords are treated like |