]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
diagnostic: avoid repeating include path
authorJason Merrill <jason@redhat.com>
Fri, 17 Dec 2021 10:45:02 +0000 (05:45 -0500)
committerJason Merrill <jason@redhat.com>
Mon, 17 Jan 2022 16:58:12 +0000 (11:58 -0500)
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.

gcc/diagnostic.c
gcc/diagnostic.h
gcc/testsuite/c-c++-common/cpp/line-2.c
gcc/testsuite/c-c++-common/cpp/line-3.c

index 58139427d019626946efb28fb3b42418f870b1b7..5c02ff05882cee7f42dc32aa9a81291319b94700 100644 (file)
@@ -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);
        }
index 6739028a9312cd43348dd9fe2401e9811aa1a7b0..ccaa33b581721b1ef4b13071d5e816d40dff13b4 100644 (file)
@@ -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
index 97cf398f64cd122185c77f3b0b05b1a485c587da..364ad0e39318871ffb282fa0612c330aa029bd79 100644 (file)
@@ -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} }
index 2ffc44907a27cf502a9f1d978528985961603ab5..b254ae400419c1cf6d07698c95621eea2854b620 100644 (file)
@@ -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" }