public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [pushed 0/7] diagnostics: remove "tree" dependency from diagnostic paths
@ 2024-06-18 15:08 David Malcolm
  2024-06-18 15:08 ` [PATCH 1/7] diagnostics: move simple_diagnostic_{path,thread,event} to their own .h/cc David Malcolm
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: David Malcolm @ 2024-06-18 15:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

This patch kit removes the dependency on "tree" from diagnostic paths,
renaming tree-diagnostic-path.cc to diagnostic-path.cc.

I have an updated prototype of libdiagnostics that uses this to support
execution paths.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-1410-gf89f9c7ae7190c through
r15-1416-g524cdf4dab610e.

David Malcolm (7):
  diagnostics: move simple_diagnostic_{path,thread,event} to their own
    .h/cc
  diagnostics: eliminate "tree" from diagnostic_{event,path}
  diagnostics: remove tree usage from tree-diagnostic-path.cc
  diagnostics: eliminate diagnostic_context::m_make_json_for_path
  diagnostics: introduce diagnostic-macro-unwinding.h/cc
  diagnostics: eliminate diagnostic_context::m_print_path callback
  diagnostics: rename tree-diagnostic-path.cc to diagnostic-path.cc

 gcc/Makefile.in                               |   6 +-
 gcc/analyzer/checker-event.h                  |   2 +-
 gcc/analyzer/checker-path.cc                  |   8 +
 gcc/analyzer/checker-path.h                   |   5 +
 gcc/c-family/c-opts.cc                        |   2 +-
 gcc/diagnostic-format-json.cc                 |  41 ++-
 gcc/diagnostic-format-sarif.cc                |   4 +-
 gcc/diagnostic-macro-unwinding.cc             | 221 ++++++++++++
 gcc/diagnostic-macro-unwinding.h              |  29 ++
 ...-diagnostic-path.cc => diagnostic-path.cc} | 317 ++++++------------
 gcc/diagnostic-path.h                         | 114 +------
 gcc/diagnostic.cc                             | 199 +++--------
 gcc/diagnostic.h                              |   6 +-
 gcc/logical-location.h                        |  10 +-
 gcc/selftest-diagnostic-path.cc               | 233 +++++++++++++
 gcc/selftest-diagnostic-path.h                | 163 +++++++++
 gcc/selftest-logical-location.cc              |  71 ++++
 gcc/selftest-logical-location.h               |  58 ++++
 gcc/selftest-run-tests.cc                     |   3 +-
 gcc/selftest.h                                |   3 +-
 gcc/simple-diagnostic-path.cc                 | 237 +++++++++++++
 gcc/simple-diagnostic-path.h                  | 139 ++++++++
 .../plugin/diagnostic_plugin_test_paths.c     |   1 +
 gcc/tree-diagnostic.cc                        | 197 -----------
 gcc/tree-diagnostic.h                         |  10 -
 gcc/tree-logical-location.cc                  |  25 ++
 gcc/tree-logical-location.h                   |   3 +
 27 files changed, 1410 insertions(+), 697 deletions(-)
 create mode 100644 gcc/diagnostic-macro-unwinding.cc
 create mode 100644 gcc/diagnostic-macro-unwinding.h
 rename gcc/{tree-diagnostic-path.cc => diagnostic-path.cc} (89%)
 create mode 100644 gcc/selftest-diagnostic-path.cc
 create mode 100644 gcc/selftest-diagnostic-path.h
 create mode 100644 gcc/selftest-logical-location.cc
 create mode 100644 gcc/selftest-logical-location.h
 create mode 100644 gcc/simple-diagnostic-path.cc
 create mode 100644 gcc/simple-diagnostic-path.h

-- 
2.26.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/7] diagnostics: move simple_diagnostic_{path,thread,event} to their own .h/cc
  2024-06-18 15:08 [pushed 0/7] diagnostics: remove "tree" dependency from diagnostic paths David Malcolm
@ 2024-06-18 15:08 ` David Malcolm
  2024-06-18 15:08 ` [PATCH 2/7] diagnostics: eliminate "tree" from diagnostic_{event,path} David Malcolm
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Malcolm @ 2024-06-18 15:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

As work towards eliminating the dependency on "tree" from
path-printing, move these classes to a new simple-diagnostic-path.h/cc.

No functional change intended.

gcc/analyzer/ChangeLog:
	* checker-path.h: Include "simple-diagnostic-path.h".

gcc/ChangeLog:
	* Makefile.in (OBJS): Add simple-diagnostic-path.o.
	* diagnostic-path.h (class simple_diagnostic_event): Move to
	simple-diagnostic-path.h.
	(class simple_diagnostic_thread): Likewise.
	(class simple_diagnostic_path): Likewise.
	* diagnostic.cc (simple_diagnostic_path::simple_diagnostic_path):
	Move to simple-diagnostic-path.cc.
	(simple_diagnostic_path::num_events): Likewise.
	(simple_diagnostic_path::get_event): Likewise.
	(simple_diagnostic_path::num_threads): Likewise.
	(simple_diagnostic_path::get_thread): Likewise.
	(simple_diagnostic_path::add_thread): Likewise.
	(simple_diagnostic_path::add_event): Likewise.
	(simple_diagnostic_path::add_thread_event): Likewise.
	(simple_diagnostic_path::connect_to_next_event): Likewise.
	(simple_diagnostic_event::simple_diagnostic_event): Likewise.
	(simple_diagnostic_event::~simple_diagnostic_event): Likewise.
	* selftest-run-tests.cc (selftest::run_tests): Call
	selftest::simple_diagnostic_path_cc_tests.
	* selftest.h (selftest::simple_diagnostic_path_cc_tests): New
	decl.
	* simple-diagnostic-path.cc: New file, from the above material.
	* simple-diagnostic-path.h: New file, from the above material
	from diagnostic-path.h.
	* tree-diagnostic-path.cc: Include "simple-diagnostic-path.h".

gcc/testsuite/ChangeLog
	* gcc.dg/plugin/diagnostic_plugin_test_paths.c: Include
	"simple-diagnostic-path.h".

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/Makefile.in                               |   1 +
 gcc/analyzer/checker-path.h                   |   1 +
 gcc/diagnostic-path.h                         | 104 +-------
 gcc/diagnostic.cc                             | 149 ------------
 gcc/selftest-run-tests.cc                     |   1 +
 gcc/selftest.h                                |   1 +
 gcc/simple-diagnostic-path.cc                 | 228 ++++++++++++++++++
 gcc/simple-diagnostic-path.h                  | 130 ++++++++++
 .../plugin/diagnostic_plugin_test_paths.c     |   1 +
 gcc/tree-diagnostic-path.cc                   |   1 +
 10 files changed, 366 insertions(+), 251 deletions(-)
 create mode 100644 gcc/simple-diagnostic-path.cc
 create mode 100644 gcc/simple-diagnostic-path.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index f5adb647d3f..35f259da858 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1700,6 +1700,7 @@ OBJS = \
 	ubsan.o \
 	sanopt.o \
 	sancov.o \
+	simple-diagnostic-path.o \
 	tree-call-cdce.o \
 	tree-cfg.o \
 	tree-cfgcleanup.o \
diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h
index 6b3e8a34fe5..162ebb3f0d8 100644
--- a/gcc/analyzer/checker-path.h
+++ b/gcc/analyzer/checker-path.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_ANALYZER_CHECKER_PATH_H
 
 #include "analyzer/checker-event.h"
+#include "simple-diagnostic-path.h"
 
 namespace ana {
 
diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h
index 938bd583a3d..958eb725322 100644
--- a/gcc/diagnostic-path.h
+++ b/gcc/diagnostic-path.h
@@ -201,108 +201,8 @@ private:
   bool get_first_event_in_a_function (unsigned *out_idx) const;
 };
 
-/* Concrete subclasses.  */
-
-/* A simple implementation of diagnostic_event.  */
-
-class simple_diagnostic_event : public diagnostic_event
-{
- public:
-  simple_diagnostic_event (location_t loc, tree fndecl, int depth,
-			   const char *desc,
-			   diagnostic_thread_id_t thread_id = 0);
-  ~simple_diagnostic_event ();
-
-  location_t get_location () const final override { return m_loc; }
-  tree get_fndecl () const final override { return m_fndecl; }
-  int get_stack_depth () const final override { return m_depth; }
-  label_text get_desc (bool) const final override
-  {
-    return label_text::borrow (m_desc);
-  }
-  const logical_location *get_logical_location () const final override
-  {
-    return NULL;
-  }
-  meaning get_meaning () const final override
-  {
-    return meaning ();
-  }
-  bool connect_to_next_event_p () const final override
-  {
-    return m_connected_to_next_event;
-  }
-  diagnostic_thread_id_t get_thread_id () const final override
-  {
-    return m_thread_id;
-  }
-
-  void connect_to_next_event ()
-  {
-    m_connected_to_next_event = true;
-  }
-
- private:
-  location_t m_loc;
-  tree m_fndecl;
-  int m_depth;
-  char *m_desc; // has been i18n-ed and formatted
-  bool m_connected_to_next_event;
-  diagnostic_thread_id_t m_thread_id;
-};
-
-/* A simple implementation of diagnostic_thread.  */
-
-class simple_diagnostic_thread : public diagnostic_thread
-{
-public:
-  simple_diagnostic_thread (const char *name) : m_name (name) {}
-  label_text get_name (bool) const final override
-  {
-    return label_text::borrow (m_name);
-  }
-
-private:
-  const char *m_name; // has been i18n-ed and formatted
-};
-
-/* A simple implementation of diagnostic_path, as a vector of
-   simple_diagnostic_event instances.  */
-
-class simple_diagnostic_path : public diagnostic_path
-{
- public:
-  simple_diagnostic_path (pretty_printer *event_pp);
-
-  unsigned num_events () const final override;
-  const diagnostic_event & get_event (int idx) const final override;
-  unsigned num_threads () const final override;
-  const diagnostic_thread &
-  get_thread (diagnostic_thread_id_t) const final override;
-
-  diagnostic_thread_id_t add_thread (const char *name);
-
-  diagnostic_event_id_t add_event (location_t loc, tree fndecl, int depth,
-				   const char *fmt, ...)
-    ATTRIBUTE_GCC_DIAG(5,6);
-  diagnostic_event_id_t
-  add_thread_event (diagnostic_thread_id_t thread_id,
-		    location_t loc, tree fndecl, int depth,
-		    const char *fmt, ...)
-    ATTRIBUTE_GCC_DIAG(6,7);
-
-  void connect_to_next_event ();
-
-  void disable_event_localization () { m_localize_events = false; }
-
- private:
-  auto_delete_vec<simple_diagnostic_thread> m_threads;
-  auto_delete_vec<simple_diagnostic_event> m_events;
-
-  /* (for use by add_event).  */
-  pretty_printer *m_event_pp;
-  bool m_localize_events;
-};
+/* Concrete subclasses of the above can be found in
+   simple-diagnostic-path.h.  */
 
 extern void debug (diagnostic_path *path);
 
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 9d0cb8ea051..a7acde50ab8 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -2517,155 +2517,6 @@ set_text_art_charset (enum diagnostic_text_art_charset charset)
     }
 }
 
-/* class simple_diagnostic_path : public diagnostic_path.  */
-
-simple_diagnostic_path::simple_diagnostic_path (pretty_printer *event_pp)
-: m_event_pp (event_pp),
-  m_localize_events (true)
-{
-  add_thread ("main");
-}
-
-/* Implementation of diagnostic_path::num_events vfunc for
-   simple_diagnostic_path: simply get the number of events in the vec.  */
-
-unsigned
-simple_diagnostic_path::num_events () const
-{
-  return m_events.length ();
-}
-
-/* Implementation of diagnostic_path::get_event vfunc for
-   simple_diagnostic_path: simply return the event in the vec.  */
-
-const diagnostic_event &
-simple_diagnostic_path::get_event (int idx) const
-{
-  return *m_events[idx];
-}
-
-unsigned
-simple_diagnostic_path::num_threads () const
-{
-  return m_threads.length ();
-}
-
-const diagnostic_thread &
-simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
-{
-  return *m_threads[idx];
-}
-
-diagnostic_thread_id_t
-simple_diagnostic_path::add_thread (const char *name)
-{
-  m_threads.safe_push (new simple_diagnostic_thread (name));
-  return m_threads.length () - 1;
-}
-
-/* Add an event to this path at LOC within function FNDECL at
-   stack depth DEPTH.
-
-   Use m_context's printer to format FMT, as the text of the new
-   event.  Localize FMT iff m_localize_events is set.
-
-   Return the id of the new event.  */
-
-diagnostic_event_id_t
-simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
-				   const char *fmt, ...)
-{
-  pretty_printer *pp = m_event_pp;
-  pp_clear_output_area (pp);
-
-  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
-
-  va_list ap;
-
-  va_start (ap, fmt);
-
-  text_info ti (m_localize_events ? _(fmt) : fmt,
-		&ap, 0, nullptr, &rich_loc);
-  pp_format (pp, &ti);
-  pp_output_formatted_text (pp);
-
-  va_end (ap);
-
-  simple_diagnostic_event *new_event
-    = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
-  m_events.safe_push (new_event);
-
-  pp_clear_output_area (pp);
-
-  return diagnostic_event_id_t (m_events.length () - 1);
-}
-
-diagnostic_event_id_t
-simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
-					  location_t loc,
-					  tree fndecl,
-					  int depth,
-					  const char *fmt, ...)
-{
-  pretty_printer *pp = m_event_pp;
-  pp_clear_output_area (pp);
-
-  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
-
-  va_list ap;
-
-  va_start (ap, fmt);
-
-  text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
-
-  pp_format (pp, &ti);
-  pp_output_formatted_text (pp);
-
-  va_end (ap);
-
-  simple_diagnostic_event *new_event
-    = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp),
-				   thread_id);
-  m_events.safe_push (new_event);
-
-  pp_clear_output_area (pp);
-
-  return diagnostic_event_id_t (m_events.length () - 1);
-}
-
-/* Mark the most recent event on this path (which must exist) as being
-   connected to the next one to be added.  */
-
-void
-simple_diagnostic_path::connect_to_next_event ()
-{
-  gcc_assert (m_events.length () > 0);
-  m_events[m_events.length () - 1]->connect_to_next_event ();
-}
-
-/* struct simple_diagnostic_event.  */
-
-/* simple_diagnostic_event's ctor.  */
-
-simple_diagnostic_event::
-simple_diagnostic_event (location_t loc,
-			 tree fndecl,
-			 int depth,
-			 const char *desc,
-			 diagnostic_thread_id_t thread_id)
-: m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc)),
-  m_connected_to_next_event (false),
-  m_thread_id (thread_id)
-{
-}
-
-/* simple_diagnostic_event's dtor.  */
-
-simple_diagnostic_event::~simple_diagnostic_event ()
-{
-  free (m_desc);
-}
-
 /* Print PATH by emitting a dummy "note" associated with it.  */
 
 DEBUG_FUNCTION
diff --git a/gcc/selftest-run-tests.cc b/gcc/selftest-run-tests.cc
index d8f5e4b34c6..3275db38ba9 100644
--- a/gcc/selftest-run-tests.cc
+++ b/gcc/selftest-run-tests.cc
@@ -103,6 +103,7 @@ selftest::run_tests ()
   spellcheck_tree_cc_tests ();
   tree_cfg_cc_tests ();
   tree_diagnostic_path_cc_tests ();
+  simple_diagnostic_path_cc_tests ();
   attribs_cc_tests ();
 
   /* This one relies on most of the above.  */
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 9e294ad1e5f..2d1aa91607e 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -250,6 +250,7 @@ extern void read_rtl_function_cc_tests ();
 extern void rtl_tests_cc_tests ();
 extern void sbitmap_cc_tests ();
 extern void selftest_cc_tests ();
+extern void simple_diagnostic_path_cc_tests ();
 extern void simplify_rtx_cc_tests ();
 extern void spellcheck_cc_tests ();
 extern void spellcheck_tree_cc_tests ();
diff --git a/gcc/simple-diagnostic-path.cc b/gcc/simple-diagnostic-path.cc
new file mode 100644
index 00000000000..3ec0e850985
--- /dev/null
+++ b/gcc/simple-diagnostic-path.cc
@@ -0,0 +1,228 @@
+/* Concrete classes for implementing diagnostic paths.
+   Copyright (C) 2019-2024 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#include "config.h"
+#define INCLUDE_MEMORY
+#define INCLUDE_VECTOR
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "version.h"
+#include "demangle.h"
+#include "intl.h"
+#include "backtrace.h"
+#include "diagnostic.h"
+#include "simple-diagnostic-path.h"
+#include "selftest.h"
+
+/* class simple_diagnostic_path : public diagnostic_path.  */
+
+simple_diagnostic_path::simple_diagnostic_path (pretty_printer *event_pp)
+: m_event_pp (event_pp),
+  m_localize_events (true)
+{
+  add_thread ("main");
+}
+
+/* Implementation of diagnostic_path::num_events vfunc for
+   simple_diagnostic_path: simply get the number of events in the vec.  */
+
+unsigned
+simple_diagnostic_path::num_events () const
+{
+  return m_events.length ();
+}
+
+/* Implementation of diagnostic_path::get_event vfunc for
+   simple_diagnostic_path: simply return the event in the vec.  */
+
+const diagnostic_event &
+simple_diagnostic_path::get_event (int idx) const
+{
+  return *m_events[idx];
+}
+
+unsigned
+simple_diagnostic_path::num_threads () const
+{
+  return m_threads.length ();
+}
+
+const diagnostic_thread &
+simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
+{
+  return *m_threads[idx];
+}
+
+diagnostic_thread_id_t
+simple_diagnostic_path::add_thread (const char *name)
+{
+  m_threads.safe_push (new simple_diagnostic_thread (name));
+  return m_threads.length () - 1;
+}
+
+/* Add an event to this path at LOC within function FNDECL at
+   stack depth DEPTH.
+
+   Use m_context's printer to format FMT, as the text of the new
+   event.  Localize FMT iff m_localize_events is set.
+
+   Return the id of the new event.  */
+
+diagnostic_event_id_t
+simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
+				   const char *fmt, ...)
+{
+  pretty_printer *pp = m_event_pp;
+  pp_clear_output_area (pp);
+
+  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+
+  va_list ap;
+
+  va_start (ap, fmt);
+
+  text_info ti (m_localize_events ? _(fmt) : fmt,
+		&ap, 0, nullptr, &rich_loc);
+  pp_format (pp, &ti);
+  pp_output_formatted_text (pp);
+
+  va_end (ap);
+
+  simple_diagnostic_event *new_event
+    = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
+  m_events.safe_push (new_event);
+
+  pp_clear_output_area (pp);
+
+  return diagnostic_event_id_t (m_events.length () - 1);
+}
+
+diagnostic_event_id_t
+simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
+					  location_t loc,
+					  tree fndecl,
+					  int depth,
+					  const char *fmt, ...)
+{
+  pretty_printer *pp = m_event_pp;
+  pp_clear_output_area (pp);
+
+  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+
+  va_list ap;
+
+  va_start (ap, fmt);
+
+  text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
+
+  pp_format (pp, &ti);
+  pp_output_formatted_text (pp);
+
+  va_end (ap);
+
+  simple_diagnostic_event *new_event
+    = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp),
+				   thread_id);
+  m_events.safe_push (new_event);
+
+  pp_clear_output_area (pp);
+
+  return diagnostic_event_id_t (m_events.length () - 1);
+}
+
+/* Mark the most recent event on this path (which must exist) as being
+   connected to the next one to be added.  */
+
+void
+simple_diagnostic_path::connect_to_next_event ()
+{
+  gcc_assert (m_events.length () > 0);
+  m_events[m_events.length () - 1]->connect_to_next_event ();
+}
+
+/* struct simple_diagnostic_event.  */
+
+/* simple_diagnostic_event's ctor.  */
+
+simple_diagnostic_event::
+simple_diagnostic_event (location_t loc,
+			 tree fndecl,
+			 int depth,
+			 const char *desc,
+			 diagnostic_thread_id_t thread_id)
+: m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc)),
+  m_connected_to_next_event (false),
+  m_thread_id (thread_id)
+{
+}
+
+/* simple_diagnostic_event's dtor.  */
+
+simple_diagnostic_event::~simple_diagnostic_event ()
+{
+  free (m_desc);
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+static void
+test_intraprocedural_path (pretty_printer *event_pp)
+{
+  tree fntype_void_void
+    = build_function_type_array (void_type_node, 0, NULL);
+  tree fndecl_foo = build_fn_decl ("foo", fntype_void_void);
+
+  simple_diagnostic_path path (event_pp);
+  path.add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "first %qs", "free");
+  path.add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "double %qs", "free");
+
+  ASSERT_EQ (path.num_events (), 2);
+  ASSERT_EQ (path.num_threads (), 1);
+  ASSERT_FALSE (path.interprocedural_p ());
+  ASSERT_STREQ (path.get_event (0).get_desc (false).get (), "first `free'");
+  ASSERT_STREQ (path.get_event (1).get_desc (false).get (), "double `free'");
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+simple_diagnostic_path_cc_tests ()
+{
+  /* In a few places we use the global dc's printer to determine
+     colorization so ensure this off during the tests.  */
+  const bool saved_show_color = pp_show_color (global_dc->printer);
+  pp_show_color (global_dc->printer) = false;
+
+  auto_fix_quotes fix_quotes;
+  std::unique_ptr<pretty_printer> event_pp
+    = std::unique_ptr<pretty_printer> (global_dc->printer->clone ());
+
+  test_intraprocedural_path (event_pp.get ());
+
+  pp_show_color (global_dc->printer) = saved_show_color;
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/simple-diagnostic-path.h b/gcc/simple-diagnostic-path.h
new file mode 100644
index 00000000000..5fbed158f15
--- /dev/null
+++ b/gcc/simple-diagnostic-path.h
@@ -0,0 +1,130 @@
+/* Concrete classes for implementing diagnostic paths.
+   Copyright (C) 2019-2024 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_SIMPLE_DIAGNOSTIC_PATH_H
+#define GCC_SIMPLE_DIAGNOSTIC_PATH_H
+
+#include "diagnostic-path.h"
+
+/* Concrete subclasses of the abstract base classes
+   declared in diagnostic-path.h.  */
+
+/* A simple implementation of diagnostic_event.  */
+
+class simple_diagnostic_event : public diagnostic_event
+{
+ public:
+  simple_diagnostic_event (location_t loc, tree fndecl, int depth,
+			   const char *desc,
+			   diagnostic_thread_id_t thread_id = 0);
+  ~simple_diagnostic_event ();
+
+  location_t get_location () const final override { return m_loc; }
+  tree get_fndecl () const final override { return m_fndecl; }
+  int get_stack_depth () const final override { return m_depth; }
+  label_text get_desc (bool) const final override
+  {
+    return label_text::borrow (m_desc);
+  }
+  const logical_location *get_logical_location () const final override
+  {
+    return NULL;
+  }
+  meaning get_meaning () const final override
+  {
+    return meaning ();
+  }
+  bool connect_to_next_event_p () const final override
+  {
+    return m_connected_to_next_event;
+  }
+  diagnostic_thread_id_t get_thread_id () const final override
+  {
+    return m_thread_id;
+  }
+
+  void connect_to_next_event ()
+  {
+    m_connected_to_next_event = true;
+  }
+
+ private:
+  location_t m_loc;
+  tree m_fndecl;
+  int m_depth;
+  char *m_desc; // has been i18n-ed and formatted
+  bool m_connected_to_next_event;
+  diagnostic_thread_id_t m_thread_id;
+};
+
+/* A simple implementation of diagnostic_thread.  */
+
+class simple_diagnostic_thread : public diagnostic_thread
+{
+public:
+  simple_diagnostic_thread (const char *name) : m_name (name) {}
+  label_text get_name (bool) const final override
+  {
+    return label_text::borrow (m_name);
+  }
+
+private:
+  const char *m_name; // has been i18n-ed and formatted
+};
+
+/* A simple implementation of diagnostic_path, as a vector of
+   simple_diagnostic_event instances.  */
+
+class simple_diagnostic_path : public diagnostic_path
+{
+ public:
+  simple_diagnostic_path (pretty_printer *event_pp);
+
+  unsigned num_events () const final override;
+  const diagnostic_event & get_event (int idx) const final override;
+  unsigned num_threads () const final override;
+  const diagnostic_thread &
+  get_thread (diagnostic_thread_id_t) const final override;
+
+  diagnostic_thread_id_t add_thread (const char *name);
+
+  diagnostic_event_id_t add_event (location_t loc, tree fndecl, int depth,
+				   const char *fmt, ...)
+    ATTRIBUTE_GCC_DIAG(5,6);
+  diagnostic_event_id_t
+  add_thread_event (diagnostic_thread_id_t thread_id,
+		    location_t loc, tree fndecl, int depth,
+		    const char *fmt, ...)
+    ATTRIBUTE_GCC_DIAG(6,7);
+
+  void connect_to_next_event ();
+
+  void disable_event_localization () { m_localize_events = false; }
+
+ private:
+  auto_delete_vec<simple_diagnostic_thread> m_threads;
+  auto_delete_vec<simple_diagnostic_event> m_events;
+
+  /* (for use by add_event).  */
+  pretty_printer *m_event_pp;
+  bool m_localize_events;
+};
+
+#endif /* ! GCC_SIMPLE_DIAGNOSTIC_PATH_H */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.c b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.c
index bf665005c8b..efa4ec475ab 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.c
@@ -38,6 +38,7 @@
 #include "print-tree.h"
 #include "gcc-rich-location.h"
 #include "cgraph.h"
+#include "simple-diagnostic-path.h"
 
 int plugin_is_GPL_compatible;
 
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index f82ef305c06..a9dd40cbd9d 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "intl.h"
 #include "diagnostic-path.h"
+#include "simple-diagnostic-path.h"
 #include "json.h"
 #include "gcc-rich-location.h"
 #include "diagnostic-color.h"
-- 
2.26.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 2/7] diagnostics: eliminate "tree" from diagnostic_{event,path}
  2024-06-18 15:08 [pushed 0/7] diagnostics: remove "tree" dependency from diagnostic paths David Malcolm
  2024-06-18 15:08 ` [PATCH 1/7] diagnostics: move simple_diagnostic_{path,thread,event} to their own .h/cc David Malcolm
@ 2024-06-18 15:08 ` David Malcolm
  2024-06-18 15:08 ` [PATCH 3/7] diagnostics: remove tree usage from tree-diagnostic-path.cc David Malcolm
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Malcolm @ 2024-06-18 15:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

This patch eliminates the use of "tree" from diagnostic_{event,path} in
favor of const logical_location *.

No functional change intended.

gcc/analyzer/ChangeLog:
	* checker-event.h (checker_event::fndecl): Drop "final" and
	"override", converting from a vfunc implementation to a plain
	accessor.
	* checker-path.cc (checker_path::same_function_p): New.
	* checker-path.h (checker_path::same_function_p): New decl.

gcc/ChangeLog:
	* diagnostic.cc: Include "logical-location.h".
	(diagnostic_path::get_first_event_in_a_function): Fix typo in
	leading comment.  Rewrite to use logical_location rather than
	tree.  Drop test on stack depth.
	(diagnostic_path::interprocedural_p): Rewrite to use
	logical_location rather than tree.
	(logical_location::function_p): New.
	* diagnostic-path.h (diagnostic_event::get_fndecl): Eliminate
	vfunc.
	(diagnostic_path::same_function_p): New pure virtual func.
	* logical-location.h (logical_location::get_name_for_path_output):
	New pure virtual func.
	* simple-diagnostic-path.cc
	(simple_diagnostic_path::same_function_p): New.
	(simple_diagnostic_event::simple_diagnostic_event): Initialize
	m_logical_loc.
	* simple-diagnostic-path.h: Include "tree-logical-location.h".
	(simple_diagnostic_event::get_fndecl): Convert from a vfunc
	implementation to an accessor.
	(simple_diagnostic_event::get_logical_location): Use
	m_logical_loc.
	(simple_diagnostic_event::m_logical_loc): New field.
	(simple_diagnostic_path::same_function_p): New decl.
	* tree-diagnostic-path.cc: Move pragma disabling -Wformat-diag to
	cover the whole file.
	(can_consolidate_events): Add params "path", "ev1_idx", and
	"ev2_idx".  Rewrite to use diagnostic_path::same_function_p rather
	than tree.
	(per_thread_summary::per_thread_summary): Add "path" param
	(per_thread_summary::m_path): New field.
	(event_range::event_range): Update for conversion of m_fndecl to
	m_logical_loc.
	(event_range::maybe_add_event): Rename param "idx" to
	"new_ev_idx".  Update call to can_consolidate_events to pass in
	"m_path", "m_start_idx", and "new_ev_idx".
	(event_range::m_fndecl): Replace with...
	(event_range::m_logical_loc): ...this.
	(path_summary::get_or_create_events_for_thread_id): Pass "path" to
	per_thread_summary ctor.
	(per_thread_summary::interprocedural_p): Rewrite to use
	diagnostic_path::same_function_p rather than tree.
	(print_fndecl): Delete.
	(thread_event_printer::print_swimlane_for_event_range): Update for
	conversion from tree to logical_location.
	(default_tree_diagnostic_path_printer): Likewise.
	(default_tree_make_json_for_path): Likewise.
	* tree-logical-location.cc: Include "intl.h".
	(compiler_logical_location::get_name_for_tree_for_path_output):
	New.
	(tree_logical_location::get_name_for_path_output): New.
	(current_fndecl_logical_location::get_name_for_path_output): New.
	* tree-logical-location.h
	(compiler_logical_location::get_name_for_tree_for_path_output):
	New decl.
	(tree_logical_location::get_name_for_path_output): New decl.
	(current_fndecl_logical_location::get_name_for_path_output): New
	decl.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/analyzer/checker-event.h  |   2 +-
 gcc/analyzer/checker-path.cc  |   8 +++
 gcc/analyzer/checker-path.h   |   4 ++
 gcc/diagnostic-path.h         |  10 +++-
 gcc/diagnostic.cc             |  47 ++++++++++++----
 gcc/logical-location.h        |   5 ++
 gcc/simple-diagnostic-path.cc |  11 +++-
 gcc/simple-diagnostic-path.h  |  13 ++++-
 gcc/tree-diagnostic-path.cc   | 103 +++++++++++++++++-----------------
 gcc/tree-logical-location.cc  |  25 +++++++++
 gcc/tree-logical-location.h   |   3 +
 11 files changed, 161 insertions(+), 70 deletions(-)

diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
index d0935aca985..4343641f441 100644
--- a/gcc/analyzer/checker-event.h
+++ b/gcc/analyzer/checker-event.h
@@ -91,7 +91,6 @@ public:
   /* Implementation of diagnostic_event.  */
 
   location_t get_location () const final override { return m_loc; }
-  tree get_fndecl () const final override { return m_effective_fndecl; }
   int get_stack_depth () const final override { return m_effective_depth; }
   const logical_location *get_logical_location () const final override
   {
@@ -111,6 +110,7 @@ public:
   maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj) const override;
 
   /* Additional functionality.  */
+  tree get_fndecl () const { return m_effective_fndecl; }
 
   int get_original_stack_depth () const { return m_original_depth; }
 
diff --git a/gcc/analyzer/checker-path.cc b/gcc/analyzer/checker-path.cc
index c8361915ad9..cfbbc0b25f3 100644
--- a/gcc/analyzer/checker-path.cc
+++ b/gcc/analyzer/checker-path.cc
@@ -63,6 +63,14 @@ along with GCC; see the file COPYING3.  If not see
 
 namespace ana {
 
+bool
+checker_path::same_function_p (int event_idx_a,
+			       int event_idx_b) const
+{
+  return (m_events[event_idx_a]->get_fndecl ()
+	  == m_events[event_idx_b]->get_fndecl ());
+}
+
 /* Print a single-line representation of this path to PP.  */
 
 void
diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h
index 162ebb3f0d8..1aa56d27927 100644
--- a/gcc/analyzer/checker-path.h
+++ b/gcc/analyzer/checker-path.h
@@ -63,6 +63,10 @@ public:
     return m_events[idx];
   }
 
+  bool
+  same_function_p (int event_idx_a,
+		   int event_idx_b) const final override;
+
   void dump (pretty_printer *pp) const;
   void debug () const;
 
diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h
index 958eb725322..7497b0a7199 100644
--- a/gcc/diagnostic-path.h
+++ b/gcc/diagnostic-path.h
@@ -142,8 +142,6 @@ class diagnostic_event
 
   virtual location_t get_location () const = 0;
 
-  virtual tree get_fndecl () const = 0;
-
   /* Stack depth, so that consumers can visualize the interprocedural
      calls, returns, and frame nesting.  */
   virtual int get_stack_depth () const = 0;
@@ -151,7 +149,7 @@ class diagnostic_event
   /* Get a localized (and possibly colorized) description of this event.  */
   virtual label_text get_desc (bool can_colorize) const = 0;
 
-  /* Get a logical_location for this event, or NULL.  */
+  /* Get a logical_location for this event, or nullptr if there is none.  */
   virtual const logical_location *get_logical_location () const = 0;
 
   virtual meaning get_meaning () const = 0;
@@ -194,6 +192,12 @@ class diagnostic_path
   virtual const diagnostic_thread &
   get_thread (diagnostic_thread_id_t) const = 0;
 
+  /* Return true iff the two events are both within the same function,
+     or both outside of any function.  */
+  virtual bool
+  same_function_p (int event_idx_a,
+		   int event_idx_b) const = 0;
+
   bool interprocedural_p () const;
   bool multithreaded_p () const;
 
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index a7acde50ab8..844eb8e1048 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cpplib.h"
 #include "text-art/theme.h"
 #include "pretty-print-urlifier.h"
+#include "logical-location.h"
 
 #ifdef HAVE_TERMIOS_H
 # include <termios.h>
@@ -1028,9 +1029,9 @@ diagnostic_event::meaning::maybe_get_property_str (enum property p)
 
 /* class diagnostic_path.  */
 
-/* Subroutint of diagnostic_path::interprocedural_p.
+/* Subroutine of diagnostic_path::interprocedural_p.
    Look for the first event in this path that is within a function
-   i.e. has a non-NULL fndecl, and a non-zero stack depth.
+   i.e. has a non-null logical location for which function_p is true.
    If found, write its index to *OUT_IDX and return true.
    Otherwise return false.  */
 
@@ -1040,12 +1041,13 @@ diagnostic_path::get_first_event_in_a_function (unsigned *out_idx) const
   const unsigned num = num_events ();
   for (unsigned i = 0; i < num; i++)
     {
-      if (!(get_event (i).get_fndecl () == NULL
-	    && get_event (i).get_stack_depth () == 0))
-	{
-	  *out_idx = i;
-	  return true;
-	}
+      const diagnostic_event &event = get_event (i);
+      if (const logical_location *logical_loc = event.get_logical_location ())
+	if (logical_loc->function_p ())
+	  {
+	    *out_idx = i;
+	    return true;
+	  }
     }
   return false;
 }
@@ -1062,13 +1064,12 @@ diagnostic_path::interprocedural_p () const
     return false;
 
   const diagnostic_event &first_fn_event = get_event (first_fn_event_idx);
-  tree first_fndecl = first_fn_event.get_fndecl ();
   int first_fn_stack_depth = first_fn_event.get_stack_depth ();
 
   const unsigned num = num_events ();
   for (unsigned i = first_fn_event_idx + 1; i < num; i++)
     {
-      if (get_event (i).get_fndecl () != first_fndecl)
+      if (!same_function_p (first_fn_event_idx, i))
 	return true;
       if (get_event (i).get_stack_depth () != first_fn_stack_depth)
 	return true;
@@ -1076,6 +1077,32 @@ diagnostic_path::interprocedural_p () const
   return false;
 }
 
+/* class logical_location.  */
+
+/* Return true iff this is a function or method.  */
+
+bool
+logical_location::function_p () const
+{
+  switch (get_kind ())
+    {
+    default:
+      gcc_unreachable ();
+    case LOGICAL_LOCATION_KIND_UNKNOWN:
+    case LOGICAL_LOCATION_KIND_MODULE:
+    case LOGICAL_LOCATION_KIND_NAMESPACE:
+    case LOGICAL_LOCATION_KIND_TYPE:
+    case LOGICAL_LOCATION_KIND_RETURN_TYPE:
+    case LOGICAL_LOCATION_KIND_PARAMETER:
+    case LOGICAL_LOCATION_KIND_VARIABLE:
+      return false;
+
+    case LOGICAL_LOCATION_KIND_FUNCTION:
+    case LOGICAL_LOCATION_KIND_MEMBER:
+      return true;
+    }
+}
+
 void
 default_diagnostic_starter (diagnostic_context *context,
 			    const diagnostic_info *diagnostic)
diff --git a/gcc/logical-location.h b/gcc/logical-location.h
index abe2c3a648e..c3b72081135 100644
--- a/gcc/logical-location.h
+++ b/gcc/logical-location.h
@@ -67,6 +67,11 @@ public:
 
   /* Get what kind of SARIF logicalLocation this is (if any).  */
   virtual enum logical_location_kind get_kind () const = 0;
+
+  /* Get a string for this location in a form suitable for path output.  */
+  virtual label_text get_name_for_path_output () const = 0;
+
+  bool function_p () const;
 };
 
 #endif /* GCC_LOGICAL_LOCATION_H.  */
diff --git a/gcc/simple-diagnostic-path.cc b/gcc/simple-diagnostic-path.cc
index 3ec0e850985..7c47b830934 100644
--- a/gcc/simple-diagnostic-path.cc
+++ b/gcc/simple-diagnostic-path.cc
@@ -72,6 +72,14 @@ simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
   return *m_threads[idx];
 }
 
+bool
+simple_diagnostic_path::same_function_p (int event_idx_a,
+					 int event_idx_b) const
+{
+  return (m_events[event_idx_a]->get_fndecl ()
+	  == m_events[event_idx_b]->get_fndecl ());
+}
+
 diagnostic_thread_id_t
 simple_diagnostic_path::add_thread (const char *name)
 {
@@ -169,7 +177,8 @@ simple_diagnostic_event (location_t loc,
 			 int depth,
 			 const char *desc,
 			 diagnostic_thread_id_t thread_id)
-: m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc)),
+: m_loc (loc), m_fndecl (fndecl), m_logical_loc (fndecl),
+  m_depth (depth), m_desc (xstrdup (desc)),
   m_connected_to_next_event (false),
   m_thread_id (thread_id)
 {
diff --git a/gcc/simple-diagnostic-path.h b/gcc/simple-diagnostic-path.h
index 5fbed158f15..5147df5185b 100644
--- a/gcc/simple-diagnostic-path.h
+++ b/gcc/simple-diagnostic-path.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_SIMPLE_DIAGNOSTIC_PATH_H
 
 #include "diagnostic-path.h"
+#include "tree-logical-location.h"
 
 /* Concrete subclasses of the abstract base classes
    declared in diagnostic-path.h.  */
@@ -37,7 +38,6 @@ class simple_diagnostic_event : public diagnostic_event
   ~simple_diagnostic_event ();
 
   location_t get_location () const final override { return m_loc; }
-  tree get_fndecl () const final override { return m_fndecl; }
   int get_stack_depth () const final override { return m_depth; }
   label_text get_desc (bool) const final override
   {
@@ -45,7 +45,10 @@ class simple_diagnostic_event : public diagnostic_event
   }
   const logical_location *get_logical_location () const final override
   {
-    return NULL;
+    if (m_fndecl)
+      return &m_logical_loc;
+    else
+      return nullptr;
   }
   meaning get_meaning () const final override
   {
@@ -65,9 +68,12 @@ class simple_diagnostic_event : public diagnostic_event
     m_connected_to_next_event = true;
   }
 
+  tree get_fndecl () const { return m_fndecl; }
+
  private:
   location_t m_loc;
   tree m_fndecl;
+  tree_logical_location m_logical_loc;
   int m_depth;
   char *m_desc; // has been i18n-ed and formatted
   bool m_connected_to_next_event;
@@ -102,6 +108,9 @@ class simple_diagnostic_path : public diagnostic_path
   unsigned num_threads () const final override;
   const diagnostic_thread &
   get_thread (diagnostic_thread_id_t) const final override;
+  bool
+  same_function_p (int event_idx_a,
+		   int event_idx_b) const final override;
 
   diagnostic_thread_id_t add_thread (const char *name);
 
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index a9dd40cbd9d..4287b90d5dd 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -43,6 +43,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "selftest-diagnostic.h"
 #include "text-art/theme.h"
 
+/* Disable warnings about missing quoting in GCC diagnostics for the print
+   calls below.  */
+#if __GNUC__ >= 10
+#  pragma GCC diagnostic push
+#  pragma GCC diagnostic ignored "-Wformat-diag"
+#endif
+
 /* Anonymous namespace for path-printing code.  */
 
 namespace {
@@ -153,14 +160,17 @@ class path_label : public range_label
    when printing a diagnostic_path.  */
 
 static bool
-can_consolidate_events (const diagnostic_event &e1,
+can_consolidate_events (const diagnostic_path &path,
+			const diagnostic_event &e1,
+			unsigned ev1_idx,
 			const diagnostic_event &e2,
+			unsigned ev2_idx,
 			bool check_locations)
 {
   if (e1.get_thread_id () != e2.get_thread_id ())
     return false;
 
-  if (e1.get_fndecl () != e2.get_fndecl ())
+  if (!path.same_function_p (ev1_idx, ev2_idx))
     return false;
 
   if (e1.get_stack_depth () != e2.get_stack_depth ())
@@ -196,8 +206,10 @@ class thread_event_printer;
 class per_thread_summary
 {
 public:
-  per_thread_summary (label_text name, unsigned swimlane_idx)
-  : m_name (std::move (name)),
+  per_thread_summary (const diagnostic_path &path,
+		      label_text name, unsigned swimlane_idx)
+  : m_path (path),
+    m_name (std::move (name)),
     m_swimlane_idx (swimlane_idx),
     m_last_event (nullptr),
     m_min_depth (INT_MAX),
@@ -222,6 +234,8 @@ private:
   friend class thread_event_printer;
   friend struct event_range;
 
+  const diagnostic_path &m_path;
+
   const label_text m_name;
 
   /* The "swimlane index" is the order in which this per_thread_summary
@@ -333,7 +347,7 @@ struct event_range
 	       bool show_event_links)
   : m_path (path),
     m_initial_event (initial_event),
-    m_fndecl (initial_event.get_fndecl ()),
+    m_logical_loc (initial_event.get_logical_location ()),
     m_stack_depth (initial_event.get_stack_depth ()),
     m_start_idx (start_idx), m_end_idx (start_idx),
     m_path_label (path, start_idx),
@@ -373,10 +387,13 @@ struct event_range
     return result;
   }
 
-  bool maybe_add_event (const diagnostic_event &new_ev, unsigned idx,
+  bool maybe_add_event (const diagnostic_event &new_ev,
+			unsigned new_ev_idx,
 			bool check_rich_locations)
   {
-    if (!can_consolidate_events (m_initial_event, new_ev,
+    if (!can_consolidate_events (*m_path,
+				 m_initial_event, m_start_idx,
+				 new_ev, new_ev_idx,
 				 check_rich_locations))
       return false;
 
@@ -388,8 +405,8 @@ struct event_range
     per_source_line_info &source_line_info
       = get_per_source_line_info (exploc.line);
     const diagnostic_event *prev_event = nullptr;
-    if (idx > 0)
-      prev_event = &m_path->get_event (idx - 1);
+    if (new_ev_idx > 0)
+      prev_event = &m_path->get_event (new_ev_idx - 1);
     const bool has_in_edge = (prev_event
 			      ? prev_event->connect_to_next_event_p ()
 			      : false);
@@ -406,7 +423,7 @@ struct event_range
 					     false, &m_path_label))
 	return false;
 
-    m_end_idx = idx;
+    m_end_idx = new_ev_idx;
     m_per_thread_summary.m_last_event = &new_ev;
 
     if (m_show_event_links)
@@ -470,7 +487,7 @@ struct event_range
 
   const diagnostic_path *m_path;
   const diagnostic_event &m_initial_event;
-  tree m_fndecl;
+  const logical_location *m_logical_loc;
   int m_stack_depth;
   unsigned m_start_idx;
   unsigned m_end_idx;
@@ -518,8 +535,10 @@ private:
       return **slot;
 
     const diagnostic_thread &thread = path.get_thread (tid);
-    per_thread_summary *pts = new per_thread_summary (thread.get_name (false),
-						m_per_thread_summary.length ());
+    per_thread_summary *pts
+      = new per_thread_summary (path,
+				thread.get_name (false),
+				m_per_thread_summary.length ());
     m_thread_id_to_events.put (tid, pts);
     m_per_thread_summary.safe_push (pts);
     return *pts;
@@ -534,12 +553,12 @@ per_thread_summary::interprocedural_p () const
 {
   if (m_event_ranges.is_empty ())
     return false;
-  tree first_fndecl = m_event_ranges[0]->m_fndecl;
   int first_stack_depth = m_event_ranges[0]->m_stack_depth;
   for (auto range : m_event_ranges)
     {
-      if (range->m_fndecl != first_fndecl)
-	return true;
+      if (!m_path.same_function_p (m_event_ranges[0]->m_start_idx,
+				   range->m_start_idx))
+	  return true;
       if (range->m_stack_depth != first_stack_depth)
 	return true;
     }
@@ -585,23 +604,6 @@ write_indent (pretty_printer *pp, int spaces)
     pp_space (pp);
 }
 
-/* Print FNDDECL to PP, quoting it if QUOTED is true.
-
-   We can't use "%qE" here since we can't guarantee the capabilities
-   of PP.  */
-
-static void
-print_fndecl (pretty_printer *pp, tree fndecl, bool quoted)
-{
-  const char *n = DECL_NAME (fndecl)
-    ? identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2))
-    : _("<anonymous>");
-  if (quoted)
-    pp_printf (pp, "%qs", n);
-  else
-    pp_string (pp, n);
-}
-
 static const int base_indent = 2;
 static const int per_frame_indent = 2;
 
@@ -684,10 +686,10 @@ public:
 	    m_cur_indent += 5;
 	  }
       }
-    if (range->m_fndecl)
+    if (const logical_location *logical_loc = range->m_logical_loc)
       {
-	print_fndecl (pp, range->m_fndecl, true);
-	pp_string (pp, ": ");
+	label_text name (logical_loc->get_name_for_path_output ());
+	pp_printf (pp, "%qs: ", name.get ());
       }
     if (range->m_start_idx == range->m_end_idx)
       pp_printf (pp, "event %i",
@@ -914,15 +916,18 @@ default_tree_diagnostic_path_printer (diagnostic_context *context,
 	    if (context->show_path_depths_p ())
 	      {
 		int stack_depth = event.get_stack_depth ();
-		tree fndecl = event.get_fndecl ();
 		/* -fdiagnostics-path-format=separate-events doesn't print
 		   fndecl information, so with -fdiagnostics-show-path-depths
 		   print the fndecls too, if any.  */
-		if (fndecl)
-		  inform (event.get_location (),
-			  "%@ %s (fndecl %qD, depth %i)",
-			  &event_id, event_text.get (),
-			  fndecl, stack_depth);
+		if (const logical_location *logical_loc
+		      = event.get_logical_location ())
+		  {
+		    label_text name (logical_loc->get_name_for_path_output ());
+		    inform (event.get_location (),
+			    "%@ %s (fndecl %qs, depth %i)",
+			    &event_id, event_text.get (),
+			    name.get (), stack_depth);
+		  }
 		else
 		  inform (event.get_location (),
 			  "%@ %s (depth %i)",
@@ -972,11 +977,10 @@ default_tree_make_json_for_path (diagnostic_context *context,
 						     event.get_location ()));
       label_text event_text (event.get_desc (false));
       event_obj->set_string ("description", event_text.get ());
-      if (tree fndecl = event.get_fndecl ())
+      if (const logical_location *logical_loc = event.get_logical_location ())
 	{
-	  const char *function
-	    = identifier_to_locale (lang_hooks.decl_printable_name (fndecl, 2));
-	  event_obj->set_string ("function", function);
+	  label_text name (logical_loc->get_name_for_path_output ());
+	  event_obj->set_string ("function", name.get ());
 	}
       event_obj->set_integer ("depth", event.get_stack_depth ());
       path_array->append (event_obj);
@@ -986,13 +990,6 @@ default_tree_make_json_for_path (diagnostic_context *context,
 
 #if CHECKING_P
 
-/* Disable warnings about missing quoting in GCC diagnostics for the print
-   calls in the tests below.  */
-#if __GNUC__ >= 10
-#  pragma GCC diagnostic push
-#  pragma GCC diagnostic ignored "-Wformat-diag"
-#endif
-
 namespace selftest {
 
 /* Return true iff all events in PATH have locations for which column data
diff --git a/gcc/tree-logical-location.cc b/gcc/tree-logical-location.cc
index 0333b318642..ca8b34a42d3 100644
--- a/gcc/tree-logical-location.cc
+++ b/gcc/tree-logical-location.cc
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "pretty-print.h"
 #include "tree-logical-location.h"
 #include "langhooks.h"
+#include "intl.h"
 
 /* class compiler_logical_location : public logical_location.  */
 
@@ -82,6 +83,16 @@ compiler_logical_location::get_kind_for_tree (tree decl)
     }
 }
 
+label_text
+compiler_logical_location::get_name_for_tree_for_path_output (tree decl)
+{
+  gcc_assert (decl);
+  const char *n = DECL_NAME (decl)
+    ? identifier_to_locale (lang_hooks.decl_printable_name (decl, 2))
+    : _("<anonymous>");
+  return label_text::borrow (n);
+}
+
 /* class tree_logical_location : public compiler_logical_location.  */
 
 /* Implementation of the logical_location vfuncs, using m_decl.  */
@@ -114,6 +125,13 @@ tree_logical_location::get_kind () const
   return get_kind_for_tree (m_decl);
 }
 
+label_text
+tree_logical_location::get_name_for_path_output () const
+{
+  gcc_assert (m_decl);
+  return get_name_for_tree_for_path_output (m_decl);
+}
+
 /* class current_fndecl_logical_location : public compiler_logical_location.  */
 
 /* Implementation of the logical_location vfuncs, using
@@ -146,3 +164,10 @@ current_fndecl_logical_location::get_kind () const
   gcc_assert (current_function_decl);
   return get_kind_for_tree (current_function_decl);
 }
+
+label_text
+current_fndecl_logical_location::get_name_for_path_output () const
+{
+  gcc_assert (current_function_decl);
+  return get_name_for_tree_for_path_output (current_function_decl);
+}
diff --git a/gcc/tree-logical-location.h b/gcc/tree-logical-location.h
index feaad6ed899..8634f3a49c0 100644
--- a/gcc/tree-logical-location.h
+++ b/gcc/tree-logical-location.h
@@ -33,6 +33,7 @@ class compiler_logical_location : public logical_location
   static const char *get_name_with_scope_for_tree (tree);
   static const char *get_internal_name_for_tree (tree);
   static enum logical_location_kind get_kind_for_tree (tree);
+  static label_text get_name_for_tree_for_path_output (tree);
 };
 
 /* Concrete subclass of logical_location, with reference to a specific
@@ -47,6 +48,7 @@ public:
   const char *get_name_with_scope () const final override;
   const char *get_internal_name () const final override;
   enum logical_location_kind get_kind () const final override;
+  label_text get_name_for_path_output () const final override;
 
 private:
   tree m_decl;
@@ -62,6 +64,7 @@ public:
   const char *get_name_with_scope () const final override;
   const char *get_internal_name () const final override;
   enum logical_location_kind get_kind () const final override;
+  label_text get_name_for_path_output () const final override;
 };
 
 #endif /* GCC_TREE_LOGICAL_LOCATION_H.  */
-- 
2.26.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 3/7] diagnostics: remove tree usage from tree-diagnostic-path.cc
  2024-06-18 15:08 [pushed 0/7] diagnostics: remove "tree" dependency from diagnostic paths David Malcolm
  2024-06-18 15:08 ` [PATCH 1/7] diagnostics: move simple_diagnostic_{path,thread,event} to their own .h/cc David Malcolm
  2024-06-18 15:08 ` [PATCH 2/7] diagnostics: eliminate "tree" from diagnostic_{event,path} David Malcolm
@ 2024-06-18 15:08 ` David Malcolm
  2024-06-18 15:08 ` [PATCH 4/7] diagnostics: eliminate diagnostic_context::m_make_json_for_path David Malcolm
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Malcolm @ 2024-06-18 15:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

No functional change intended.

gcc/ChangeLog:
	* Makefile.in (OBJS): Add selftest-diagnostic-path.o and
	selftest-logical-location.o.
	* logical-location.h: Include "label-text.h".
	(class logical_location): Update leading comment.
	* selftest-diagnostic-path.cc: New file, adapted from
	simple-diagnostic-path.cc and from material in
	tree-diagnostic-path.cc.
	* selftest-diagnostic-path.h: New file, adapted from
	simple-diagnostic-path.h and from material in
	tree-diagnostic-path.cc.
	* selftest-logical-location.cc: New file.
	* selftest-logical-location.h: New file.
	* tree-diagnostic-path.cc: Remove includes of "tree-pretty-print.h",
	"langhooks.h", and "simple-diagnostic-path.h".  Add include of
	"selftest-diagnostic-path.h".
	(class test_diagnostic_path): Delete, in favor of new
	implementation in selftest-diagnostic-path.{h,cc}, which is
	directly derived from diagnostic_path, rather than from
	simple_diagnostic_path.
	(selftest::test_intraprocedural_path): Eliminate tree usage,
	via change to test_diagnostic_path, using strings rather than
	function_decls for identifying functions in the test.
	(selftest::test_interprocedural_path_1): Likewise.
	(selftest::test_interprocedural_path_2): Likewise.
	(selftest::test_recursion): Likewise.
	(selftest::test_control_flow_1): Likewise.
	(selftest::test_control_flow_2): Likewise.
	(selftest::test_control_flow_3): Likewise.
	(selftest::assert_cfg_edge_path_streq): Likewise.
	(selftest::test_control_flow_5): Likewise.
	(selftest::test_control_flow_6): Likewise.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/Makefile.in                  |   2 +
 gcc/logical-location.h           |   5 +-
 gcc/selftest-diagnostic-path.cc  | 233 +++++++++++++++++++++++++++++++
 gcc/selftest-diagnostic-path.h   | 163 +++++++++++++++++++++
 gcc/selftest-logical-location.cc |  71 ++++++++++
 gcc/selftest-logical-location.h  |  58 ++++++++
 gcc/tree-diagnostic-path.cc      | 161 +++++++--------------
 7 files changed, 580 insertions(+), 113 deletions(-)
 create mode 100644 gcc/selftest-diagnostic-path.cc
 create mode 100644 gcc/selftest-diagnostic-path.h
 create mode 100644 gcc/selftest-logical-location.cc
 create mode 100644 gcc/selftest-logical-location.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 35f259da858..a2799b8d826 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1700,6 +1700,8 @@ OBJS = \
 	ubsan.o \
 	sanopt.o \
 	sancov.o \
+	selftest-diagnostic-path.o \
+	selftest-logical-location.o \
 	simple-diagnostic-path.o \
 	tree-call-cdce.o \
 	tree-cfg.o \
diff --git a/gcc/logical-location.h b/gcc/logical-location.h
index c3b72081135..bba21087786 100644
--- a/gcc/logical-location.h
+++ b/gcc/logical-location.h
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_LOGICAL_LOCATION_H
 #define GCC_LOGICAL_LOCATION_H
 
+#include "label-text.h"
+
 /* An enum for discriminating between different kinds of logical location
    for a diagnostic.
 
@@ -46,7 +48,8 @@ enum logical_location_kind
    - "within function 'foo'", or
    - "within method 'bar'",
    but *without* requiring knowledge of trees
-   (see tree-logical-location.h for subclasses relating to trees).  */
+   (see tree-logical-location.h for concrete subclasses relating to trees,
+   and selftest-logical-location.h for a concrete subclass for selftests).  */
 
 class logical_location
 {
diff --git a/gcc/selftest-diagnostic-path.cc b/gcc/selftest-diagnostic-path.cc
new file mode 100644
index 00000000000..6d21f2e5599
--- /dev/null
+++ b/gcc/selftest-diagnostic-path.cc
@@ -0,0 +1,233 @@
+/* Concrete classes for selftests involving diagnostic paths.
+   Copyright (C) 2019-2024 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+
+#include "config.h"
+#define INCLUDE_VECTOR
+#include "system.h"
+#include "coretypes.h"
+#include "version.h"
+#include "demangle.h"
+#include "backtrace.h"
+#include "diagnostic.h"
+#include "selftest-diagnostic-path.h"
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* class test_diagnostic_path : public diagnostic_path.  */
+
+test_diagnostic_path::test_diagnostic_path (pretty_printer *event_pp)
+: m_event_pp (event_pp)
+{
+  add_thread ("main");
+}
+
+/* Implementation of diagnostic_path::num_events vfunc for
+   test_diagnostic_path: simply get the number of events in the vec.  */
+
+unsigned
+test_diagnostic_path::num_events () const
+{
+  return m_events.length ();
+}
+
+/* Implementation of diagnostic_path::get_event vfunc for
+   test_diagnostic_path: simply return the event in the vec.  */
+
+const diagnostic_event &
+test_diagnostic_path::get_event (int idx) const
+{
+  return *m_events[idx];
+}
+
+unsigned
+test_diagnostic_path::num_threads () const
+{
+  return m_threads.length ();
+}
+
+const diagnostic_thread &
+test_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
+{
+  return *m_threads[idx];
+}
+
+bool
+test_diagnostic_path::same_function_p (int event_idx_a,
+				       int event_idx_b) const
+{
+  const char *name_a = m_events[event_idx_a]->get_function_name ();
+  const char *name_b = m_events[event_idx_b]->get_function_name ();
+
+  if (name_a && name_b)
+    return 0 == strcmp (name_a, name_b);
+  return name_a == name_b;
+}
+
+diagnostic_thread_id_t
+test_diagnostic_path::add_thread (const char *name)
+{
+  m_threads.safe_push (new test_diagnostic_thread (name));
+  return m_threads.length () - 1;
+}
+
+/* Add an event to this path at LOC within function FNDECL at
+   stack depth DEPTH.
+
+   Use m_context's printer to format FMT, as the text of the new
+   event.
+
+   Return the id of the new event.  */
+
+diagnostic_event_id_t
+test_diagnostic_path::add_event (location_t loc,
+				 const char *funcname,
+				 int depth,
+				 const char *fmt, ...)
+{
+  pretty_printer *pp = m_event_pp;
+  pp_clear_output_area (pp);
+
+  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+
+  va_list ap;
+
+  va_start (ap, fmt);
+
+  /* No localization is done on FMT.  */
+  text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
+  pp_format (pp, &ti);
+  pp_output_formatted_text (pp);
+
+  va_end (ap);
+
+  test_diagnostic_event *new_event
+    = new test_diagnostic_event (loc, funcname, depth, pp_formatted_text (pp));
+  m_events.safe_push (new_event);
+
+  pp_clear_output_area (pp);
+
+  return diagnostic_event_id_t (m_events.length () - 1);
+}
+
+diagnostic_event_id_t
+test_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
+					location_t loc,
+					const char *funcname,
+					int depth,
+					const char *fmt, ...)
+{
+  pretty_printer *pp = m_event_pp;
+  pp_clear_output_area (pp);
+
+  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+
+  va_list ap;
+
+  va_start (ap, fmt);
+
+  /* No localization is done on FMT.  */
+  text_info ti (fmt, &ap, 0, nullptr, &rich_loc);
+
+  pp_format (pp, &ti);
+  pp_output_formatted_text (pp);
+
+  va_end (ap);
+
+  test_diagnostic_event *new_event
+    = new test_diagnostic_event (loc, funcname, depth, pp_formatted_text (pp),
+				   thread_id);
+  m_events.safe_push (new_event);
+
+  pp_clear_output_area (pp);
+
+  return diagnostic_event_id_t (m_events.length () - 1);
+}
+
+/* Mark the most recent event on this path (which must exist) as being
+   connected to the next one to be added.  */
+
+void
+test_diagnostic_path::connect_to_next_event ()
+{
+  gcc_assert (m_events.length () > 0);
+  m_events[m_events.length () - 1]->connect_to_next_event ();
+}
+
+void
+test_diagnostic_path::add_entry (const char *callee_name,
+				 int stack_depth,
+				 diagnostic_thread_id_t thread_id)
+{
+  add_thread_event (thread_id, UNKNOWN_LOCATION, callee_name, stack_depth,
+		    "entering %qs", callee_name);
+}
+
+void
+test_diagnostic_path::add_return (const char *caller_name,
+				  int stack_depth,
+				  diagnostic_thread_id_t thread_id)
+{
+  add_thread_event (thread_id, UNKNOWN_LOCATION, caller_name, stack_depth,
+		    "returning to %qs", caller_name);
+}
+
+void
+test_diagnostic_path::add_call (const char *caller_name,
+				int caller_stack_depth,
+				const char *callee_name,
+				diagnostic_thread_id_t thread_id)
+{
+  add_thread_event (thread_id, UNKNOWN_LOCATION,
+		    caller_name, caller_stack_depth,
+		    "calling %qs", callee_name);
+  add_entry (callee_name, caller_stack_depth + 1, thread_id);
+}
+
+/* struct test_diagnostic_event.  */
+
+/* test_diagnostic_event's ctor.  */
+
+test_diagnostic_event::
+test_diagnostic_event (location_t loc,
+			 const char *funcname,
+			 int depth,
+			 const char *desc,
+			 diagnostic_thread_id_t thread_id)
+: m_loc (loc),
+  m_logical_loc (LOGICAL_LOCATION_KIND_FUNCTION, funcname),
+  m_depth (depth), m_desc (xstrdup (desc)),
+  m_connected_to_next_event (false),
+  m_thread_id (thread_id)
+{
+}
+
+/* test_diagnostic_event's dtor.  */
+
+test_diagnostic_event::~test_diagnostic_event ()
+{
+  free (m_desc);
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/selftest-diagnostic-path.h b/gcc/selftest-diagnostic-path.h
new file mode 100644
index 00000000000..51786a0f589
--- /dev/null
+++ b/gcc/selftest-diagnostic-path.h
@@ -0,0 +1,163 @@
+/* Concrete classes for selftests involving diagnostic paths.
+   Copyright (C) 2019-2024 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_SELFTEST_DIAGNOSTIC_PATH_H
+#define GCC_SELFTEST_DIAGNOSTIC_PATH_H
+
+#include "diagnostic-path.h"
+#include "selftest-logical-location.h"
+
+/* The selftest code should entirely disappear in a production
+   configuration, hence we guard all of it with #if CHECKING_P.  */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Concrete subclasses of the abstract base classes
+   declared in diagnostic-path.h for use in selftests.
+
+   This code should have no dependency on "tree".  */
+
+/* An implementation of diagnostic_event.  */
+
+class test_diagnostic_event : public diagnostic_event
+{
+ public:
+  test_diagnostic_event (location_t loc, const char *funcname, int depth,
+			 const char *desc,
+			 diagnostic_thread_id_t thread_id = 0);
+  ~test_diagnostic_event ();
+
+  location_t get_location () const final override { return m_loc; }
+  int get_stack_depth () const final override { return m_depth; }
+  label_text get_desc (bool) const final override
+  {
+    return label_text::borrow (m_desc);
+  }
+  const logical_location *get_logical_location () const final override
+  {
+    if (m_logical_loc.get_name ())
+      return &m_logical_loc;
+    else
+      return nullptr;
+  }
+  meaning get_meaning () const final override
+  {
+    return meaning ();
+  }
+  bool connect_to_next_event_p () const final override
+  {
+    return m_connected_to_next_event;
+  }
+  diagnostic_thread_id_t get_thread_id () const final override
+  {
+    return m_thread_id;
+  }
+
+  void connect_to_next_event ()
+  {
+    m_connected_to_next_event = true;
+  }
+
+  const char *get_function_name () const
+  {
+    return m_logical_loc.get_name ();
+  }
+
+ private:
+  location_t m_loc;
+  test_logical_location m_logical_loc;
+  int m_depth;
+  char *m_desc; // has been formatted; doesn't get i18n-ed
+  bool m_connected_to_next_event;
+  diagnostic_thread_id_t m_thread_id;
+};
+
+/* A simple implementation of diagnostic_thread.  */
+
+class test_diagnostic_thread : public diagnostic_thread
+{
+public:
+  test_diagnostic_thread (const char *name) : m_name (name) {}
+  label_text get_name (bool) const final override
+  {
+    return label_text::borrow (m_name);
+  }
+
+private:
+  const char *m_name; // has been i18n-ed and formatted
+};
+
+/* A concrete subclass of diagnostic_path for implementing selftests
+   - a vector of test_diagnostic_event instances
+   - adds member functions for adding test event
+   - does no translation of its events
+   - has no dependency on "tree".  */
+
+class test_diagnostic_path : public diagnostic_path
+{
+ public:
+  test_diagnostic_path (pretty_printer *event_pp);
+
+  unsigned num_events () const final override;
+  const diagnostic_event & get_event (int idx) const final override;
+  unsigned num_threads () const final override;
+  const diagnostic_thread &
+  get_thread (diagnostic_thread_id_t) const final override;
+  bool
+  same_function_p (int event_idx_a,
+		   int event_idx_b) const final override;
+
+  diagnostic_thread_id_t add_thread (const char *name);
+
+  diagnostic_event_id_t add_event (location_t loc, const char *funcname, int depth,
+				   const char *fmt, ...)
+    ATTRIBUTE_GCC_DIAG(5,6);
+  diagnostic_event_id_t
+  add_thread_event (diagnostic_thread_id_t thread_id,
+		    location_t loc, const char *funcname, int depth,
+		    const char *fmt, ...)
+    ATTRIBUTE_GCC_DIAG(6,7);
+
+  void connect_to_next_event ();
+
+  void add_entry (const char *callee_name, int stack_depth,
+		  diagnostic_thread_id_t thread_id = 0);
+  void add_return (const char *caller_name, int stack_depth,
+		   diagnostic_thread_id_t thread_id = 0);
+  void add_call (const char *caller_name,
+		 int caller_stack_depth,
+		 const char *callee_name,
+		 diagnostic_thread_id_t thread_id = 0);
+
+ private:
+  auto_delete_vec<test_diagnostic_thread> m_threads;
+  auto_delete_vec<test_diagnostic_event> m_events;
+
+  /* (for use by add_event).  */
+  pretty_printer *m_event_pp;
+};
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+#endif /* ! GCC_SELFTEST_DIAGNOSTIC_PATH_H */
diff --git a/gcc/selftest-logical-location.cc b/gcc/selftest-logical-location.cc
new file mode 100644
index 00000000000..8017672afa7
--- /dev/null
+++ b/gcc/selftest-logical-location.cc
@@ -0,0 +1,71 @@
+/* Concrete subclass of logical_location for use in selftests.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "selftest-logical-location.h"
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* class test_logical_location : public logical_location.  */
+
+test_logical_location::test_logical_location (enum logical_location_kind kind,
+					      const char *name)
+: m_kind (kind),
+  m_name (name)
+{
+}
+
+const char *
+test_logical_location::get_short_name () const
+{
+  return m_name;
+}
+
+const char *
+test_logical_location::get_name_with_scope () const
+{
+  return m_name;
+}
+
+const char *
+test_logical_location::get_internal_name () const
+{
+  return m_name;
+}
+
+enum logical_location_kind
+test_logical_location::get_kind () const
+{
+  return m_kind;
+}
+
+label_text
+test_logical_location::get_name_for_path_output () const
+{
+  return label_text::borrow (m_name);
+}
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/selftest-logical-location.h b/gcc/selftest-logical-location.h
new file mode 100644
index 00000000000..819e111851e
--- /dev/null
+++ b/gcc/selftest-logical-location.h
@@ -0,0 +1,58 @@
+/* Concrete subclass of logical_location for use in selftests.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_SELFTEST_LOGICAL_LOCATION_H
+#define GCC_SELFTEST_LOGICAL_LOCATION_H
+
+#include "logical-location.h"
+
+/* The selftest code should entirely disappear in a production
+   configuration, hence we guard all of it with #if CHECKING_P.  */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Concrete subclass of logical_location for use in selftests.  */
+
+class test_logical_location : public logical_location
+{
+public:
+  test_logical_location (enum logical_location_kind kind,
+			 const char *name);
+  virtual const char *get_short_name () const final override;
+  virtual const char *get_name_with_scope () const final override;
+  virtual const char *get_internal_name () const final override;
+  virtual enum logical_location_kind get_kind () const final override;
+  virtual label_text get_name_for_path_output () const final override;
+
+  const char *get_name () const { return m_name; }
+
+ private:
+  enum logical_location_kind m_kind;
+  const char *m_name;
+};
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+
+#endif /* GCC_SELFTEST_LOGICAL_LOCATION_H.  */
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 4287b90d5dd..39a85d33015 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -27,13 +27,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tree.h"
 #include "diagnostic.h"
-#include "tree-pretty-print.h"
-#include "gimple-pretty-print.h"
 #include "tree-diagnostic.h"
-#include "langhooks.h"
 #include "intl.h"
 #include "diagnostic-path.h"
-#include "simple-diagnostic-path.h"
 #include "json.h"
 #include "gcc-rich-location.h"
 #include "diagnostic-color.h"
@@ -41,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-label-effects.h"
 #include "selftest.h"
 #include "selftest-diagnostic.h"
+#include "selftest-diagnostic-path.h"
 #include "text-art/theme.h"
 
 /* Disable warnings about missing quoting in GCC diagnostics for the print
@@ -1013,38 +1010,6 @@ path_events_have_column_data_p (const diagnostic_path &path)
   return true;
 }
 
-/* A subclass of simple_diagnostic_path that adds member functions
-   for adding test events and suppresses translation of these events.  */
-
-class test_diagnostic_path : public simple_diagnostic_path
-{
- public:
-  test_diagnostic_path (pretty_printer *event_pp)
-  : simple_diagnostic_path (event_pp)
-  {
-    disable_event_localization ();
-  }
-
-  void add_entry (tree fndecl, int stack_depth)
-  {
-    add_event (UNKNOWN_LOCATION, fndecl, stack_depth,
-	       "entering %qE", fndecl);
-  }
-
-  void add_return (tree fndecl, int stack_depth)
-  {
-    add_event (UNKNOWN_LOCATION, fndecl, stack_depth,
-	       "returning to %qE", fndecl);
-  }
-
-  void add_call (tree caller, int caller_stack_depth, tree callee)
-  {
-    add_event (UNKNOWN_LOCATION, caller, caller_stack_depth,
-	       "calling %qE", callee);
-    add_entry (callee, caller_stack_depth + 1);
-  }
-};
-
 /* Verify that empty paths are handled gracefully.  */
 
 static void
@@ -1067,13 +1032,10 @@ test_empty_path (pretty_printer *event_pp)
 static void
 test_intraprocedural_path (pretty_printer *event_pp)
 {
-  tree fntype_void_void
-    = build_function_type_array (void_type_node, 0, NULL);
-  tree fndecl_foo = build_fn_decl ("foo", fntype_void_void);
-
   test_diagnostic_path path (event_pp);
-  path.add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "first %qs", "free");
-  path.add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "double %qs", "free");
+  const char *const funcname = "foo";
+  path.add_event (UNKNOWN_LOCATION, funcname, 0, "first %qs", "free");
+  path.add_event (UNKNOWN_LOCATION, funcname, 0, "double %qs", "free");
 
   ASSERT_FALSE (path.interprocedural_p ());
 
@@ -1093,33 +1055,20 @@ test_intraprocedural_path (pretty_printer *event_pp)
 static void
 test_interprocedural_path_1 (pretty_printer *event_pp)
 {
-  /* Build fndecls.  The types aren't quite right, but that
-     doesn't matter for the purposes of this test.  */
-  tree fntype_void_void
-    = build_function_type_array (void_type_node, 0, NULL);
-  tree fndecl_test = build_fn_decl ("test", fntype_void_void);
-  tree fndecl_make_boxed_int
-    = build_fn_decl ("make_boxed_int", fntype_void_void);
-  tree fndecl_wrapped_malloc
-    = build_fn_decl ("wrapped_malloc", fntype_void_void);
-  tree fndecl_free_boxed_int
-    = build_fn_decl ("free_boxed_int", fntype_void_void);
-  tree fndecl_wrapped_free
-    = build_fn_decl ("wrapped_free", fntype_void_void);
-
   test_diagnostic_path path (event_pp);
-  path.add_entry (fndecl_test, 0);
-  path.add_call (fndecl_test, 0, fndecl_make_boxed_int);
-  path.add_call (fndecl_make_boxed_int, 1, fndecl_wrapped_malloc);
-  path.add_event (UNKNOWN_LOCATION, fndecl_wrapped_malloc, 2, "calling malloc");
-  path.add_return (fndecl_test, 0);
-  path.add_call (fndecl_test, 0, fndecl_free_boxed_int);
-  path.add_call (fndecl_free_boxed_int, 1, fndecl_wrapped_free);
-  path.add_event (UNKNOWN_LOCATION, fndecl_wrapped_free, 2, "calling free");
-  path.add_return (fndecl_test, 0);
-  path.add_call (fndecl_test, 0, fndecl_free_boxed_int);
-  path.add_call (fndecl_free_boxed_int, 1, fndecl_wrapped_free);
-  path.add_event (UNKNOWN_LOCATION, fndecl_wrapped_free, 2, "calling free");
+  path.add_entry ("test", 0);
+  path.add_call ("test", 0, "make_boxed_int");
+  path.add_call ("make_boxed_int", 1, "wrapped_malloc");
+  path.add_event (UNKNOWN_LOCATION,
+		  "wrapped_malloc", 2, "calling malloc");
+  path.add_return ("test", 0);
+  path.add_call ("test", 0, "free_boxed_int");
+  path.add_call ("free_boxed_int", 1, "wrapped_free");
+  path.add_event (UNKNOWN_LOCATION, "wrapped_free", 2, "calling free");
+  path.add_return ("test", 0);
+  path.add_call ("test", 0, "free_boxed_int");
+  path.add_call ("free_boxed_int", 1, "wrapped_free");
+  path.add_event (UNKNOWN_LOCATION, "wrapped_free", 2, "calling free");
   ASSERT_EQ (path.num_events (), 18);
 
   ASSERT_TRUE (path.interprocedural_p ());
@@ -1248,20 +1197,12 @@ test_interprocedural_path_1 (pretty_printer *event_pp)
 static void
 test_interprocedural_path_2 (pretty_printer *event_pp)
 {
-  /* Build fndecls.  The types aren't quite right, but that
-     doesn't matter for the purposes of this test.  */
-  tree fntype_void_void
-    = build_function_type_array (void_type_node, 0, NULL);
-  tree fndecl_foo = build_fn_decl ("foo", fntype_void_void);
-  tree fndecl_bar = build_fn_decl ("bar", fntype_void_void);
-  tree fndecl_baz = build_fn_decl ("baz", fntype_void_void);
-
   test_diagnostic_path path (event_pp);
-  path.add_entry (fndecl_foo, 0);
-  path.add_call (fndecl_foo, 0, fndecl_bar);
-  path.add_call (fndecl_bar, 1, fndecl_baz);
-  path.add_return (fndecl_bar, 1);
-  path.add_call (fndecl_bar, 1, fndecl_baz);
+  path.add_entry ("foo", 0);
+  path.add_call ("foo", 0, "bar");
+  path.add_call ("bar", 1, "baz");
+  path.add_return ("bar", 1);
+  path.add_call ("bar", 1, "baz");
   ASSERT_EQ (path.num_events (), 8);
 
   ASSERT_TRUE (path.interprocedural_p ());
@@ -1341,14 +1282,10 @@ test_interprocedural_path_2 (pretty_printer *event_pp)
 static void
 test_recursion (pretty_printer *event_pp)
 {
-  tree fntype_void_void
-    = build_function_type_array (void_type_node, 0, NULL);
-  tree fndecl_factorial = build_fn_decl ("factorial", fntype_void_void);
-
  test_diagnostic_path path (event_pp);
-  path.add_entry (fndecl_factorial, 0);
+  path.add_entry ("factorial", 0);
   for (int depth = 0; depth < 3; depth++)
-    path.add_call (fndecl_factorial, depth, fndecl_factorial);
+    path.add_call ("factorial", depth, "factorial");
   ASSERT_EQ (path.num_events (), 7);
 
   ASSERT_TRUE (path.interprocedural_p ());
@@ -1485,14 +1422,14 @@ test_control_flow_1 (const line_table_case &case_,
   const location_t cfg_dest = t.get_line_and_column (5, 10);
 
   test_diagnostic_path path (event_pp);
-  path.add_event (conditional, NULL_TREE, 0,
+  path.add_event (conditional, nullptr, 0,
 		  "following %qs branch (when %qs is NULL)...",
 		  "false", "p");
   path.connect_to_next_event ();
 
-  path.add_event (cfg_dest, NULL_TREE, 0,
+  path.add_event (cfg_dest, nullptr, 0,
 		  "...to here");
-  path.add_event (cfg_dest, NULL_TREE, 0,
+  path.add_event (cfg_dest, nullptr, 0,
 		  "dereference of NULL %qs",
 		  "p");
 
@@ -1665,17 +1602,17 @@ test_control_flow_2 (const line_table_case &case_,
   const location_t loop_body_end = t.get_line_and_columns (5, 5, 9, 17);
 
   test_diagnostic_path path (event_pp);
-  path.add_event (iter_test, NULL_TREE, 0, "infinite loop here");
+  path.add_event (iter_test, nullptr, 0, "infinite loop here");
 
-  path.add_event (iter_test, NULL_TREE, 0, "looping from here...");
+  path.add_event (iter_test, nullptr, 0, "looping from here...");
   path.connect_to_next_event ();
 
-  path.add_event (loop_body_start, NULL_TREE, 0, "...to here");
+  path.add_event (loop_body_start, nullptr, 0, "...to here");
 
-  path.add_event (loop_body_end, NULL_TREE, 0, "looping back...");
+  path.add_event (loop_body_end, nullptr, 0, "looping back...");
   path.connect_to_next_event ();
 
-  path.add_event (iter_test, NULL_TREE, 0, "...to here");
+  path.add_event (iter_test, nullptr, 0, "...to here");
 
   if (!path_events_have_column_data_p (path))
     return;
@@ -1751,17 +1688,17 @@ test_control_flow_3 (const line_table_case &case_,
   const location_t iter_next = t.get_line_and_columns (3, 22, 24);
 
   test_diagnostic_path path (event_pp);
-  path.add_event (iter_test, NULL_TREE, 0, "infinite loop here");
+  path.add_event (iter_test, nullptr, 0, "infinite loop here");
 
-  path.add_event (iter_test, NULL_TREE, 0, "looping from here...");
+  path.add_event (iter_test, nullptr, 0, "looping from here...");
   path.connect_to_next_event ();
 
-  path.add_event (iter_next, NULL_TREE, 0, "...to here");
+  path.add_event (iter_next, nullptr, 0, "...to here");
 
-  path.add_event (iter_next, NULL_TREE, 0, "looping back...");
+  path.add_event (iter_next, nullptr, 0, "looping back...");
   path.connect_to_next_event ();
 
-  path.add_event (iter_test, NULL_TREE, 0, "...to here");
+  path.add_event (iter_test, nullptr, 0, "...to here");
 
   if (!path_events_have_column_data_p (path))
     return;
@@ -1816,10 +1753,10 @@ assert_cfg_edge_path_streq (const location &loc,
 			    const char *expected_str)
 {
   test_diagnostic_path path (event_pp);
-  path.add_event (src_loc, NULL_TREE, 0, "from here...");
+  path.add_event (src_loc, nullptr, 0, "from here...");
   path.connect_to_next_event ();
 
-  path.add_event (dst_loc, NULL_TREE, 0, "...to here");
+  path.add_event (dst_loc, nullptr, 0, "...to here");
 
   if (!path_events_have_column_data_p (path))
     return;
@@ -2120,27 +2057,27 @@ test_control_flow_5 (const line_table_case &case_,
 
   test_diagnostic_path path (event_pp);
   /* (1) */
-  path.add_event (t.get_line_and_column (1, 6), NULL_TREE, 0,
+  path.add_event (t.get_line_and_column (1, 6), nullptr, 0,
 		  "following %qs branch (when %qs is non-NULL)...",
 		  "false", "arr");
   path.connect_to_next_event ();
 
   /* (2) */
-  path.add_event (t.get_line_and_columns (4, 8, 10, 12), NULL_TREE, 0,
+  path.add_event (t.get_line_and_columns (4, 8, 10, 12), nullptr, 0,
 		  "...to here");
 
   /* (3) */
-  path.add_event (t.get_line_and_columns (4, 15, 17, 19), NULL_TREE, 0,
+  path.add_event (t.get_line_and_columns (4, 15, 17, 19), nullptr, 0,
 		  "following %qs branch (when %qs)...",
 		  "true", "i < n");
   path.connect_to_next_event ();
 
   /* (4) */
-  path.add_event (t.get_line_and_column (5, 13), NULL_TREE, 0,
+  path.add_event (t.get_line_and_column (5, 13), nullptr, 0,
 		  "...to here");
 
   /* (5) */
-  path.add_event (t.get_line_and_columns (5, 33, 58), NULL_TREE, 0,
+  path.add_event (t.get_line_and_columns (5, 33, 58), nullptr, 0,
 		  "allocated here");
 
   if (!path_events_have_column_data_p (path))
@@ -2208,27 +2145,27 @@ test_control_flow_6 (const line_table_case &case_,
 
   test_diagnostic_path path (event_pp);
   /* (1) */
-  path.add_event (t.get_line_and_columns (6, 25, 35), NULL_TREE, 0,
+  path.add_event (t.get_line_and_columns (6, 25, 35), nullptr, 0,
 		  "allocated here");
 
   /* (2) */
-  path.add_event (t.get_line_and_columns (8, 13, 14, 17), NULL_TREE, 0,
+  path.add_event (t.get_line_and_columns (8, 13, 14, 17), nullptr, 0,
 		  "following %qs branch (when %qs)...",
 		  "true", "i <= 254");
   path.connect_to_next_event ();
 
   /* (3) */
-  path.add_event (t.get_line_and_columns (9, 5, 15, 17), NULL_TREE, 0,
+  path.add_event (t.get_line_and_columns (9, 5, 15, 17), nullptr, 0,
 		  "...to here");
 
   /* (4) */
-  path.add_event (t.get_line_and_columns (8, 13, 14, 17), NULL_TREE, 0,
+  path.add_event (t.get_line_and_columns (8, 13, 14, 17), nullptr, 0,
 		  "following %qs branch (when %qs)...",
 		  "true", "i <= 254");
   path.connect_to_next_event ();
 
   /* (5) */
-  path.add_event (t.get_line_and_columns (9, 5, 15, 17), NULL_TREE, 0,
+  path.add_event (t.get_line_and_columns (9, 5, 15, 17), nullptr, 0,
 		  "...to here");
 
   if (!path_events_have_column_data_p (path))
-- 
2.26.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 4/7] diagnostics: eliminate diagnostic_context::m_make_json_for_path
  2024-06-18 15:08 [pushed 0/7] diagnostics: remove "tree" dependency from diagnostic paths David Malcolm
                   ` (2 preceding siblings ...)
  2024-06-18 15:08 ` [PATCH 3/7] diagnostics: remove tree usage from tree-diagnostic-path.cc David Malcolm
@ 2024-06-18 15:08 ` David Malcolm
  2024-06-18 15:08 ` [PATCH 5/7] diagnostics: introduce diagnostic-macro-unwinding.h/cc David Malcolm
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: David Malcolm @ 2024-06-18 15:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Now that the path-handling code for json_output_format no longer
needs "tree", and thus can be in OBJS-libcommon we can move it
from tree-diagnostic-path.cc to diagnostic-format-json.cc where it
should have been all along.

No functional change intended.

gcc/ChangeLog:
	* diagnostic-format-json.cc: Include "diagnostic-path.h" and
	"logical-location.h".
	(make_json_for_path): Move tree-diagnostic-path.cc's
	default_tree_make_json_for_path here, renaming it and making it
	static.
	(json_output_format::on_end_diagnostic): Replace call of
	m_context's m_make_json_for_path callback with a direct call to
	make_json_for_path.
	* diagnostic.h (diagnostic_context::m_make_json_for_path): Drop
	field.
	* tree-diagnostic-path.cc: Drop include of "json.h".
	(default_tree_make_json_for_path): Rename to make_json_for_path
	and move to diagnostic-format-json.cc.
	* tree-diagnostic.cc (tree_diagnostics_defaults): Drop
	initialization of m_make_json_for_path.
	* tree-diagnostic.h (default_tree_make_json_for): Delete decl.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/diagnostic-format-json.cc | 37 ++++++++++++++++++++++++++++++++---
 gcc/diagnostic.h              |  2 --
 gcc/tree-diagnostic-path.cc   | 32 ------------------------------
 gcc/tree-diagnostic.cc        |  1 -
 gcc/tree-diagnostic.h         |  2 --
 5 files changed, 34 insertions(+), 40 deletions(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 0782ae831eb..2bdc2c13d37 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -25,8 +25,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic.h"
 #include "selftest-diagnostic.h"
 #include "diagnostic-metadata.h"
+#include "diagnostic-path.h"
 #include "json.h"
 #include "selftest.h"
+#include "logical-location.h"
 
 /* Subclass of diagnostic_output_format for JSON output.  */
 
@@ -187,6 +189,36 @@ json_from_metadata (const diagnostic_metadata *metadata)
   return metadata_obj;
 }
 
+/* Make a JSON value for PATH.  */
+
+static json::value *
+make_json_for_path (diagnostic_context *context,
+		    const diagnostic_path *path)
+{
+  json::array *path_array = new json::array ();
+  for (unsigned i = 0; i < path->num_events (); i++)
+    {
+      const diagnostic_event &event = path->get_event (i);
+
+      json::object *event_obj = new json::object ();
+      if (event.get_location ())
+	event_obj->set ("location",
+			json_from_expanded_location (context,
+						     event.get_location ()));
+      label_text event_text (event.get_desc (false));
+      event_obj->set_string ("description", event_text.get ());
+      if (const logical_location *logical_loc = event.get_logical_location ())
+	{
+	  label_text name (logical_loc->get_name_for_path_output ());
+	  event_obj->set_string ("function", name.get ());
+	}
+      event_obj->set_integer ("depth", event.get_stack_depth ());
+      path_array->append (event_obj);
+    }
+  return path_array;
+}
+
+
 /* Implementation of "on_end_diagnostic" vfunc for JSON output.
    Generate a JSON object for DIAGNOSTIC, and store for output
    within current diagnostic group.  */
@@ -291,10 +323,9 @@ json_output_format::on_end_diagnostic (const diagnostic_info &diagnostic,
     }
 
   const diagnostic_path *path = richloc->get_path ();
-  if (path && m_context.m_make_json_for_path)
+  if (path)
     {
-      json::value *path_value
-	= m_context.m_make_json_for_path (&m_context, path);
+      json::value *path_value = make_json_for_path (&m_context, path);
       diag_obj->set ("path", path_value);
     }
 
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 9a9571bb76d..ff2aa3dd9a3 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -713,8 +713,6 @@ private:
 
 public:
   void (*m_print_path) (diagnostic_context *, const diagnostic_path *);
-  json::value *(*m_make_json_for_path) (diagnostic_context *,
-					const diagnostic_path *);
 
   /* Auxiliary data for client.  */
   void *m_client_aux_data;
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 39a85d33015..40b197d971c 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -30,7 +30,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-diagnostic.h"
 #include "intl.h"
 #include "diagnostic-path.h"
-#include "json.h"
 #include "gcc-rich-location.h"
 #include "diagnostic-color.h"
 #include "diagnostic-event-id.h"
@@ -954,37 +953,6 @@ default_tree_diagnostic_path_printer (diagnostic_context *context,
     }
 }
 
-/* This has to be here, rather than diagnostic-format-json.cc,
-   since diagnostic-format-json.o is within OBJS-libcommon and thus
-   doesn't have access to trees (for m_fndecl).  */
-
-json::value *
-default_tree_make_json_for_path (diagnostic_context *context,
-				 const diagnostic_path *path)
-{
-  json::array *path_array = new json::array ();
-  for (unsigned i = 0; i < path->num_events (); i++)
-    {
-      const diagnostic_event &event = path->get_event (i);
-
-      json::object *event_obj = new json::object ();
-      if (event.get_location ())
-	event_obj->set ("location",
-			json_from_expanded_location (context,
-						     event.get_location ()));
-      label_text event_text (event.get_desc (false));
-      event_obj->set_string ("description", event_text.get ());
-      if (const logical_location *logical_loc = event.get_logical_location ())
-	{
-	  label_text name (logical_loc->get_name_for_path_output ());
-	  event_obj->set_string ("function", name.get ());
-	}
-      event_obj->set_integer ("depth", event.get_stack_depth ());
-      path_array->append (event_obj);
-    }
-  return path_array;
-}
-
 #if CHECKING_P
 
 namespace selftest {
diff --git a/gcc/tree-diagnostic.cc b/gcc/tree-diagnostic.cc
index a660c7d0785..f6e2a73497a 100644
--- a/gcc/tree-diagnostic.cc
+++ b/gcc/tree-diagnostic.cc
@@ -375,7 +375,6 @@ tree_diagnostics_defaults (diagnostic_context *context)
   diagnostic_finalizer (context) = default_diagnostic_finalizer;
   diagnostic_format_decoder (context) = default_tree_printer;
   context->m_print_path = default_tree_diagnostic_path_printer;
-  context->m_make_json_for_path = default_tree_make_json_for_path;
   context->set_set_locations_callback (set_inlining_locations);
   context->set_client_data_hooks (make_compiler_data_hooks ());
 }
diff --git a/gcc/tree-diagnostic.h b/gcc/tree-diagnostic.h
index 1d13368537a..7959294f489 100644
--- a/gcc/tree-diagnostic.h
+++ b/gcc/tree-diagnostic.h
@@ -59,8 +59,6 @@ bool default_tree_printer (pretty_printer *, text_info *, const char *,
 
 extern void default_tree_diagnostic_path_printer (diagnostic_context *,
 						  const diagnostic_path *);
-extern json::value *default_tree_make_json_for_path (diagnostic_context *,
-						     const diagnostic_path *);
 
 extern void maybe_unwind_expanded_macro_loc (diagnostic_context *context,
 					     location_t where);
-- 
2.26.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 5/7] diagnostics: introduce diagnostic-macro-unwinding.h/cc
  2024-06-18 15:08 [pushed 0/7] diagnostics: remove "tree" dependency from diagnostic paths David Malcolm
                   ` (3 preceding siblings ...)
  2024-06-18 15:08 ` [PATCH 4/7] diagnostics: eliminate diagnostic_context::m_make_json_for_path David Malcolm
@ 2024-06-18 15:08 ` David Malcolm
  2024-06-18 15:08 ` [PATCH 6/7] diagnostics: eliminate diagnostic_context::m_print_path callback David Malcolm
  2024-06-18 15:08 ` [PATCH 7/7] diagnostics: rename tree-diagnostic-path.cc to diagnostic-path.cc David Malcolm
  6 siblings, 0 replies; 9+ messages in thread
