diff mbox series

C++: less verbose error-recovery for version conflict markers

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

Commit Message

David Malcolm June 28, 2018, 6:57 p.m. UTC
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 ();

Comments

Jason Merrill June 28, 2018, 7:39 p.m. UTC | #1
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
>
diff mbox series

Patch

=======
  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 ();
+}