Message ID | 1530212246-41069-1-git-send-email-dmalcolm@redhat.com |
---|---|
State | New |
Headers | show |
Series | C++: less verbose error-recovery for version conflict markers | expand |
OK. On Thu, Jun 28, 2018 at 2:57 PM, David Malcolm <dmalcolm@redhat.com> wrote: > We handle version conflict markers in source: > > $ cat /tmp/test.cc > > extern void f1 (void); > extern void f2 (void); > extern void f3 (void); > extern void f4 (void); > > void test () > { > f1 (); > <<<<<<< HEAD > f2 (); > ======= > f3 (); >>>>>>>> 252be53... Some commit message > f4 (); > } > > The C frontend's output is mostly reasonable: > > gcc -xc /tmp/test.cc > /tmp/test.cc: In function ‘test’: > /tmp/test.cc:9:1: error: version control conflict marker in file > <<<<<<< HEAD > ^~~~~~~ > /tmp/test.cc:11:1: error: version control conflict marker in file > ======= > ^~~~~~~ > /tmp/test.cc:13:1: error: version control conflict marker in file > >>>>>>> 252be53... Some commit message > ^~~~~~~ > /tmp/test.cc:13:9: error: invalid suffix "be53..." on integer constant > >>>>>>> 252be53... Some commit message > ^~~~~~~~~~ > > whereas in C++ the output can be very verbose: > > /tmp/test.cc: In function ‘void test()’: > /tmp/test.cc:9:1: error: version control conflict marker in file > <<<<<<< HEAD > ^~~~~~~ > /tmp/test.cc:9:3: error: expected primary-expression before ‘<<’ token > <<<<<<< HEAD > ^~ > /tmp/test.cc:9:5: error: expected primary-expression before ‘<<’ token > <<<<<<< HEAD > ^~ > /tmp/test.cc:9:7: error: expected primary-expression before ‘<’ token > <<<<<<< HEAD > ^ > /tmp/test.cc:9:9: error: ‘HEAD’ was not declared in this scope > <<<<<<< HEAD > ^~~~ > /tmp/test.cc:11:1: error: version control conflict marker in file > ======= > ^~~~~~~ > /tmp/test.cc:11:3: error: expected primary-expression before ‘==’ token > ======= > ^~ > /tmp/test.cc:11:5: error: expected primary-expression before ‘==’ token > ======= > ^~ > /tmp/test.cc:11:7: error: expected primary-expression before ‘=’ token > ======= > ^ > /tmp/test.cc:13:1: error: version control conflict marker in file > >>>>>>> 252be53... Some commit message > ^~~~~~~ > /tmp/test.cc:13:3: error: expected primary-expression before ‘>>’ token > >>>>>>> 252be53... Some commit message > ^~ > /tmp/test.cc:13:5: error: expected primary-expression before ‘>>’ token > >>>>>>> 252be53... Some commit message > ^~ > /tmp/test.cc:13:7: error: expected primary-expression before ‘>’ token > >>>>>>> 252be53... Some commit message > ^ > /tmp/test.cc:13:9: error: unable to find numeric literal operator ‘operator""be53...’ > >>>>>>> 252be53... Some commit message > ^~~~~~~~~~ > > The following patch eliminates this spew by consuming tokens until the > start of the next line after emitting such a message. > > The C frontend and C++ with -std=c++98 both emit: > error: invalid suffix "be53..." on integer constant > on the above testcase, but it's not fixable through this approach, > since that error is emitted by the lexer. > > > Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. > > OK for trunk? > > gcc/cp/ChangeLog: > * parser.c (cp_parser_error_1): After issuing a conflict marker > error, consume tokens until the end of the source line. > > gcc/testsuite/ChangeLog: > * g++.dg/conflict-markers-2.C: New test. > --- > gcc/cp/parser.c | 14 ++++++++++++++ > gcc/testsuite/g++.dg/conflict-markers-2.C | 17 +++++++++++++++++ > 2 files changed, 31 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/conflict-markers-2.C > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index 154729c..09d224f 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -2862,6 +2862,20 @@ cp_parser_error_1 (cp_parser* parser, const char* gmsgid, > if (cp_lexer_peek_conflict_marker (parser->lexer, token->type, &loc)) > { > error_at (loc, "version control conflict marker in file"); > + expanded_location token_exploc = expand_location (token->location); > + /* Consume tokens until the end of the source line. */ > + while (1) > + { > + cp_lexer_consume_token (parser->lexer); > + cp_token *next = cp_lexer_peek_token (parser->lexer); > + if (next == NULL) > + break; > + expanded_location next_exploc = expand_location (next->location); > + if (next_exploc.file != token_exploc.file) > + break; > + if (next_exploc.line != token_exploc.line) > + break; > + } > return; > } > } > diff --git a/gcc/testsuite/g++.dg/conflict-markers-2.C b/gcc/testsuite/g++.dg/conflict-markers-2.C > new file mode 100644 > index 0000000..4fc3820 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/conflict-markers-2.C > @@ -0,0 +1,17 @@ > +// { dg-do compile { target c++11 } } > + > +extern void f1 (void); > +extern void f2 (void); > +extern void f3 (void); > +extern void f4 (void); > + > +void test () > +{ > + f1 (); > +<<<<<<< HEAD // { dg-error "conflict marker" } > + f2 (); > +======= // { dg-error "conflict marker" } > + f3 (); > +>>>>>>> 252be53... Some commit message // { dg-error "conflict marker" } > + f4 (); > +} > -- > 1.8.5.3 >
======= f3 (); >>>>>>> 252be53... Some commit message f4 (); } The C frontend's output is mostly reasonable: gcc -xc /tmp/test.cc /tmp/test.cc: In function ‘test’: /tmp/test.cc:9:1: error: version control conflict marker in file <<<<<<< HEAD ^~~~~~~ /tmp/test.cc:11:1: error: version control conflict marker in file ======= ^~~~~~~ /tmp/test.cc:13:1: error: version control conflict marker in file >>>>>>> 252be53... Some commit message ^~~~~~~ /tmp/test.cc:13:9: error: invalid suffix "be53..." on integer constant >>>>>>> 252be53... Some commit message ^~~~~~~~~~ whereas in C++ the output can be very verbose: /tmp/test.cc: In function ‘void test()’: /tmp/test.cc:9:1: error: version control conflict marker in file <<<<<<< HEAD ^~~~~~~ /tmp/test.cc:9:3: error: expected primary-expression before ‘<<’ token <<<<<<< HEAD ^~ /tmp/test.cc:9:5: error: expected primary-expression before ‘<<’ token <<<<<<< HEAD ^~ /tmp/test.cc:9:7: error: expected primary-expression before ‘<’ token <<<<<<< HEAD ^ /tmp/test.cc:9:9: error: ‘HEAD’ was not declared in this scope <<<<<<< HEAD ^~~~ /tmp/test.cc:11:1: error: version control conflict marker in file ======= ^~~~~~~ /tmp/test.cc:11:3: error: expected primary-expression before ‘==’ token ======= ^~ /tmp/test.cc:11:5: error: expected primary-expression before ‘==’ token ======= ^~ /tmp/test.cc:11:7: error: expected primary-expression before ‘=’ token ======= ^ /tmp/test.cc:13:1: error: version control conflict marker in file >>>>>>> 252be53... Some commit message ^~~~~~~ /tmp/test.cc:13:3: error: expected primary-expression before ‘>>’ token >>>>>>> 252be53... Some commit message ^~ /tmp/test.cc:13:5: error: expected primary-expression before ‘>>’ token >>>>>>> 252be53... Some commit message ^~ /tmp/test.cc:13:7: error: expected primary-expression before ‘>’ token >>>>>>> 252be53... Some commit message ^ /tmp/test.cc:13:9: error: unable to find numeric literal operator ‘operator""be53...’ >>>>>>> 252be53... Some commit message ^~~~~~~~~~ The following patch eliminates this spew by consuming tokens until the start of the next line after emitting such a message. The C frontend and C++ with -std=c++98 both emit: error: invalid suffix "be53..." on integer constant on the above testcase, but it's not fixable through this approach, since that error is emitted by the lexer. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. OK for trunk? gcc/cp/ChangeLog: * parser.c (cp_parser_error_1): After issuing a conflict marker error, consume tokens until the end of the source line. gcc/testsuite/ChangeLog: * g++.dg/conflict-markers-2.C: New test. --- gcc/cp/parser.c | 14 ++++++++++++++ gcc/testsuite/g++.dg/conflict-markers-2.C | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 gcc/testsuite/g++.dg/conflict-markers-2.C diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 154729c..09d224f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2862,6 +2862,20 @@ cp_parser_error_1 (cp_parser* parser, const char* gmsgid, if (cp_lexer_peek_conflict_marker (parser->lexer, token->type, &loc)) { error_at (loc, "version control conflict marker in file"); + expanded_location token_exploc = expand_location (token->location); + /* Consume tokens until the end of the source line. */ + while (1) + { + cp_lexer_consume_token (parser->lexer); + cp_token *next = cp_lexer_peek_token (parser->lexer); + if (next == NULL) + break; + expanded_location next_exploc = expand_location (next->location); + if (next_exploc.file != token_exploc.file) + break; + if (next_exploc.line != token_exploc.line) + break; + } return; } } diff --git a/gcc/testsuite/g++.dg/conflict-markers-2.C b/gcc/testsuite/g++.dg/conflict-markers-2.C new file mode 100644 index 0000000..4fc3820 --- /dev/null +++ b/gcc/testsuite/g++.dg/conflict-markers-2.C @@ -0,0 +1,17 @@ +// { dg-do compile { target c++11 } } + +extern void f1 (void); +extern void f2 (void); +extern void f3 (void); +extern void f4 (void); + +void test () +{ + f1 (); +<<<<<<< HEAD // { dg-error "conflict marker" } + f2 (); +======= // { dg-error "conflict marker" } + f3 (); +>>>>>>> 252be53... Some commit message // { dg-error "conflict marker" } + f4 (); +}