From: David Malcolm @ 2024-06-18 15:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Eliminate a dependency on "tree" from the code used by
diagnostic_path handling.

No functional change intended.

gcc/ChangeLog:
	* Makefile.in (OBJS): Add diagnostic-macro-unwinding.o.

gcc/c-family/ChangeLog:
	* c-opts.cc: Replace include of "tree-diagnostic.h" with
	"diagnostic-macro-unwinding.h".

gcc/ChangeLog:
	* diagnostic-macro-unwinding.cc: New file, with material taken
	from tree-diagnostic.cc.
	* diagnostic-macro-unwinding.h: New file, with material taken
	from tree-diagnostic.h.
	* tree-diagnostic-path.cc: Repalce include of "tree-diagnostic.h"
	with "diagnostic-macro-unwinding.h".
	* tree-diagnostic.cc (struct loc_map_pair): Move to
	diagnostic-macro-unwinding.cc.
	(maybe_unwind_expanded_macro_loc): Likewise.
	(virt_loc_aware_diagnostic_finalizer): Likewise.
	* tree-diagnostic.h (virt_loc_aware_diagnostic_finalizer): Move
	decl to diagnostic-macro-unwinding.h.
	(maybe_unwind_expanded_macro_loc): Likewise.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/Makefile.in                   |   1 +
 gcc/c-family/c-opts.cc            |   2 +-
 gcc/diagnostic-macro-unwinding.cc | 221 ++++++++++++++++++++++++++++++
 gcc/diagnostic-macro-unwinding.h  |  29 ++++
 gcc/tree-diagnostic-path.cc       |   2 +-
 gcc/tree-diagnostic.cc            | 195 --------------------------
 gcc/tree-diagnostic.h             |   5 -
 7 files changed, 253 insertions(+), 202 deletions(-)
 create mode 100644 gcc/diagnostic-macro-unwinding.cc
 create mode 100644 gcc/diagnostic-macro-unwinding.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index a2799b8d826..e701d9fb082 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1826,6 +1826,7 @@ OBJS = \
 OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
 	diagnostic-format-json.o \
 	diagnostic-format-sarif.o \
