From 3c3392928de54678e6b1d15ab2cfa039d9dd6630 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 24 Aug 2018 17:23:09 -0400
Subject: [PATCH 05/49] FIXME: fix locations of maybe_add_include_fixit (move
 to before "C: Ensure that we print include hints in
 -Wimplicit-function-declaration")

Improves:

  ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:87:22: note: message
   73 | # include <debug/vector>
  +++ |+#include <vector>
   74 | #endif
  ....
   87 |       using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>;
      |                      ^~~

to:

  ../x86_64-pc-linux-gnu/libstdc++-v3/include/vector:87:22: note: message
   73 | # include <debug/vector>
  +++ |+#include <vector>
   74 | #endif
      | ^

eliminating the repetition of the location.

FIXME: can we get rid of that caret?  Setting show caret == false
just turns it into a tilde.
---
 gcc/c-family/c-common.c                           | 13 +++++++++++--
 gcc/c-family/c-common.h                           |  2 +-
 gcc/c-family/known-headers.cc                     |  2 +-
 gcc/c/c-decl.c                                    |  2 +-
 gcc/cp/name-lookup.c                              |  2 +-
 gcc/cp/pt.c                                       |  2 +-
 gcc/cp/rtti.c                                     |  2 +-
 gcc/testsuite/gcc.dg/fixits-pr84852-1.c           |  6 ++----
 gcc/testsuite/gcc.dg/fixits-pr84852-2.c           |  6 ++----
 gcc/testsuite/gcc.dg/missing-header-fixit-FIXME.c | 22 ++++++++++++++++++++++
 10 files changed, 43 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/missing-header-fixit-FIXME.c

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 95cff21..6afa15c 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -8477,10 +8477,16 @@ static added_includes_t *added_includes;
    location.
 
    This function is idempotent: a header will be added at most once to
-   any given file.  */
+   any given file.
+
+   If OVERRIDE_LOCATION is true, then if a fix-it is added and will be
+   printed, then RICHLOC's primary location will be replaced by that of
+   the fix-it hint (for use by "inform" notes where the location of the
+   issue has already been reported).  */
 
 void
-maybe_add_include_fixit (rich_location *richloc, const char *header)
+maybe_add_include_fixit (rich_location *richloc, const char *header,
+			 bool override_location)
 {
   location_t loc = richloc->get_loc ();
   const char *file = LOCATION_FILE (loc);
@@ -8508,6 +8514,9 @@ maybe_add_include_fixit (rich_location *richloc, const char *header)
   char *text = xasprintf ("#include %s\n", header);
   richloc->add_fixit_insert_before (include_insert_loc, text);
   free (text);
+
+  if (override_location && global_dc->show_caret)
+    richloc->set_range (0, include_insert_loc, true);
 }
 
 /* Attempt to convert a braced array initializer list CTOR for array
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 9b05e60..c5e2028 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1327,7 +1327,7 @@ excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method);
 extern int c_flt_eval_method (bool ts18661_p);
 extern void add_no_sanitize_value (tree node, unsigned int flags);
 
-extern void maybe_add_include_fixit (rich_location *, const char *);
+extern void maybe_add_include_fixit (rich_location *, const char *, bool);
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc
index 5524d21..b0763cf 100644
--- a/gcc/c-family/known-headers.cc
+++ b/gcc/c-family/known-headers.cc
@@ -192,7 +192,7 @@ suggest_missing_header::~suggest_missing_header ()
     return;
 
   gcc_rich_location richloc (get_location ());
-  maybe_add_include_fixit (&richloc, m_header_hint);
+  maybe_add_include_fixit (&richloc, m_header_hint, true);
   inform (&richloc,
 	  "%qs is defined in header %qs;"
 	  " did you forget to %<#include %s%>?",
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 9524977..2fcf429 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -3445,7 +3445,7 @@ implicitly_declare (location_t loc, tree functionid)
 		  if (header != NULL && warned)
 		    {
 		      rich_location richloc (line_table, loc);
-		      maybe_add_include_fixit (&richloc, header);
+		      maybe_add_include_fixit (&richloc, header, true);
 		      inform (&richloc,
 			      "include %qs or provide a declaration of %qD",
 			      header, decl);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8c7f685..540ff21 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -5630,7 +5630,7 @@ maybe_suggest_missing_std_header (location_t location, tree name)
   if (cxx_dialect >= header_hint->min_dialect)
     {
       const char *header = header_hint->header;
-      maybe_add_include_fixit (&richloc, header);
+      maybe_add_include_fixit (&richloc, header, true);
       inform (&richloc,
 	      "%<std::%s%> is defined in header %qs;"
 	      " did you forget to %<#include %s%>?",
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index efed9a1..a7266e3 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -26077,7 +26077,7 @@ listify (tree arg)
   if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
     {    
       gcc_rich_location richloc (input_location);
-      maybe_add_include_fixit (&richloc, "<initializer_list>");
+      maybe_add_include_fixit (&richloc, "<initializer_list>", false);
       error_at (&richloc,
 		"deducing from brace-enclosed initializer list"
 		" requires %<#include <initializer_list>%>");
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 6692fb7..94a9219 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -317,7 +317,7 @@ typeid_ok_p (void)
   if (!COMPLETE_TYPE_P (const_type_info_type_node))
     {
       gcc_rich_location richloc (input_location);
-      maybe_add_include_fixit (&richloc, "<typeinfo>");
+      maybe_add_include_fixit (&richloc, "<typeinfo>", false);
       error_at (&richloc,
 		"must %<#include <typeinfo>%> before using"
 		" %<typeid%>");
diff --git a/gcc/testsuite/gcc.dg/fixits-pr84852-1.c b/gcc/testsuite/gcc.dg/fixits-pr84852-1.c
index 98087ab..80098de 100644
--- a/gcc/testsuite/gcc.dg/fixits-pr84852-1.c
+++ b/gcc/testsuite/gcc.dg/fixits-pr84852-1.c
@@ -13,13 +13,11 @@
 int foo (void) { return strlen(""); }
 
 /* { dg-warning "incompatible implicit declaration of built-in function 'strlen'" "" { target *-*-* } -812156810 } */
-/* { dg-message "include '<string.h>' or provide a declaration of 'strlen'" "" { target *-*-* } -812156810 } */
+/* { dg-message "include '<string.h>' or provide a declaration of 'strlen'" "" { target *-*-* } 1 } */
 #if 0
 { dg-begin-multiline-output "" }
 +#include <string.h>
  /* This is padding (to avoid the output containing DejaGnu directives).  */
+ ^
 { dg-end-multiline-output "" }
 #endif
-
-/* We need this, to consume a stray line marker for the bogus line.  */
-/* { dg-regexp ".*fixits-pr84852-1.c:-812156810:25:" } */
diff --git a/gcc/testsuite/gcc.dg/fixits-pr84852-2.c b/gcc/testsuite/gcc.dg/fixits-pr84852-2.c
index 0674ef5..fd6ecd1 100644
--- a/gcc/testsuite/gcc.dg/fixits-pr84852-2.c
+++ b/gcc/testsuite/gcc.dg/fixits-pr84852-2.c
@@ -13,13 +13,11 @@
 int foo (void) { return strlen(""); }
 
 /* { dg-warning "incompatible implicit declaration of built-in function 'strlen'" "" { target *-*-* } -812156810 } */
-/* { dg-message "include '<string.h>' or provide a declaration of 'strlen'" "" { target *-*-* } -812156810 } */
+/* { dg-message "include '<string.h>' or provide a declaration of 'strlen'" "" { target *-*-* } 1 } */
 #if 0
 { dg-begin-multiline-output "" }
 +#include <string.h>
  /* This is padding (to avoid the output containing DejaGnu directives).  */
+ ^
 { dg-end-multiline-output "" }
 #endif
-
-/* We need this, to consume a stray line marker for the bogus line.  */
-/* { dg-regexp ".*fixits-pr84852-2.c:-812156810:25:" } */
diff --git a/gcc/testsuite/gcc.dg/missing-header-fixit-FIXME.c b/gcc/testsuite/gcc.dg/missing-header-fixit-FIXME.c
new file mode 100644
index 0000000..e958c2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/missing-header-fixit-FIXME.c
@@ -0,0 +1,22 @@
+/* Example of a fix-it hint that adds a #include directive,
+   adding them to the top of the file, given that there is no
+   pre-existing #include.  */
+
+/* { dg-options "-fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } */
+
+void test (int i, int j)
+{
+  printf ("%i of %i\n", i, j); /* { dg-line printf } */
+  /* { dg-warning "implicit declaration of function" "" { target *-*-* } printf } */
+  /* { dg-warning "incompatible implicit declaration" "" { target *-*-* } printf } */
+  /* { dg-begin-multiline-output "" }
+9 |   printf ("%i of %i\n", i, j);
+  |   ^~~~~~
+   { dg-end-multiline-output "" } */
+  /* { dg-message "include '<stdio.h>' or provide a declaration of 'printf'" "" { target *-*-* } 1 } */
+  /* { dg-begin-multiline-output "" }
++ |+#include <stdio.h>
+1 | /* Example of a fix-it hint that adds a #include directive,
+  | ^
+   { dg-end-multiline-output "" } */
+}
-- 
1.8.5.3

