aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2015-12-16 18:15:01 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2015-12-16 18:15:01 +0000
commitde67c4c37913cb4f30cc0d5163665ab8419ac2ed (patch)
tree631c0d4e81b08a923db1179b2753d0d62d53bd9c /gcc/cp
parent8a69b8590383788dc5da60693b3a48f8222a2893 (diff)
downloadgcc-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/ChangeLog6
-rw-r--r--gcc/cp/parser.c53
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