+	diagnostic-macro-unwinding.o \
 	diagnostic-show-locus.o \
 	edit-context.o \
 	pretty-print.o intl.o \
diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index faaf9ee6350..33114f13c8d 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -32,7 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "toplev.h"
 #include "langhooks.h"
-#include "tree-diagnostic.h" /* for virt_loc_aware_diagnostic_finalizer */
+#include "diagnostic-macro-unwinding.h" /* for virt_loc_aware_diagnostic_finalizer */
 #include "intl.h"
 #include "cppdefault.h"
 #include "incpath.h"
diff --git a/gcc/diagnostic-macro-unwinding.cc b/gcc/diagnostic-macro-unwinding.cc
new file mode 100644
index 00000000000..3056d8c8afb
--- /dev/null
+++ b/gcc/diagnostic-macro-unwinding.cc
@@ -0,0 +1,221 @@
+/* Code for unwinding macro expansions in diagnostics.
+   Copyright (C) 1999-2024 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "diagnostic.h"
+#include "diagnostic-macro-unwinding.h"
+#include "intl.h"
+
+/* This is a pair made of a location and the line map it originated
+   from.  It's used in the maybe_unwind_expanded_macro_loc function
+   below.  */
+struct loc_map_pair
+{
+  const line_map_macro *map;
+  location_t where;
+};
+
+
+/* Unwind the different macro expansions that lead to the token which
+   location is WHERE and emit diagnostics showing the resulting
+   unwound macro expansion trace.  Let's look at an example to see how
+   the trace looks like.  Suppose we have this piece of code,
+   artificially annotated with the line numbers to increase
+   legibility:
+
+    $ cat -n test.c
+      1    #define OPERATE(OPRD1, OPRT, OPRD2) \
+      2      OPRD1 OPRT OPRD2;
+      3
+      4    #define SHIFTL(A,B) \
+      5      OPERATE (A,<<,B)
+      6
+      7    #define MULT(A) \
+      8      SHIFTL (A,1)
+      9
+     10    void
+     11    g ()
+     12    {
+     13      MULT (1.0);// 1.0 << 1; <-- so this is an error.
+     14    }
+
+   Here is the diagnostic that we want the compiler to generate:
+
+    test.c: In function ‘g’:
+    test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’)
+    test.c:2:9: note: in definition of macro 'OPERATE'
+    test.c:8:3: note: in expansion of macro 'SHIFTL'
+    test.c:13:3: note: in expansion of macro 'MULT'
+
+   The part that goes from the third to the fifth line of this
+   diagnostic (the lines containing the 'note:' string) is called the
+   unwound macro expansion trace.  That's the part generated by this
+   function.  */
+
+void
+maybe_unwind_expanded_macro_loc (diagnostic_context *context,
+                                 location_t where)
+{
+  const struct line_map *map;
+  auto_vec<loc_map_pair> loc_vec;
+  unsigned ix;
+  loc_map_pair loc, *iter;
+
+  const location_t original_loc = where;
+
+  map = linemap_lookup (line_table, where);
+  if (!linemap_macro_expansion_map_p (map))
+    return;
+
+  /* Let's unwind the macros that got expanded and led to the token
+     which location is WHERE.  We are going to store these macros into
+     LOC_VEC, so that we can later walk it at our convenience to
+     display a somewhat meaningful trace of the macro expansion
+     history to the user.  Note that the first macro of the trace
+     (which is OPERATE in the example above) is going to be stored at
+     the beginning of LOC_VEC.  */
+
+  do
+    {
+      loc.where = where;
+      loc.map = linemap_check_macro (map);
+
+      loc_vec.safe_push (loc);
+
+      /* WHERE is the location of a token inside the expansion of a
+         macro.  MAP is the map holding the locations of that macro
+         expansion.  Let's get the location of the token inside the
+         context that triggered the expansion of this macro.
+         This is basically how we go "down" in the trace of macro
+         expansions that led to WHERE.  */
+      where = linemap_unwind_toward_expansion (line_table, where, &map);
+    } while (linemap_macro_expansion_map_p (map));
+
+  /* Now map is set to the map of the location in the source that
+     first triggered the macro expansion.  This must be an ordinary map.  */
+  const line_map_ordinary *ord_map = linemap_check_ordinary (map);
+
+  /* Walk LOC_VEC and print the macro expansion trace, unless the
+     first macro which expansion triggered this trace was expanded
+     inside a system header.  */
+  int saved_location_line =
+    expand_location_to_spelling_point (original_loc).line;
+
+  if (!LINEMAP_SYSP (ord_map))
+    FOR_EACH_VEC_ELT (loc_vec, ix, iter)
+      {
+	/* Sometimes, in the unwound macro expansion trace, we want to
+	   print a part of the context that shows where, in the
+	   definition of the relevant macro, is the token (we are
+	   looking at) used.  That is the case in the introductory
+	   comment of this function, where we print:
+
+	       test.c:2:9: note: in definition of macro 'OPERATE'.
+
+	   We print that "macro definition context" because the
+	   diagnostic line (emitted by the call to
+	   pp_ouput_formatted_text in diagnostic_report_diagnostic):
+
+	       test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’)
+
+	   does not point into the definition of the macro where the
+	   token '<<' (that is an argument to the function-like macro
+	   OPERATE) is used.  So we must "display" the line of that
+	   macro definition context to the user somehow.
+
+	   A contrario, when the first interesting diagnostic line
+	   points into the definition of the macro, we don't need to
+	   display any line for that macro definition in the trace
+	   anymore, otherwise it'd be redundant.  */
+
+        /* Okay, now here is what we want.  For each token resulting
+           from macro expansion we want to show: 1/ where in the
+           definition of the macro the token comes from; 2/ where the
+           macro got expanded.  */
+
+        /* Resolve the location iter->where into the locus 1/ of the
+           comment above.  */
+        location_t resolved_def_loc =
+          linemap_resolve_location (line_table, iter->where,
+                                    LRK_MACRO_DEFINITION_LOCATION, NULL);
+
+	/* Don't print trace for locations that are reserved or from
+	   within a system header.  */
+        const line_map_ordinary *m = NULL;
+        location_t l = 
+          linemap_resolve_location (line_table, resolved_def_loc,
+                                    LRK_SPELLING_LOCATION,  &m);
+	location_t l0 = l;
+	if (IS_ADHOC_LOC (l0))
+	  l0 = get_location_from_adhoc_loc (line_table, l0);
+	if (l0 < RESERVED_LOCATION_COUNT || LINEMAP_SYSP (m))
+          continue;
+        
+	/* We need to print the context of the macro definition only
+	   when the locus of the first displayed diagnostic (displayed
+	   before this trace) was inside the definition of the
+	   macro.  */
+	const int resolved_def_loc_line = SOURCE_LINE (m, l0);
+        if (ix == 0 && saved_location_line != resolved_def_loc_line)
+          {
+            diagnostic_append_note (context, resolved_def_loc, 
+                                    "in definition of macro %qs",
+                                    linemap_map_get_macro_name (iter->map));
+            /* At this step, as we've printed the context of the macro
+               definition, we don't want to print the context of its
+               expansion, otherwise, it'd be redundant.  */
+            continue;
+          }
+
+        /* Resolve the location of the expansion point of the macro
+           which expansion gave the token represented by def_loc.
+           This is the locus 2/ of the earlier comment.  */
+        location_t resolved_exp_loc =
+          linemap_resolve_location (line_table,
+                                    iter->map->get_expansion_point_location (),
+                                    LRK_MACRO_DEFINITION_LOCATION, NULL);
+
+        diagnostic_append_note (context, resolved_exp_loc, 
+                                "in expansion of macro %qs",
+                                linemap_map_get_macro_name (iter->map));
+      }
+}
+
+/*  This is a diagnostic finalizer implementation that is aware of
+    virtual locations produced by libcpp.
+
+    It has to be called by the diagnostic finalizer of front ends that
+    uses libcpp and wish to get diagnostics involving tokens resulting
+    from macro expansion.
+
+    For a given location, if said location belongs to a token
+    resulting from a macro expansion, this starter prints the context
+    of the token.  E.g, for multiply nested macro expansion, it
+    unwinds the nested macro expansions and prints them in a manner
+    that is similar to what is done for function call stacks, or
+    template instantiation contexts.  */
+void
+virt_loc_aware_diagnostic_finalizer (diagnostic_context *context,
+				     const diagnostic_info *diagnostic)
+{
+  maybe_unwind_expanded_macro_loc (context, diagnostic_location (diagnostic));
+}
diff --git a/gcc/diagnostic-macro-unwinding.h b/gcc/diagnostic-macro-unwinding.h
new file mode 100644
index 00000000000..74083cd56de
--- /dev/null
+++ b/gcc/diagnostic-macro-unwinding.h
@@ -0,0 +1,29 @@
+/* Code for unwinding macro expansions in diagnostics.
+   Copyright (C) 2000-2024 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_DIAGNOSTIC_MACRO_UNWINDING_H
+#define GCC_DIAGNOSTIC_MACRO_UNWINDING_H
+
+void virt_loc_aware_diagnostic_finalizer (diagnostic_context *,
+					  const diagnostic_info *);
+
+extern void maybe_unwind_expanded_macro_loc (diagnostic_context *context,
+					     location_t where);
+
+#endif /* ! GCC_DIAGNOSTIC_MACRO_UNWINDING_H */
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 40b197d971c..adaaf30b84f 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tree.h"
 #include "diagnostic.h"
