From 2483ce1569849e497ae91de7542febf908ec5f37 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 14 Jun 2016 15:14:48 -0400
Subject: [PATCH 16/38] Add fixit hint for -Wendif-labels

gcc/testsuite/ChangeLog:
	* c-c++-common/Wendif-labels.c: New test case.

libcpp/ChangeLog:
	* directives.c (check_eol_1): Emit a fixit hint for a
	C++-style comment when warning about trailing tokens.
	* errors.c (cpp_diagnostic): Move logic for determining
	the source_location to...
	(cpp_get_source_location): New function.
	(cpp_diagnostic_at_richloc): New function.
	(cpp_pedwarning_at_richloc): New function.
	* include/cpplib.h (cpp_get_source_location): New prototype.
	(cpp_pedwarning_at_richloc): New prototype.
---
 gcc/testsuite/c-c++-common/Wendif-labels.c | 11 +++++
 libcpp/directives.c                        | 10 +++-
 libcpp/errors.c                            | 77 ++++++++++++++++++++++++------
 libcpp/include/cpplib.h                    |  9 ++++
 4 files changed, 91 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/Wendif-labels.c

diff --git a/gcc/testsuite/c-c++-common/Wendif-labels.c b/gcc/testsuite/c-c++-common/Wendif-labels.c
new file mode 100644
index 0000000..01bf99b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wendif-labels.c
@@ -0,0 +1,11 @@
+/* { dg-options "-Wendif-labels -fdiagnostics-show-caret" } */
+
+/* Ensure that we emit a fixit hint for -Wendif-labels.  */
+#if 1
+#endif foo /* { dg-warning "extra tokens" } */
+/* { dg-begin-multiline-output "" }
+ #endif foo
+        ^~~
+        // 
+   { dg-end-multiline-output "" } */
+
diff --git a/libcpp/directives.c b/libcpp/directives.c
index c0006a4..a847b4b 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -232,8 +232,14 @@ check_eol_1 (cpp_reader *pfile, bool expand, int reason)
   if (! SEEN_EOL () && (expand
 			? cpp_get_token (pfile)
 			: _cpp_lex_token (pfile))->type != CPP_EOF)
-    cpp_pedwarning (pfile, reason, "extra tokens at end of #%s directive",
-		    pfile->directive->name);
+    {
+      source_location src_loc = cpp_get_source_location (pfile);
+      rich_location richloc (pfile->line_table, src_loc);
+      richloc.add_fixit_insert (src_loc, "// ");
+      cpp_pedwarning_at_richloc (pfile, reason, &richloc,
+				 "extra tokens at end of #%s directive",
+				 pfile->directive->name);
+    }
 }
 
 /* Variant of check_eol used for Wendif-labels warnings.  */
diff --git a/libcpp/errors.c b/libcpp/errors.c
index 3b0a0b4..b19ce96 100644
--- a/libcpp/errors.c
+++ b/libcpp/errors.c
@@ -62,33 +62,48 @@ cpp_diagnostic_at (cpp_reader * pfile, int level, int reason,
   return ret;
 }
 
-/* Print a diagnostic at the location of the previously lexed token.  */
+/* Return the location of the previously lexed token.  */
 
-ATTRIBUTE_FPTR_PRINTF(4,0)
-static bool
-cpp_diagnostic (cpp_reader * pfile, int level, int reason,
-                const char *msgid, va_list *ap)
+source_location
+cpp_get_source_location (cpp_reader * pfile)
 {
-  source_location src_loc;
-
   if (CPP_OPTION (pfile, traditional))
     {
       if (pfile->state.in_directive)
-	src_loc = pfile->directive_line;
+	return pfile->directive_line;
       else
-	src_loc = pfile->line_table->highest_line;
+	return pfile->line_table->highest_line;
     }
   /* We don't want to refer to a token before the beginning of the
      current run -- that is invalid.  */
   else if (pfile->cur_token == pfile->cur_run->base)
     {
-      src_loc = 0;
+      return 0;
     }
   else
     {
-      src_loc = pfile->cur_token[-1].src_loc;
+      return pfile->cur_token[-1].src_loc;
     }
-  return cpp_diagnostic_at (pfile, level, reason, src_loc, msgid, ap);
+}
+
+/* Print a diagnostic at the location of the previously lexed token.  */
+
+ATTRIBUTE_FPTR_PRINTF(4,0)
+static bool
+cpp_diagnostic (cpp_reader * pfile, int level, int reason,
+                const char *msgid, va_list *ap)
+{
+  source_location src_loc;
+  bool ret;
+
+  src_loc = cpp_get_source_location (pfile);
+
+  if (!pfile->cb.error)
+    abort ();
+  rich_location richloc (pfile->line_table, src_loc);
+  ret = pfile->cb.error (pfile, level, reason, &richloc, _(msgid), ap);
+
+  return ret;
 }
 
 /* Print a warning or error, depending on the value of LEVEL.  */
@@ -260,13 +275,47 @@ bool
 cpp_error_at (cpp_reader * pfile, int level, source_location src_loc,
 	      const char *msgid, ...)
 {
+   va_list ap;
+   bool ret;
+
+   va_start (ap, msgid);
+
+   ret = cpp_diagnostic_at (pfile, level, CPP_W_NONE, src_loc,
+			    msgid, &ap);
+   va_end (ap);
+   return ret;
+}
+
+/* Print a diagnostic at a specific rich location.  */
+
+ATTRIBUTE_FPTR_PRINTF(5,0)
+static bool
+cpp_diagnostic_at_richloc (cpp_reader * pfile, int level, int reason,
+			   rich_location *richloc, const char *msgid,
+			   va_list *ap)
+{
+  bool ret;
+
+  if (!pfile->cb.error)
+    abort ();
+  ret = pfile->cb.error (pfile, level, reason, richloc, _(msgid), ap);
+
+  return ret;
+}
+
+/* As cpp_pedwarning, but use RICHLOC for the location of the warning.  */
+
+bool
+cpp_pedwarning_at_richloc (cpp_reader * pfile, int reason,
+			   rich_location *richloc, const char *msgid, ...)
+{
   va_list ap;
   bool ret;
 
   va_start (ap, msgid);
 
-  ret = cpp_diagnostic_at (pfile, level, CPP_W_NONE, src_loc,
-			   msgid, &ap);
+  ret = cpp_diagnostic_at_richloc (pfile, CPP_DL_PEDWARN, reason, richloc,
+				   msgid, &ap);
 
   va_end (ap);
   return ret;
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index cfc6ccd..80a2894 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -1038,6 +1038,9 @@ enum {
   CPP_W_CXX11_COMPAT
 };
 
+/* Return the location of the previously lexed token.  */
+extern source_location cpp_get_source_location (cpp_reader *);
+
 /* Output a diagnostic of some kind.  */
 extern bool cpp_error (cpp_reader *, int, const char *msgid, ...)
   ATTRIBUTE_PRINTF_3;
@@ -1081,6 +1084,12 @@ extern bool cpp_error_at_richloc (cpp_reader * pfile, int level,
 				  ...)
   ATTRIBUTE_PRINTF_4;
 
+/* As cpp_pedwarning, but use the rich_location for the location of the
+   warning.  */
+extern bool cpp_pedwarning_at_richloc (cpp_reader *, int, rich_location *,
+				       const char *msgid, ...)
+  ATTRIBUTE_PRINTF_4;
+
 /* In lex.c */
 extern int cpp_ideq (const cpp_token *, const char *);
 extern void cpp_output_line (cpp_reader *, FILE *);
-- 
1.8.5.3

