[gcc r12-6642] diagnostic: avoid repeating include path

Jason Merrill jason@gcc.gnu.org
Mon Jan 17 16:59:24 GMT 2022


https://gcc.gnu.org/g:d3a57993359c9759990fe8f2aa4088684ed82190

commit r12-6642-gd3a57993359c9759990fe8f2aa4088684ed82190
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Dec 17 05:45:02 2021 -0500

    diagnostic: avoid repeating include path
    
    When a sequence of diagnostic messages bounces back and forth repeatedly
    between two includes, as with
    
     #include <map>
     std::map<const char*, const char*> m ("123", "456");
    
    The output is quite a bit longer than necessary because we dump the include
    path each time it changes.  I'd think we could print the include path once
    for each header file, and then expect that the user can look earlier in the
    output if they're wondering.
    
    gcc/ChangeLog:
    
            * diagnostic.h (struct diagnostic_context): Add includes_seen.
            * diagnostic.c (diagnostic_initialize): Initialize it.
            (diagnostic_finish): Clean it up.
            (includes_seen): New function.
            (diagnostic_report_current_module): Use it.
    
    gcc/testsuite/ChangeLog:
    
            * c-c++-common/cpp/line-2.c: Only expect includes once.
            * c-c++-common/cpp/line-3.c: Likewise.

Diff:
---
 gcc/diagnostic.h                        |  4 ++++
 gcc/diagnostic.c                        | 36 +++++++++++++++++++++++++++++++--
 gcc/testsuite/c-c++-common/cpp/line-2.c |  2 +-
 gcc/testsuite/c-c++-common/cpp/line-3.c |  2 +-
 4 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 6739028a931..ccaa33b5817 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -387,6 +387,10 @@ struct diagnostic_context
      the BLOCK_SUPERCONTEXT() chain hanging off the LOCATION_BLOCK()
      of a diagnostic's location.  */
   void (*set_locations_cb)(diagnostic_context *, diagnostic_info *);
+
+  /* Include files that diagnostic_report_current_module has already listed the
+     include path for.  */
+  hash_set<location_t, false, location_hash> *includes_seen;
 };
 
 static inline void
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 58139427d01..5c02ff05882 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -237,6 +237,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
   context->begin_group_cb = NULL;
   context->end_group_cb = NULL;
   context->final_cb = default_diagnostic_final_cb;
+  context->includes_seen = NULL;
 }
 
 /* Maybe initialize the color support. We require clients to do this
@@ -329,6 +330,12 @@ diagnostic_finish (diagnostic_context *context)
       delete context->edit_context_ptr;
       context->edit_context_ptr = NULL;
     }
+
+  if (context->includes_seen)
+    {
+      delete context->includes_seen;
+      context->includes_seen = nullptr;
+    }
 }
 
 /* Initialize DIAGNOSTIC, where the message MSG has already been
@@ -700,6 +707,31 @@ set_last_module (diagnostic_context *context, const line_map_ordinary *map)
   context->last_module = map;
 }
 
+/* Only dump the "In file included from..." stack once for each file.  */
+
+static bool
+includes_seen (diagnostic_context *context, const line_map_ordinary *map)
+{
+  /* No include path for main.  */
+  if (MAIN_FILE_P (map))
+    return true;
+
+  /* Always identify C++ modules, at least for now.  */
+  auto probe = map;
+  if (linemap_check_ordinary (map)->reason == LC_RENAME)
+    /* The module source file shows up as LC_RENAME inside LC_MODULE.  */
+    probe = linemap_included_from_linemap (line_table, map);
+  if (MAP_MODULE_P (probe))
+    return false;
+
+  if (!context->includes_seen)
+    context->includes_seen = new hash_set<location_t, false, location_hash>;
+
+  /* Hash the location of the #include directive to better handle files
+     that are included multiple times with different macros defined.  */
+  return context->includes_seen->add (linemap_included_from (map));
+}
+
 void
 diagnostic_report_current_module (diagnostic_context *context, location_t where)
 {
@@ -721,7 +753,7 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where)
   if (map && last_module_changed_p (context, map))
     {
       set_last_module (context, map);
-      if (! MAIN_FILE_P (map))
+      if (!includes_seen (context, map))
 	{
 	  bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
 	  expanded_location s = {};
@@ -760,7 +792,7 @@ diagnostic_report_current_module (diagnostic_context *context, location_t where)
 			   "locus", s.file, line_col);
 	      first = false, need_inc = was_module, was_module = is_module;
 	    }
-	  while (! MAIN_FILE_P (map));
+	  while (!includes_seen (context, map));
 	  pp_verbatim (context->printer, ":");
 	  pp_newline (context->printer);
 	}
diff --git a/gcc/testsuite/c-c++-common/cpp/line-2.c b/gcc/testsuite/c-c++-common/cpp/line-2.c
index 97cf398f64c..364ad0e3931 100644
--- a/gcc/testsuite/c-c++-common/cpp/line-2.c
+++ b/gcc/testsuite/c-c++-common/cpp/line-2.c
@@ -8,4 +8,4 @@ int line4;
 
 // { dg-regexp {In file included from <command-line>:\n[^\n]*/line-2.h:4:2: error: #error wrong\n} }
 
-// { dg-regexp {[^\n]*/line-2.c:3:11: error: macro "bill" passed 1 arguments, but takes just 0\nIn file included from <command-line>:\n[^\n]*/line-2.h:3: note: macro "bill" defined here\n} }
+// { dg-regexp {[^\n]*/line-2.c:3:11: error: macro "bill" passed 1 arguments, but takes just 0\n[^\n]*/line-2.h:3: note: macro "bill" defined here\n} }
diff --git a/gcc/testsuite/c-c++-common/cpp/line-3.c b/gcc/testsuite/c-c++-common/cpp/line-3.c
index 2ffc44907a2..b254ae40041 100644
--- a/gcc/testsuite/c-c++-common/cpp/line-3.c
+++ b/gcc/testsuite/c-c++-common/cpp/line-3.c
@@ -15,6 +15,6 @@ int line4;
 
 // { dg-regexp {In file included from <command-line>:\n[^\n]*/line-2.h:4:2: error: #error wrong\n} }
 
-// { dg-regexp {[^\n]*/line-3.c:3:11: error: macro "bill" passed 1 arguments, but takes just 0\nIn file included from <command-line>:\n[^\n]*/line-2.h:3: note: macro "bill" defined here\n} }
+// { dg-regexp {[^\n]*/line-3.c:3:11: error: macro "bill" passed 1 arguments, but takes just 0\n[^\n]*/line-2.h:3: note: macro "bill" defined here\n} }
 
 // { dg-options "-fpreprocessed -fdirectives-only" }


More information about the Gcc-cvs mailing list