-#include "tree-diagnostic.h"
+#include "diagnostic-macro-unwinding.h"
 #include "intl.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
diff --git a/gcc/tree-diagnostic.cc b/gcc/tree-diagnostic.cc
index f6e2a73497a..f236f3db0b2 100644
--- a/gcc/tree-diagnostic.cc
+++ b/gcc/tree-diagnostic.cc
@@ -51,201 +51,6 @@ default_tree_diagnostic_starter (diagnostic_context *context,
 							    diagnostic));
 }
 
-/* This is a pair made of a location and the line map it originated
-   from.  It's used in the maybe_unwind_expanded_macro_loc function
-   below.  */
-struct loc_map_pair
-{
-  const line_map_macro *map;
-  location_t where;
-};
-
-
-/* Unwind the different macro expansions that lead to the token which
-   location is WHERE and emit diagnostics showing the resulting
-   unwound macro expansion trace.  Let's look at an example to see how
-   the trace looks like.  Suppose we have this piece of code,
-   artificially annotated with the line numbers to increase
-   legibility:
-
-    $ cat -n test.c
-      1    #define OPERATE(OPRD1, OPRT, OPRD2) \
-      2      OPRD1 OPRT OPRD2;
-      3
-      4    #define SHIFTL(A,B) \
-      5      OPERATE (A,<<,B)
-      6
-      7    #define MULT(A) \
-      8      SHIFTL (A,1)
-      9
-     10    void
-     11    g ()
-     12    {
-     13      MULT (1.0);// 1.0 << 1; <-- so this is an error.
-     14    }
-
-   Here is the diagnostic that we want the compiler to generate:
-
-    test.c: In function ‘g’:
-    test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’)
-    test.c:2:9: note: in definition of macro 'OPERATE'
-    test.c:8:3: note: in expansion of macro 'SHIFTL'
-    test.c:13:3: note: in expansion of macro 'MULT'
-
-   The part that goes from the third to the fifth line of this
-   diagnostic (the lines containing the 'note:' string) is called the
-   unwound macro expansion trace.  That's the part generated by this
-   function.  */
-
-void
-maybe_unwind_expanded_macro_loc (diagnostic_context *context,
-                                 location_t where)
-{
-  const struct line_map *map;
-  auto_vec<loc_map_pair> loc_vec;
-  unsigned ix;
-  loc_map_pair loc, *iter;
-
-  const location_t original_loc = where;
-
-  map = linemap_lookup (line_table, where);
-  if (!linemap_macro_expansion_map_p (map))
-    return;
-
-  /* Let's unwind the macros that got expanded and led to the token
-     which location is WHERE.  We are going to store these macros into
-     LOC_VEC, so that we can later walk it at our convenience to
-     display a somewhat meaningful trace of the macro expansion
-     history to the user.  Note that the first macro of the trace
-     (which is OPERATE in the example above) is going to be stored at
-     the beginning of LOC_VEC.  */
-
-  do
-    {
-      loc.where = where;
-      loc.map = linemap_check_macro (map);
-
-      loc_vec.safe_push (loc);
-
-      /* WHERE is the location of a token inside the expansion of a
-         macro.  MAP is the map holding the locations of that macro
-         expansion.  Let's get the location of the token inside the
-         context that triggered the expansion of this macro.
-         This is basically how we go "down" in the trace of macro
-         expansions that led to WHERE.  */
-      where = linemap_unwind_toward_expansion (line_table, where, &map);
-    } while (linemap_macro_expansion_map_p (map));
-
-  /* Now map is set to the map of the location in the source that
-     first triggered the macro expansion.  This must be an ordinary map.  */
-  const line_map_ordinary *ord_map = linemap_check_ordinary (map);
-
-  /* Walk LOC_VEC and print the macro expansion trace, unless the
-     first macro which expansion triggered this trace was expanded
-     inside a system header.  */
-  int saved_location_line =
-    expand_location_to_spelling_point (original_loc).line;
-
-  if (!LINEMAP_SYSP (ord_map))
-    FOR_EACH_VEC_ELT (loc_vec, ix, iter)
-      {
-	/* Sometimes, in the unwound macro expansion trace, we want to
-	   print a part of the context that shows where, in the
-	   definition of the relevant macro, is the token (we are
-	   looking at) used.  That is the case in the introductory
-	   comment of this function, where we print:
-
-	       test.c:2:9: note: in definition of macro 'OPERATE'.
-
-	   We print that "macro definition context" because the
-	   diagnostic line (emitted by the call to
-	   pp_ouput_formatted_text in diagnostic_report_diagnostic):
-
-	       test.c:5:14: error: invalid operands to binary << (have ‘double’ and ‘int’)
-
-	   does not point into the definition of the macro where the
-	   token '<<' (that is an argument to the function-like macro
-	   OPERATE) is used.  So we must "display" the line of that
-	   macro definition context to the user somehow.
-
-	   A contrario, when the first interesting diagnostic line
-	   points into the definition of the macro, we don't need to
-	   display any line for that macro definition in the trace
-	   anymore, otherwise it'd be redundant.  */
-
-        /* Okay, now here is what we want.  For each token resulting
-           from macro expansion we want to show: 1/ where in the
-           definition of the macro the token comes from; 2/ where the
-           macro got expanded.  */
-
-        /* Resolve the location iter->where into the locus 1/ of the
-           comment above.  */
-        location_t resolved_def_loc =
-          linemap_resolve_location (line_table, iter->where,
-                                    LRK_MACRO_DEFINITION_LOCATION, NULL);
-
-	/* Don't print trace for locations that are reserved or from
-	   within a system header.  */
-        const line_map_ordinary *m = NULL;
-        location_t l = 
-          linemap_resolve_location (line_table, resolved_def_loc,
-                                    LRK_SPELLING_LOCATION,  &m);
-	location_t l0 = l;
-	if (IS_ADHOC_LOC (l0))
-	  l0 = get_location_from_adhoc_loc (line_table, l0);
-	if (l0 < RESERVED_LOCATION_COUNT || LINEMAP_SYSP (m))
-          continue;
-        
-	/* We need to print the context of the macro definition only
-	   when the locus of the first displayed diagnostic (displayed
-	   before this trace) was inside the definition of the
-	   macro.  */
-	const int resolved_def_loc_line = SOURCE_LINE (m, l0);
-        if (ix == 0 && saved_location_line != resolved_def_loc_line)
-          {
-            diagnostic_append_note (context, resolved_def_loc, 
-                                    "in definition of macro %qs",
-                                    linemap_map_get_macro_name (iter->map));
-            /* At this step, as we've printed the context of the macro
-               definition, we don't want to print the context of its
-               expansion, otherwise, it'd be redundant.  */
-            continue;
-          }
-
-        /* Resolve the location of the expansion point of the macro
-           which expansion gave the token represented by def_loc.
-           This is the locus 2/ of the earlier comment.  */
-        location_t resolved_exp_loc =
-          linemap_resolve_location (line_table,
-                                    iter->map->get_expansion_point_location (),
-                                    LRK_MACRO_DEFINITION_LOCATION, NULL);
-
-        diagnostic_append_note (context, resolved_exp_loc, 
-                                "in expansion of macro %qs",
-                                linemap_map_get_macro_name (iter->map));
-      }
-}
-
-/*  This is a diagnostic finalizer implementation that is aware of
-    virtual locations produced by libcpp.
-
-    It has to be called by the diagnostic finalizer of front ends that
-    uses libcpp and wish to get diagnostics involving tokens resulting
-    from macro expansion.
-
-    For a given location, if said location belongs to a token
-    resulting from a macro expansion, this starter prints the context
-    of the token.  E.g, for multiply nested macro expansion, it
-    unwinds the nested macro expansions and prints them in a manner
-    that is similar to what is done for function call stacks, or
-    template instantiation contexts.  */
-void
-virt_loc_aware_diagnostic_finalizer (diagnostic_context *context,
-				     const diagnostic_info *diagnostic)
-{
-  maybe_unwind_expanded_macro_loc (context, diagnostic_location (diagnostic));
-}
-
 /* Default tree printer.   Handles declarations only.  */
 bool
 default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
