From c63377792da375e237b68a95b20825a1256ab2a6 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Sun, 28 Aug 2016 20:33:29 -0400
Subject: [PATCH 28/46] gcc 8: FIXME: C++ stray token fixits

---
 gcc/cp/parser.c               | 42 +++++++++++++++++++++++++++++++++---------
 gcc/testsuite/g++.dg/fixits.C | 24 ++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/fixits.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f7e88e1..471fa85 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2596,6 +2596,8 @@ static bool cp_parser_uncommitted_to_tentative_parse_p
   (cp_parser *);
 static void cp_parser_error
   (cp_parser *, const char *);
+static void cp_parser_error_stray_token
+  (cp_parser *, const char *);
 static void cp_parser_name_lookup_error
   (cp_parser *, tree, tree, name_lookup_error, location_t);
 static bool cp_parser_simulate_error
@@ -2813,6 +2815,23 @@ cp_parser_error (cp_parser* parser, const char* gmsgid)
     }
 }
 
+/* If not parsing tentatively, issue a diagnostic of the form
+      FILE:LINE: MESSAGE
+   with a fix-it hint suggesting the removal of the next token
+   in the input stream.  */
+
+static void
+cp_parser_error_stray_token (cp_parser* parser, const char* gmsgid)
+{
+  if (!cp_parser_simulate_error (parser))
+    {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      rich_location richloc (line_table, token->location);
+      richloc.add_fixit_remove ();
+      error_at_rich_loc (&richloc, gmsgid);
+    }
+}
+
 /* Issue an error about name-lookup failing.  NAME is the
    IDENTIFIER_NODE DECL is the result of
    the lookup (as returned from cp_parser_lookup_name).  DESIRED is
@@ -23700,8 +23719,9 @@ cp_parser_base_specifier (cp_parser* parser)
 	  /* If `virtual' appears more than once, issue an error.  */
 	  if (virtual_p && !duplicate_virtual_error_issued_p)
 	    {
-	      cp_parser_error (parser,
-			       "%<virtual%> specified more than once in base-specified");
+	      cp_parser_error_stray_token
+                (parser,
+                 "%<virtual%> specified more than once in base-specifier");
 	      duplicate_virtual_error_issued_p = true;
 	    }
 
@@ -23720,8 +23740,9 @@ cp_parser_base_specifier (cp_parser* parser)
 	  if (access != access_default_node
 	      && !duplicate_access_error_issued_p)
 	    {
-	      cp_parser_error (parser,
-			       "more than one access specifier in base-specified");
+	      cp_parser_error_stray_token
+                (parser,
+                 "more than one access specifier in base-specifier");
 	      duplicate_access_error_issued_p = true;
 	    }
 
@@ -23743,13 +23764,16 @@ cp_parser_base_specifier (cp_parser* parser)
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
       token = cp_lexer_peek_token (parser->lexer);
+      rich_location richloc (line_table, token->location);
+      richloc.add_fixit_remove ();
       if (!processing_template_decl)
-	error_at (token->location,
-		  "keyword %<typename%> not allowed outside of templates");
+	error_at_rich_loc
+	  (&richloc,
+	   "keyword %<typename%> not allowed outside of templates");
       else
-	error_at (token->location,
-		  "keyword %<typename%> not allowed in this context "
-		  "(the base class is implicitly a type)");
+	error_at_rich_loc (&richloc,
+			   "keyword %<typename%> not allowed in this context "
+			   "(the base class is implicitly a type)");
       cp_lexer_consume_token (parser->lexer);
     }
 
diff --git a/gcc/testsuite/g++.dg/fixits.C b/gcc/testsuite/g++.dg/fixits.C
new file mode 100644
index 0000000..eefb2d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/fixits.C
@@ -0,0 +1,24 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+struct b {};
+
+struct s1 : public virtual virtual b {}; // { dg-error "'virtual' specified more than once" }
+/* { dg-begin-multiline-output "" }
+ struct s1 : public virtual virtual b {};
+                            ^~~~~~~
+                            -------
+   { dg-end-multiline-output "" } */
+
+struct sub2 : public public b {}; // { dg-error "more than one access specifier" }
+/* { dg-begin-multiline-output "" }
+ struct sub2 : public public b {};
+                      ^~~~~~
+                      ------
+   { dg-end-multiline-output "" } */
+
+struct sub3: public typename b {}; // { dg-error "keyword .typename. not allowed outside of templates" }
+/* { dg-begin-multiline-output "" }
+ struct sub3: public typename b {};
+                     ^~~~~~~~
+                     --------
+   { dg-end-multiline-output "" } */
-- 
1.8.5.3