diff --git a/gcc/tree-diagnostic.h b/gcc/tree-diagnostic.h
index 7959294f489..648d6e6ab91 100644
--- a/gcc/tree-diagnostic.h
+++ b/gcc/tree-diagnostic.h
@@ -50,8 +50,6 @@ along with GCC; see the file COPYING3.  If not see
 
 void diagnostic_report_current_function (diagnostic_context *,
 					 const diagnostic_info *);
-void virt_loc_aware_diagnostic_finalizer (diagnostic_context *,
-					  const diagnostic_info *);
 
 void tree_diagnostics_defaults (diagnostic_context *context);
 bool default_tree_printer (pretty_printer *, text_info *, const char *,
@@ -60,7 +58,4 @@ bool default_tree_printer (pretty_printer *, text_info *, const char *,
 extern void default_tree_diagnostic_path_printer (diagnostic_context *,
 						  const diagnostic_path *);
 
-extern void maybe_unwind_expanded_macro_loc (diagnostic_context *context,
-					     location_t where);
-
 #endif /* ! GCC_TREE_DIAGNOSTIC_H */
-- 
2.26.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 6/7] diagnostics: eliminate diagnostic_context::m_print_path callback
  2024-06-18 15:08 [pushed 0/7] diagnostics: remove "tree" dependency from diagnostic paths David Malcolm
                   ` (4 preceding siblings ...)
  2024-06-18 15:08 ` [PATCH 5/7] diagnostics: introduce diagnostic-macro-unwinding.h/cc David Malcolm
@ 2024-06-18 15:08 ` David Malcolm
  2024-06-18 18:22   ` David Malcolm
  2024-06-18 15:08 ` [PATCH 7/7] diagnostics: rename tree-diagnostic-path.cc to diagnostic-path.cc David Malcolm
  6 siblings, 1 reply; 9+ messages in thread
From: David Malcolm @ 2024-06-18 15:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

No functional change intended.

gcc/ChangeLog:
	* diagnostic-format-json.cc (diagnostic_output_format_init_json):
	Replace clearing of diagnostic_context::m_print_path callback with
	setting the path format to DPF_NONE.
	* diagnostic-format-sarif.cc
	(diagnostic_output_format_init_sarif): Likewise.
	* diagnostic.cc (diagnostic_context::show_any_path): Replace call
	to diagnostic_context::m_print_path callback with a direct call to
	diagnostic_context::print_path.
	* diagnostic.h (diagnostic_context::print_path): New decl.
	(diagnostic_context::m_print_path): Delete callback.
	* tree-diagnostic-path.cc (default_tree_diagnostic_path_printer):
	Convert to...
	(diagnostic_context::print_path): ...this.
	* tree-diagnostic.cc (tree_diagnostics_defaults): Delete
	initialization of m_print_path.
	* tree-diagnostic.h (default_tree_diagnostic_path_printer): Delete
	decl.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/diagnostic-format-json.cc  |  4 ++--
 gcc/diagnostic-format-sarif.cc |  4 +++-
 gcc/diagnostic.cc              |  3 +--
 gcc/diagnostic.h               |  4 ++--
 gcc/tree-diagnostic-path.cc    | 23 +++++++++++------------
 gcc/tree-diagnostic.cc         |  1 -
 gcc/tree-diagnostic.h          |  3 ---
 7 files changed, 19 insertions(+), 23 deletions(-)

diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 2bdc2c13d37..ec03ac15aeb 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -395,8 +395,8 @@ private:
 static void
 diagnostic_output_format_init_json (diagnostic_context *context)
 {
-  /* Override callbacks.  */
-  context->m_print_path = nullptr; /* handled in json_end_diagnostic.  */
+  /* Suppress normal textual path output.  */
+  context->set_path_format (DPF_NONE);
 
   /* The metadata is handled in JSON format, rather than as text.  */
   context->set_show_cwe (false);
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 79116f051bc..5f438dd38a8 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -1991,8 +1991,10 @@ private:
 static void
 diagnostic_output_format_init_sarif (diagnostic_context *context)
 {
+  /* Suppress normal textual path output.  */
+  context->set_path_format (DPF_NONE);
+
   /* Override callbacks.  */
-  context->m_print_path = nullptr; /* handled in sarif_end_diagnostic.  */
   context->set_ice_handler_callback (sarif_ice_handler);
 
   /* The metadata is handled in SARIF format, rather than as text.  */
diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc
index 844eb8e1048..471135f16de 100644
--- a/gcc/diagnostic.cc
+++ b/gcc/diagnostic.cc
@@ -915,8 +915,7 @@ diagnostic_context::show_any_path (const diagnostic_info &diagnostic)
   if (!path)
     return;
 
-  if (m_print_path)
-    m_print_path (this, path);
+  print_path (path);
 }
 
 /* class diagnostic_event.  */
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index ff2aa3dd9a3..c6846525da3 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -583,6 +583,8 @@ private:
 		   pretty_printer *pp,
 		   diagnostic_source_effect_info *effect_info);
 
+  void print_path (const diagnostic_path *path);
+
   /* Data members.
      Ideally, all of these would be private and have "m_" prefixes.  */
 
@@ -712,8 +714,6 @@ private:
   urlifier *m_urlifier;
 
 public:
-  void (*m_print_path) (diagnostic_context *, const diagnostic_path *);
-
   /* Auxiliary data for client.  */
   void *m_client_aux_data;
 
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index adaaf30b84f..35f8ea2b8b6 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -884,17 +884,16 @@ print_path_summary_as_text (const path_summary *ps, diagnostic_context *dc,
 
 } /* end of anonymous namespace for path-printing code.  */
 
-/* Print PATH to CONTEXT, according to CONTEXT's path_format.  */
+/* Print PATH according to this context's path_format.  */
 
 void
-default_tree_diagnostic_path_printer (diagnostic_context *context,
-				      const diagnostic_path *path)
+diagnostic_context::print_path (const diagnostic_path *path)
 {
   gcc_assert (path);
 
   const unsigned num_events = path->num_events ();
 
-  switch (context->get_path_format ())
+  switch (get_path_format ())
     {
     case DPF_NONE:
       /* Do nothing.  */
@@ -909,7 +908,7 @@ default_tree_diagnostic_path_printer (diagnostic_context *context,
 	    label_text event_text (event.get_desc (false));
 	    gcc_assert (event_text.get ());
 	    diagnostic_event_id_t event_id (i);
-	    if (context->show_path_depths_p ())
+	    if (this->show_path_depths_p ())
 	      {
 		int stack_depth = event.get_stack_depth ();
 		/* -fdiagnostics-path-format=separate-events doesn't print
@@ -941,13 +940,13 @@ default_tree_diagnostic_path_printer (diagnostic_context *context,
       {
 	/* Consolidate related events.  */
 	path_summary summary (*path, true,
-			      context->m_source_printing.show_event_links_p);
-	char *saved_prefix = pp_take_prefix (context->printer);
-	pp_set_prefix (context->printer, NULL);
-	print_path_summary_as_text (&summary, context,
-				    context->show_path_depths_p ());
-	pp_flush (context->printer);
-	pp_set_prefix (context->printer, saved_prefix);
+			      m_source_printing.show_event_links_p);
+	char *saved_prefix = pp_take_prefix (this->printer);
+	pp_set_prefix (this->printer, NULL);
+	print_path_summary_as_text (&summary, this,
+				    show_path_depths_p ());
+	pp_flush (this->printer);
+	pp_set_prefix (this->printer, saved_prefix);
       }
       break;
     }
diff --git a/gcc/tree-diagnostic.cc b/gcc/tree-diagnostic.cc
index f236f3db0b2..fc78231dfa4 100644
--- a/gcc/tree-diagnostic.cc
+++ b/gcc/tree-diagnostic.cc
@@ -179,7 +179,6 @@ tree_diagnostics_defaults (diagnostic_context *context)
   diagnostic_starter (context) = default_tree_diagnostic_starter;
   diagnostic_finalizer (context) = default_diagnostic_finalizer;
   diagnostic_format_decoder (context) = default_tree_printer;
-  context->m_print_path = default_tree_diagnostic_path_printer;
   context->set_set_locations_callback (set_inlining_locations);
   context->set_client_data_hooks (make_compiler_data_hooks ());
 }
diff --git a/gcc/tree-diagnostic.h b/gcc/tree-diagnostic.h
index 648d6e6ab91..6ebac381ace 100644
--- a/gcc/tree-diagnostic.h
+++ b/gcc/tree-diagnostic.h
@@ -55,7 +55,4 @@ void tree_diagnostics_defaults (diagnostic_context *context);
 bool default_tree_printer (pretty_printer *, text_info *, const char *,
 			   int, bool, bool, bool, bool *, const char **);
 
-extern void default_tree_diagnostic_path_printer (diagnostic_context *,
-						  const diagnostic_path *);
-
 #endif /* ! GCC_TREE_DIAGNOSTIC_H */
-- 
2.26.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 7/7] diagnostics: rename tree-diagnostic-path.cc to diagnostic-path.cc
  2024-06-18 15:08 [pushed 0/7] diagnostics: remove "tree" dependency from diagnostic paths David Malcolm
                   ` (5 preceding siblings ...)
  2024-06-18 15:08 ` [PATCH 6/7] diagnostics: eliminate diagnostic_context::m_print_path callback David Malcolm
@ 2024-06-18 15:08 ` David Malcolm
  6 siblings, 0 replies; 9+ messages in thread
From: David Malcolm @ 2024-06-18 15:08 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Now that nothing in tree-diagnostic-path.cc uses "tree", this patch
renames it to diagnostic-path.cc and moves it from OBJS to
OBJS-libcommon.

No functional change intended.

gcc/ChangeLog:
	* Makefile.in (OBJS): Move selftest-diagnostic-path.o,
	selftest-logical-location.o, and tree-diagnostic-path.o to...
	(OBJS-libcommon): ...here, renaming tree-diagnostic-path.o to
	diagnostic-path.o.
	* tree-diagnostic-path.cc: Rename to...
	* diagnostic-path.cc: ...this.  Drop include of "tree.h".
	(tree_diagnostic_path_cc_tests): Rename to...
	(diagnostic_path_cc_tests): ...this.
	* selftest-run-tests.cc (selftest::run_tests): Update for above
	renaming.
	* selftest.h (tree_diagnostic_path_cc_tests): Rename decl to...
	(diagnostic_path_cc_tests): ...this.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/Makefile.in                                     | 6 +++---
 gcc/{tree-diagnostic-path.cc => diagnostic-path.cc} | 3 +--
 gcc/selftest-run-tests.cc                           | 2 +-
 gcc/selftest.h                                      | 2 +-
 4 files changed, 6 insertions(+), 7 deletions(-)
 rename gcc/{tree-diagnostic-path.cc => diagnostic-path.cc} (99%)

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index e701d9fb082..638ea6b2307 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1700,8 +1700,6 @@ OBJS = \
 	ubsan.o \
 	sanopt.o \
 	sancov.o \
-	selftest-diagnostic-path.o \
-	selftest-logical-location.o \
 	simple-diagnostic-path.o \
 	tree-call-cdce.o \
 	tree-cfg.o \
@@ -1712,7 +1710,6 @@ OBJS = \
 	tree-dfa.o \
 	tree-diagnostic.o \
 	tree-diagnostic-client-data-hooks.o \
-	tree-diagnostic-path.o \
 	tree-dump.o \
 	tree-eh.o \
 	tree-emutls.o \
@@ -1827,6 +1824,7 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
 	diagnostic-format-json.o \
 	diagnostic-format-sarif.o \
 	diagnostic-macro-unwinding.o \
+	diagnostic-path.o \
 	diagnostic-show-locus.o \
 	edit-context.o \
 	pretty-print.o intl.o \
@@ -1834,6 +1832,8 @@ OBJS-libcommon = diagnostic-spec.o diagnostic.o diagnostic-color.o \
 	sbitmap.o \
 	vec.o input.o hash-table.o ggc-none.o memory-block.o \
 	selftest.o selftest-diagnostic.o sort.o \
+	selftest-diagnostic-path.o \
+	selftest-logical-location.o \
 	text-art/box-drawing.o \
 	text-art/canvas.o \
 	text-art/ruler.o \
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/diagnostic-path.cc
similarity index 99%
rename from gcc/tree-diagnostic-path.cc
rename to gcc/diagnostic-path.cc
index 35f8ea2b8b6..882dc1c5805 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/diagnostic-path.cc
@@ -25,7 +25,6 @@ along with GCC; see the file COPYING3.  If not see
 #define INCLUDE_VECTOR
 #include "system.h"
 #include "coretypes.h"
-#include "tree.h"
 #include "diagnostic.h"
 #include "diagnostic-macro-unwinding.h"
 #include "intl.h"
@@ -2199,7 +2198,7 @@ control_flow_tests (const line_table_case &case_)
 /* Run all of the selftests within this file.  */
 
 void
-tree_diagnostic_path_cc_tests ()
+diagnostic_path_cc_tests ()
 {
   /* In a few places we use the global dc's printer to determine
      colorization so ensure this off during the tests.  */
diff --git a/gcc/selftest-run-tests.cc b/gcc/selftest-run-tests.cc
index 3275db38ba9..e6779206c47 100644
--- a/gcc/selftest-run-tests.cc
+++ b/gcc/selftest-run-tests.cc
@@ -102,7 +102,7 @@ selftest::run_tests ()
   spellcheck_cc_tests ();
   spellcheck_tree_cc_tests ();
   tree_cfg_cc_tests ();
-  tree_diagnostic_path_cc_tests ();
+  diagnostic_path_cc_tests ();
   simple_diagnostic_path_cc_tests ();
   attribs_cc_tests ();
 
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 2d1aa91607e..dcb1463ed90 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -222,6 +222,7 @@ extern void cgraph_cc_tests ();
 extern void convert_cc_tests ();
 extern void diagnostic_color_cc_tests ();
 extern void diagnostic_format_json_cc_tests ();
+extern void diagnostic_path_cc_tests ();
 extern void diagnostic_show_locus_cc_tests ();
 extern void digraph_cc_tests ();
 extern void dumpfile_cc_tests ();
@@ -259,7 +260,6 @@ extern void sreal_cc_tests ();
 extern void store_merging_cc_tests ();
 extern void tree_cc_tests ();
 extern void tree_cfg_cc_tests ();
-extern void tree_diagnostic_path_cc_tests ();
 extern void tristate_cc_tests ();
 extern void typed_splay_tree_cc_tests ();
 extern void vec_cc_tests ();
-- 
2.26.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 6/7] diagnostics: eliminate diagnostic_context::m_print_path callback
  2024-06-18 15:08 ` [PATCH 6/7] diagnostics: eliminate diagnostic_context::m_print_path callback David Malcolm
@ 2024-06-18 18:22   ` David Malcolm
  0 siblings, 0 replies; 9+ messages in thread
From: David Malcolm @ 2024-06-18 18:22 UTC (permalink / raw)
  To: gcc-patches

On Tue, 2024-06-18 at 11:08 -0400, David Malcolm wrote:
> No functional change intended.

Sorry, it looks like I should have combined patches 6 and 7, in that
patch 6 temporarily breaks the build:

e.g.:
  https://builder.sourceware.org/buildbot/#/builders/156/builds/10063

make[2]: Leaving directory '/home/mjw/wildebeest/buildbot/gcc-fedora-ppc64le/gcc-build/gcc'
g++ -no-pie   -g -O2     -DIN_GCC    -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Wconditionally-supported -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings   -DHAVE_CONFIG_H -no-pie  gcov-dump.o \
	hash-table.o ggc-none.o\
	libcommon.a ../libcpp/libcpp.a   ../libbacktrace/.libs/libbacktrace.a ../libiberty/libiberty.a ../libdecnumber/libdecnumber.a  -o gcov-dump
/usr/bin/ld: libcommon.a(diagnostic.o): in function `diagnostic_context::show_any_path(diagnostic_info const&)':
/home/mjw/wildebeest/buildbot/gcc-fedora-ppc64le/gcc-build/gcc/../../gcc/gcc/diagnostic.cc:918:(.text+0x2084): undefined reference to `diagnostic_context::print_path(diagnostic_path const*)'
/usr/bin/ld: /home/mjw/wildebeest/buildbot/gcc-fedora-ppc64le/gcc-build/gcc/../../gcc/gcc/diagnostic.cc:918:(.text+0x4a34): undefined reference to `diagnostic_context::print_path(diagnostic_path const*)'
collect2: error: ld returned 1 exit status

Should be fixed by patch 7 in the kit, which puts that symbol in
libcommon.a; am continuing to watch the post-commit CI.

Sorry again
Dave


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2024-06-18 18:22 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-18 15:08 [pushed 0/7] diagnostics: remove "tree" dependency from diagnostic paths David Malcolm
2024-06-18 15:08 ` [PATCH 1/7] diagnostics: move simple_diagnostic_{path,thread,event} to their own .h/cc David Malcolm
2024-06-18 15:08 ` [PATCH 2/7] diagnostics: eliminate "tree" from diagnostic_{event,path} David Malcolm
2024-06-18 15:08 ` [PATCH 3/7] diagnostics: remove tree usage from tree-diagnostic-path.cc David Malcolm
2024-06-18 15:08 ` [PATCH 4/7] diagnostics: eliminate diagnostic_context::m_make_json_for_path David Malcolm
2024-06-18 15:08 ` [PATCH 5/7] diagnostics: introduce diagnostic-macro-unwinding.h/cc David Malcolm
2024-06-18 15:08 ` [PATCH 6/7] diagnostics: eliminate diagnostic_context::m_print_path callback David Malcolm
2024-06-18 18:22   ` David Malcolm
2024-06-18 15:08 ` [PATCH 7/7] diagnostics: rename tree-diagnostic-path.cc to diagnostic-path.cc David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).