]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
diagnostics: add logical_location_manager; reimplement logical_location
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 6 May 2025 13:26:17 +0000 (09:26 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Tue, 6 May 2025 13:26:17 +0000 (09:26 -0400)
Previously we used an abstract base class logical_location with
concrete subclasses to separate the diagnostics subsystem from
implementation details of "tree" and of libgdiagnostics.

This approach required allocating implementation objects on the heap
whenever working with logical locations, and made comparing logical
locations awkward.

This patch reworks things so that the type "logical_location" becomes a
boxed pointer (const void *), and client code provides a single object
implementing a new logical_location_manager abstract base class.  The
manager class has responsibility for providing meaning to the boxed
pointers.  Within the compiler we use a manager in which they are "tree"
pointers, whereas within libgdiagnostics we use a manager in which they
are pointers to instances of libgdiagnostics'
"struct diagnostic_logical_location".  Other kinds of manager could be
implemented.

gcc/analyzer/ChangeLog:
* checker-event.cc (checker_event::checker_event): Update
initialization of m_logical_loc.
(checker_event::maybe_add_sarif_properties): Add "builder" param.
Replace call to make_sarif_logical_location_object with call to
sarif_property_bag::set_logical_location.
(superedge_event::maybe_add_sarif_properties): Add "builder"
param.
* checker-event.h (checker_event::get_logical_location):
Reimplement.
(checker_event::maybe_add_sarif_properties): Add "builder" param.
(checker_event::maybe_add_sarif_properties): Add "builder" param.
(checker_event::m_logical_loc): Convert from tree_logical_location
to logical_location.
(superedge_event::maybe_add_sarif_properties): Add sarif_builder
param.
* checker-path.h (checker_path::checker_path): Add logical_loc_mgr
param.
* diagnostic-manager.cc
(diagnostic_manager::emit_saved_diagnostic): Pass logical location
manager to emission_path ctor.
(diagnostic_manager::get_logical_location_manager): New.
* diagnostic-manager.h
(diagnostic_manager::get_logical_location_manager): New decl.

gcc/ChangeLog:
* diagnostic-client-data-hooks.h: Include "logical-location.h".
(diagnostic_client_data_hooks::get_logical_location_manager): New.
(diagnostic_client_data_hooks::get_current_logical_location):
Convert return type from const logical_location * to
logical_location.
* diagnostic-format-json.cc: Include
"diagnostic-client-data-hooks.h".
(make_json_for_path): Update to use logical_location_manager from
the context.
* diagnostic-format-sarif.cc
(sarif_builder::get_logical_location_manager): New.
(sarif_builder::make_location_object): Update type of logical_loc
from "const logical_location *" to "logical_location".
(sarif_builder::set_any_logical_locs_arr): Likewise.
(sarif_builder::m_logical_loc_mgr): New field.
(sarif_result::on_nested_diagnostic): Use logical_location default
ctor rather than nullptr.
(sarif_builder::sarif_builder): Initialize m_logical_loc_mgr from
context's client data hooks.
(sarif_builder::make_locations_arr): Convert type of logical_loc
from from "const logical_location *" to "logical_location".
(sarif_builder::set_any_logical_locs_arr): Likewise.  Pass manager
to make_sarif_logical_location_object.
(sarif_builder::make_location_object): Likewise.
(sarif_property_bag::set_logical_location): New.
(make_sarif_logical_location_object): Update for introduction of
logical_location_manager.
(populate_thread_flow_location_object): Pass builder to
ev.maybe_add_sarif_properties.
(selftest::test_make_location_object): Use logical_location
default ctor rather than nullptr.
* diagnostic-format-sarif.h (class logical_location): Replace
forward decl with include of "logical-location.h".
(class sarif_builder): New forward decl.
(sarif_property_bag::set_logical_location): New.
(make_sarif_logical_location_object): Add "mgr" param.
* diagnostic-path.cc
(diagnostic_path::get_first_event_in_a_function): Update for
change of logical_location type.
(per_thread_summary::per_thread_summary): Pass in
"logical_loc_mgr".
(per_thread_summary::m_logical_loc_mgr): New field.
(event_range::m_logical_loc): Update for change of
logical_location type.
(path_summary::get_logical_location_manager): New accessor.
(path_summary::m_logical_loc_mgr): New field.
(path_summary::get_or_create_events_for_thread_id): Pass
m_logical_loc_mgr to per_thread_summary ctor.
(path_summary::path_summary): Initialize m_logical_loc_mgr.
(thread_event_printer::print_swimlane_for_event_range): Add param
"logical_loc_mgr".  Update for change in logical_loc type.
(print_path_summary_as_text): Pass manager to
thread_event_printer::print_swimlane_for_event_range.
(diagnostic_text_output_format::print_path): Update for
introduction of logical_location_manager.
* diagnostic-path.h: Include "logical-location.h".
(class sarif_builder): New forward decl.
(diagnostic_event::get_logical_location): Convert return type from
"const logical_location *" to "logical_location".
(diagnostic_event::maybe_add_sarif_properties): Add sarif_builder
param.
(diagnostic_path::get_logical_location_manager): New accessor.
(diagnostic_path::diagnostic_path): New ctor, taking manager.
(diagnostic_path::m_logical_loc_mgr): New field.
* diagnostic.cc
(diagnostic_context::get_logical_location_manager): New.
(logical_location::function_p): Convert to...
(logical_location_manager::function_p): ...this.
* diagnostic.h (class logical_location): Replace forward decl
with...
(class logical_location_manager): ...this.
(diagnostic_context::get_logical_location_manager): New decl.
* lazy-diagnostic-path.cc
(selftest::test_lazy_path::test_lazy_path): Pass m_logical_loc_mgr
to path ctor.
(selftest::test_lazy_path::make_inner_path): Likewise.
(selftest::test_lazy_path::m_logical_loc_mgr): New field.
* lazy-diagnostic-path.h
(lazy_diagnostic_path::lazy_diagnostic_path): New ctor.
* libgdiagnostics.cc (struct diagnostic_logical_location): Convert
from subclass of logical_location to a plain struct, dropping
accessors.
(class impl_logical_location_manager): New.
(impl_diagnostic_client_data_hooks::get_logical_location_manager):
New
(impl_diagnostic_client_data_hooks::m_logical_location_manager):
New field.
(diagnostic_manager::get_logical_location_manager): New.
(libgdiagnostics_path_event::get_logical_location): Reimplement.
(diagnostic_execution_path::diagnostic_execution_path): Add
logical_loc_mgr and pass to base class.
(diagnostic_execution_path::same_function_p): Update for change to
logical_location type.
(diagnostic::add_execution_path): Pass logical_loc_mgr to path
ctor.
(impl_diagnostic_client_data_hooks::get_current_logical_location):
Reimplement.
(diagnostic_text_sink::text_starter): Reimplement printing of
logical location.
(diagnostic_manager::new_execution_path): Pass mgr to path ctor.
(diagnostic_manager_debug_dump_logical_location): Update for
changes to diagnostic_logical_location.
(diagnostic_logical_location_get_kind): Likewise.
(diagnostic_logical_location_get_parent): Likewise.
(diagnostic_logical_location_get_short_name): Likewise.
(diagnostic_logical_location_get_fully_qualified_name): Likewise.
(diagnostic_logical_location_get_decorated_name): Likewise.
* logical-location.h (class logical_location_manager): New.
(class logical_location): Convert to typedef of
logical_location_manager::key.
* selftest-diagnostic-path.cc
(selftest::test_diagnostic_path::test_diagnostic_path): Pass
m_test_logical_loc_mgr to base ctor.
(selftest::test_diagnostic_path::same_function_p): Use pointer
comparison.
(selftest::test_diagnostic_path::add_event): Use
logical_location_from_funcname.
(selftest::test_diagnostic_path::add_thread_event): Likewise.
(selftest::test_diagnostic_path::logical_location_from_funcname):
New.
(selftest::test_diagnostic_event::test_diagnostic_event): Fix
indentation.  Pass logical_location rather than const char *.
* selftest-diagnostic-path.h
(selftest::test_diagnostic_event::test_diagnostic_event):
Likewise.
(selftest::test_diagnostic_event::get_logical_location): Update
for change to logical_location type.
(selftest::test_diagnostic_event::get_function_name): Drop.
(selftest::test_diagnostic_event::m_logical_loc): Convert from
test_logical_location to logical_location.
(selftest::test_diagnostic_path::logical_location_from_funcname):
New.
(selftest::test_diagnostic_path::m_test_logical_loc_mgr): New
field.
* selftest-logical-location.cc: Include "selftest.h".
(selftest::test_logical_location::test_logical_location): Drop.
(selftest::test_logical_location_manager::~test_logical_location_manager):
New.
(selftest::test_logical_location::get_short_name): Replace with...
(selftest::test_logical_location_manager::get_short_name):
...this.
(selftest::test_logical_location::get_name_with_scope): Replace
with...
(selftest::test_logical_location_manager::get_name_with_scope):
...this.
(selftest::test_logical_location::get_internal_name): Replace
with...
(selftest::test_logical_location_manager::get_internal_name):
...this.
(selftest::test_logical_location::get_kind): Replace with...
(selftest::test_logical_location_manager::get_kind): ...this.
(selftest::test_logical_location::get_name_for_path_output):
Replace with...
(selftest::test_logical_location_manager::get_name_for_path_output):
...this.
(selftest::test_logical_location_manager::logical_location_from_funcname):
New.
(selftest::test_logical_location_manager::item_from_funcname):
New.
(selftest::selftest_logical_location_cc_tests): New.
* selftest-logical-location.h (class test_logical_location):
Replace with...
(class test_logical_location_manager): ...this.
* selftest-run-tests.cc (selftest::run_tests): Call
selftest_logical_location_cc_tests.
* selftest.h (selftest::selftest_logical_location_cc_tests): New
decl.
* simple-diagnostic-path.cc
(simple_diagnostic_path::simple_diagnostic_path): Add
"logical_loc_mgr" param and pass it to base ctor.
(simple_diagnostic_event::simple_diagnostic_event): Update init of
m_logical_loc.
(selftest::test_intraprocedural_path): Update for changes to
logical locations.
* simple-diagnostic-path.h: Likewise.
* tree-diagnostic-client-data-hooks.cc
(compiler_data_hooks::get_logical_location_manger): New.
(compiler_data_hooks::get_current_logical_location): Update.
(compiler_data_hooks::m_current_fndecl_logical_loc): Replace
with...
(compiler_data_hooks::m_logical_location_manager): ...this.
* tree-logical-location.cc
(compiler_logical_location::get_short_name_for_tree): Replace
with...
(tree_logical_location_manager::get_short_name): ...this.
(compiler_logical_location::get_name_with_scope_for_tree): Replace
with...
(tree_logical_location_manager::get_name_with_scope): ...this.
(compiler_logical_location::get_internal_name_for_tree): Replace
with...
(tree_logical_location_manager::get_internal_name): ...this.
(compiler_logical_location::get_kind_for_tree): Replace with...
(tree_logical_location_manager::get_kind): ...this.
(compiler_logical_location::get_name_for_tree_for_path_output):
Replace with...
(tree_logical_location_manager::get_name_for_path_output):
...this.
(tree_logical_location::get_short_name): Drop.
(tree_logical_location::get_name_with_scope): Drop.
(tree_logical_location::get_internal_name): Drop.
(tree_logical_location::get_kind): Drop.
(tree_logical_location::get_name_for_path_output): Drop.
(current_fndecl_logical_location::get_short_name): Drop.
(current_fndecl_logical_location::get_name_with_scope): Drop.
(current_fndecl_logical_location::get_internal_name): Drop.
(current_fndecl_logical_location::get_kind): Drop.
(current_fndecl_logical_location::get_name_for_path_output): Drop.
* tree-logical-location.h (class compiler_logical_location): Drop.
(class tree_logical_location): Drop.
(class current_fndecl_logical_location): Drop.
(class tree_logical_location_manager): New.

gcc/testsuite/ChangeLog:
* gcc.dg/plugin/diagnostic_plugin_test_paths.cc: Update for
changes to simple_diagnostic_path.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
29 files changed:
gcc/analyzer/checker-event.cc
gcc/analyzer/checker-event.h
gcc/analyzer/checker-path.h
gcc/analyzer/diagnostic-manager.cc
gcc/analyzer/diagnostic-manager.h
gcc/diagnostic-client-data-hooks.h
gcc/diagnostic-format-json.cc
gcc/diagnostic-format-sarif.cc
gcc/diagnostic-format-sarif.h
gcc/diagnostic-path.cc
gcc/diagnostic-path.h
gcc/diagnostic.cc
gcc/diagnostic.h
gcc/lazy-diagnostic-path.cc
gcc/lazy-diagnostic-path.h
gcc/libgdiagnostics.cc
gcc/logical-location.h
gcc/selftest-diagnostic-path.cc
gcc/selftest-diagnostic-path.h
gcc/selftest-logical-location.cc
gcc/selftest-logical-location.h
gcc/selftest-run-tests.cc
gcc/selftest.h
gcc/simple-diagnostic-path.cc
gcc/simple-diagnostic-path.h
gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc
gcc/tree-diagnostic-client-data-hooks.cc
gcc/tree-logical-location.cc
gcc/tree-logical-location.h

index 958cdbf394d0e259a69594eb727fa0cfa7a2278d..e041778e8d1984aa558a700ae77bd25393661dbe 100644 (file)
@@ -112,7 +112,8 @@ checker_event::checker_event (enum event_kind kind,
   m_original_depth (loc_info.m_depth),
   m_effective_depth (loc_info.m_depth),
   m_pending_diagnostic (NULL), m_emission_id (),
-  m_logical_loc (loc_info.m_fndecl)
+  m_logical_loc
+    (tree_logical_location_manager::key_from_tree (loc_info.m_fndecl))
 {
   /* Update effective fndecl and depth if inlining has been recorded.  */
   if (flag_analyzer_undo_inlining)
@@ -122,7 +123,8 @@ checker_event::checker_event (enum event_kind kind,
        {
          m_effective_fndecl = info.get_inner_fndecl ();
          m_effective_depth += info.get_extra_frames ();
-         m_logical_loc = tree_logical_location (m_effective_fndecl);
+         m_logical_loc
+           = tree_logical_location_manager::key_from_tree (m_effective_fndecl);
        }
     }
 }
@@ -141,7 +143,8 @@ checker_event::get_meaning () const
 
 void
 checker_event::
-maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj) const
+maybe_add_sarif_properties (sarif_builder &builder,
+                           sarif_object &thread_flow_loc_obj) const
 {
   sarif_property_bag &props = thread_flow_loc_obj.get_or_create_properties ();
 #define PROPERTY_PREFIX "gcc/analyzer/checker_event/"
@@ -150,12 +153,11 @@ maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj) const
   props.set_string (PROPERTY_PREFIX "kind", event_kind_to_string (m_kind));
 
   if (m_original_fndecl != m_effective_fndecl)
-    {
-      tree_logical_location logical_loc (m_original_fndecl);
-      props.set<sarif_logical_location>
-       (PROPERTY_PREFIX "original_fndecl",
-        make_sarif_logical_location_object (logical_loc));
-    }
+    props.set_logical_location
+      (PROPERTY_PREFIX "original_fndecl",
+       builder,
+       tree_logical_location_manager::key_from_tree (m_original_fndecl));
+
   if (m_original_depth != m_effective_depth)
     props.set_integer (PROPERTY_PREFIX "original_depth", m_original_depth);
 #undef PROPERTY_PREFIX
@@ -502,10 +504,11 @@ state_change_event::get_meaning () const
    for superedge_event.  */
 
 void
-superedge_event::maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj)
+superedge_event::maybe_add_sarif_properties (sarif_builder &builder,
+                                            sarif_object &thread_flow_loc_obj)
   const
 {
-  checker_event::maybe_add_sarif_properties (thread_flow_loc_obj);
+  checker_event::maybe_add_sarif_properties (builder, thread_flow_loc_obj);
   sarif_property_bag &props = thread_flow_loc_obj.get_or_create_properties ();
 #define PROPERTY_PREFIX "gcc/analyzer/superedge_event/"
   if (m_sedge)
index f3ab899841831e09487596997ad91b49b535e410..2f26b8daaa6a518c27f999da0deaebbb74deda47 100644 (file)
@@ -100,12 +100,9 @@ public:
 
   location_t get_location () const final override { return m_loc; }
   int get_stack_depth () const final override { return m_effective_depth; }
-  const logical_location *get_logical_location () const final override
+  logical_location get_logical_location () const final override
   {
-    if (m_effective_fndecl)
-      return &m_logical_loc;
-    else
-      return NULL;
+    return m_logical_loc;
   }
   meaning get_meaning () const override;
   bool connect_to_next_event_p () const override { return false; }
@@ -115,7 +112,8 @@ public:
   }
 
   void
-  maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj) const override;
+  maybe_add_sarif_properties (sarif_builder &,
+                             sarif_object &thread_flow_loc_obj) const override;
 
   /* Additional functionality.  */
   tree get_fndecl () const { return m_effective_fndecl; }
@@ -154,7 +152,7 @@ protected:
   int m_effective_depth;
   pending_diagnostic *m_pending_diagnostic;
   diagnostic_event_id_t m_emission_id; // only set once all pruning has occurred
-  tree_logical_location m_logical_loc;
+  logical_location m_logical_loc;
 };
 
 /* A concrete event subclass for a purely textual event, for use in
@@ -391,7 +389,8 @@ public:
 class superedge_event : public checker_event
 {
 public:
-  void maybe_add_sarif_properties (sarif_object &thread_flow_loc_obj)
+  void maybe_add_sarif_properties (sarif_builder &,
+                                  sarif_object &thread_flow_loc_obj)
     const override;
 
   /* Mark this edge event as being either an interprocedural call or
index dfc782d45205ff75d79270a71b75f4cbb5571b7a..80c975c6a745a773c069eac1a7e3f38e24ead55d 100644 (file)
@@ -31,8 +31,9 @@ namespace ana {
 class checker_path : public diagnostic_path
 {
 public:
-  checker_path (logger *logger)
-  : diagnostic_path (),
+  checker_path (const logical_location_manager &logical_loc_mgr,
+               logger *logger)
+  : diagnostic_path (logical_loc_mgr),
     m_thread ("main"),
     m_logger (logger)
   {}
index 7575b16c86cd46015f7838f74bb298883dfb99ce..e5d1a2571a0464a556b03d4d7c7764b9f66bea23 100644 (file)
@@ -1580,7 +1580,8 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
 
   /* This is the diagnostic_path subclass that will be built for
      the diagnostic.  */
-  checker_path emission_path (get_logger ());
+  checker_path emission_path (get_logical_location_manager (),
+                             get_logger ());
 
   /* Populate emission_path with a full description of EPATH.  */
   build_emission_path (pb, *epath, &emission_path);
@@ -1656,6 +1657,15 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
     }
 }
 
+const logical_location_manager &
+diagnostic_manager::get_logical_location_manager () const
+{
+  gcc_assert (global_dc);
+  auto mgr = global_dc->get_logical_location_manager ();
+  gcc_assert (mgr);
+  return *mgr;
+}
+
 /* Emit a "path" of events to EMISSION_PATH describing the exploded path
    EPATH within EG.  */
 
index b62fc7a258e57bdd0d9a6e00d90521261b62cdd2..aa0bd79faedbcbd23be40c00aa9f1016b883aa5a 100644 (file)
@@ -191,6 +191,9 @@ public:
   }
 
 private:
+  const logical_location_manager &
+  get_logical_location_manager () const;
+
   void build_emission_path (const path_builder &pb,
                            const exploded_path &epath,
                            checker_path *emission_path) const;
index 0057b803bc9e1e2ac454ca6cecf7a88feaa5dae2..99091727819838ecc82aead95dd1bb8322b7a11a 100644 (file)
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_DIAGNOSTIC_CLIENT_DATA_HOOKS_H
 #define GCC_DIAGNOSTIC_CLIENT_DATA_HOOKS_H
 
+#include "logical-location.h"
+
 class sarif_object;
 class client_version_info;
 
@@ -35,8 +37,13 @@ class diagnostic_client_data_hooks
   /* Get version info for this client, or NULL.  */
   virtual const client_version_info *get_any_version_info () const = 0;
 
-  /* Get the current logical_location for this client, or NULL.  */
-  virtual const logical_location *get_current_logical_location () const = 0;
+  /* Get the current logical_location_manager for this client, or NULL.  */
+  virtual const logical_location_manager *get_logical_location_manager () const = 0;
+
+  /* Get the current logical_location, or null.
+     If this returns a non-null logical_location, then
+     get_logical_location_manager must return non-NULL.  */
+  virtual logical_location get_current_logical_location () const = 0;
 
   /* Get a sourceLanguage value for FILENAME, or return NULL.
      See SARIF v2.1.0 Appendix J for suggested values.  */
index c28804e78fbf3969cdd679e5e58fa3ccb53e259b..205678dbe041f041fa112115e95ce7ba887f7999 100644 (file)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-buffer.h"
 #include "json.h"
 #include "selftest.h"
+#include "diagnostic-client-data-hooks.h"
 #include "logical-location.h"
 
 class json_output_format;
@@ -272,11 +273,13 @@ make_json_for_path (diagnostic_context &context,
       auto pp = ref_pp->clone ();
       event.print_desc (*pp.get ());
       event_obj->set_string ("description", pp_formatted_text (pp.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 ());
-       }
+      if (logical_location logical_loc = event.get_logical_location ())
+       if (auto hooks = context.get_client_data_hooks ())
+         if (auto mgr = hooks->get_logical_location_manager ())
+           {
+             label_text name (mgr->get_name_for_path_output (logical_loc));
+             event_obj->set_string ("function", name.get ());
+           }
       event_obj->set_integer ("depth", event.get_stack_depth ());
       path_array->append (std::move (event_obj));
     }
index bc6abdff5e4e04fed2c21864564dbfd02695e546..e9a3872914213f2e7bf66dc01d03dfead1e8ccc2 100644 (file)
@@ -708,6 +708,12 @@ public:
     m_printer = &printer;
   }
 
+  const logical_location_manager *
+  get_logical_location_manager () const
+  {
+    return m_logical_loc_mgr;
+  }
+
   void on_report_diagnostic (const diagnostic_info &diagnostic,
                             diagnostic_t orig_diag_kind,
                             diagnostic_sarif_format_buffer *buffer);
@@ -729,7 +735,7 @@ public:
   std::unique_ptr<sarif_location>
   make_location_object (sarif_location_manager &loc_mgr,
                        const rich_location &rich_loc,
-                       const logical_location *logical_loc,
+                       logical_location logical_loc,
                        enum diagnostic_artifact_role role);
   std::unique_ptr<sarif_location>
   make_location_object (sarif_location_manager &loc_mgr,
@@ -790,7 +796,7 @@ private:
                         location_t where);
   void
   set_any_logical_locs_arr (sarif_location &location_obj,
-                           const logical_location *logical_loc);
+                           logical_location logical_loc);
   std::unique_ptr<sarif_location>
   make_location_object (sarif_location_manager &loc_mgr,
                        const diagnostic_event &event,
@@ -879,6 +885,8 @@ private:
   const line_maps *m_line_maps;
   sarif_token_printer m_token_printer;
 
+  const logical_location_manager *m_logical_loc_mgr;
+
   /* The JSON object for the invocation object.  */
   std::unique_ptr<sarif_invocation> m_invocation_obj;
 
@@ -1232,7 +1240,8 @@ sarif_result::on_nested_diagnostic (const diagnostic_info &diagnostic,
      sometimes these will related to current_function_decl, but
      often they won't.  */
   auto location_obj
-    = builder.make_location_object (*this, *diagnostic.richloc, nullptr,
+    = builder.make_location_object (*this, *diagnostic.richloc,
+                                   logical_location (),
                                    diagnostic_artifact_role::result_file);
   auto message_obj
     = builder.make_message_object (pp_formatted_text (builder.get_printer ()));
@@ -1579,6 +1588,7 @@ sarif_builder::sarif_builder (diagnostic_context &context,
   m_printer (&printer),
   m_line_maps (line_maps),
   m_token_printer (*this),
+  m_logical_loc_mgr (nullptr),
   m_invocation_obj
     (std::make_unique<sarif_invocation> (*this,
                                         context.get_original_argv ())),
@@ -1596,6 +1606,9 @@ sarif_builder::sarif_builder (diagnostic_context &context,
   gcc_assert (m_line_maps);
   gcc_assert (m_serialization_format);
 
+  if (auto client_data_hooks = context.get_client_data_hooks ())
+    m_logical_loc_mgr = client_data_hooks->get_logical_location_manager ();
+
   /* Mark MAIN_INPUT_FILENAME_ as the artifact that the tool was
      instructed to scan.
      Only quote the contents if it gets referenced by physical locations,
@@ -2089,7 +2102,7 @@ sarif_builder::make_locations_arr (sarif_location_manager &loc_mgr,
                                   enum diagnostic_artifact_role role)
 {
   auto locations_arr = std::make_unique<json::array> ();
-  const logical_location *logical_loc = nullptr;
+  logical_location logical_loc;
   if (auto client_data_hooks = m_context.get_client_data_hooks ())
     logical_loc = client_data_hooks->get_current_logical_location ();
 
@@ -2108,13 +2121,15 @@ sarif_builder::make_locations_arr (sarif_location_manager &loc_mgr,
 void
 sarif_builder::
 set_any_logical_locs_arr (sarif_location &location_obj,
-                         const logical_location *logical_loc)
+                         logical_location logical_loc)
 {
   if (!logical_loc)
     return;
+  gcc_assert (m_logical_loc_mgr);
   auto location_locs_arr = std::make_unique<json::array> ();
   location_locs_arr->append<sarif_logical_location>
-    (make_sarif_logical_location_object (*logical_loc));
+    (make_sarif_logical_location_object (logical_loc,
+                                        *m_logical_loc_mgr));
   location_obj.set<json::array> ("logicalLocations",
                                 std::move (location_locs_arr));
 }
@@ -2127,7 +2142,7 @@ set_any_logical_locs_arr (sarif_location &location_obj,
 std::unique_ptr<sarif_location>
 sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
                                     const rich_location &rich_loc,
-                                    const logical_location *logical_loc,
+                                    logical_location logical_loc,
                                     enum diagnostic_artifact_role role)
 {
   class escape_nonascii_renderer : public content_renderer
@@ -2321,7 +2336,7 @@ sarif_builder::make_location_object (sarif_location_manager &loc_mgr,
                                                std::move (phs_loc_obj));
 
   /* "logicalLocations" property (SARIF v2.1.0 section 3.28.4).  */
-  const logical_location *logical_loc = event.get_logical_location ();
+  logical_location logical_loc = event.get_logical_location ();
   set_any_logical_locs_arr (*location_obj, logical_loc);
 
   /* "message" property (SARIF v2.1.0 section 3.28.5).  */
@@ -2670,32 +2685,53 @@ maybe_get_sarif_kind (enum logical_location_kind kind)
     }
 }
 
-/* Make a "logicalLocation" object (SARIF v2.1.0 section 3.33) for LOGICAL_LOC,
-   or return nullptr.  */
+/* Set PROPERTY_NAME within this bag to a "logicalLocation" object (SARIF v2.1.0
+   section 3.33) for LOGICAL_LOC.  The object has an "index" property to refer to
+   theRuns.logicalLocations (3.33.3).  */
+
+void
+sarif_property_bag::set_logical_location (const char *property_name,
+                                         sarif_builder &builder,
+                                         logical_location logical_loc)
+{
+  gcc_assert (logical_loc);
+  const logical_location_manager *mgr
+    = builder.get_logical_location_manager ();
+  gcc_assert (mgr);
+  set<sarif_logical_location>
+    (property_name,
+     make_sarif_logical_location_object (logical_loc, *mgr));
+}
+
+/* Make a "logicalLocation" object (SARIF v2.1.0 section 3.33) for
+   LOGICAL_LOC, which must be non-null.  */
 
 std::unique_ptr<sarif_logical_location>
-make_sarif_logical_location_object (const logical_location &logical_loc)
+make_sarif_logical_location_object (logical_location logical_loc,
+                                   const logical_location_manager &mgr)
 {
-  auto logical_loc_obj = std::make_unique<sarif_logical_location> ();
+  gcc_assert (logical_loc);
+
+  auto sarif_logical_loc = std::make_unique<sarif_logical_location> ();
 
   /* "name" property (SARIF v2.1.0 section 3.33.4).  */
-  if (const char *short_name = logical_loc.get_short_name ())
-    logical_loc_obj->set_string ("name", short_name);
+  if (const char *short_name = mgr.get_short_name (logical_loc))
+    sarif_logical_loc->set_string ("name", short_name);
 
   /* "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
-  if (const char *name_with_scope = logical_loc.get_name_with_scope ())
-    logical_loc_obj->set_string ("fullyQualifiedName", name_with_scope);
+  if (const char *name_with_scope = mgr.get_name_with_scope (logical_loc))
+    sarif_logical_loc->set_string ("fullyQualifiedName", name_with_scope);
 
   /* "decoratedName" property (SARIF v2.1.0 section 3.33.6).  */
-  if (const char *internal_name = logical_loc.get_internal_name ())
-    logical_loc_obj->set_string ("decoratedName", internal_name);
+  if (const char *internal_name = mgr.get_internal_name (logical_loc))
+    sarif_logical_loc->set_string ("decoratedName", internal_name);
 
   /* "kind" property (SARIF v2.1.0 section 3.33.7).  */
-  enum logical_location_kind kind = logical_loc.get_kind ();
+  enum logical_location_kind kind = mgr.get_kind (logical_loc);
   if (const char *sarif_kind_str = maybe_get_sarif_kind (kind))
-    logical_loc_obj->set_string ("kind", sarif_kind_str);
+    sarif_logical_loc->set_string ("kind", sarif_kind_str);
 
-  return logical_loc_obj;
+  return sarif_logical_loc;
 }
 
 label_text
@@ -2784,7 +2820,7 @@ populate_thread_flow_location_object (sarif_result &result,
 {
   /* Give diagnostic_event subclasses a chance to add custom properties
      via a property bag.  */
-  ev.maybe_add_sarif_properties (tfl_obj);
+  ev.maybe_add_sarif_properties (*this, tfl_obj);
 
   /* "location" property (SARIF v2.1.0 section 3.38.3).  */
   tfl_obj.set<sarif_location>
@@ -4029,7 +4065,8 @@ test_make_location_object (const sarif_generation_options &sarif_gen_opts,
 
   std::unique_ptr<sarif_location> location_obj
     = builder.make_location_object
-    (result, richloc, nullptr, diagnostic_artifact_role::analysis_target);
+       (result, richloc, logical_location (),
+        diagnostic_artifact_role::analysis_target);
   ASSERT_NE (location_obj, nullptr);
 
   auto physical_location
index 644625747cc8661c1d68fe35f6aa11131de3e4a2..354f18a6c6900c603c42ab923b504919050736ae 100644 (file)
@@ -24,8 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "json.h"
 #include "diagnostic-format.h"
 #include "diagnostic-output-file.h"
-
-class logical_location;
+#include "logical-location.h"
 
 /* Enum for choosing what format to serializing the generated SARIF into.  */
 
@@ -115,11 +114,17 @@ make_sarif_sink (diagnostic_context &context,
                 const sarif_generation_options &sarif_gen_opts,
                 diagnostic_output_file output_file);
 
+class sarif_builder;
+
 /* Concrete subclass of json::object for SARIF property bags
    (SARIF v2.1.0 section 3.8).  */
 
 class sarif_property_bag : public json::object
 {
+public:
+  void set_logical_location (const char *property_name,
+                            sarif_builder &,
+                            logical_location logical_loc);
 };
 
 /* Concrete subclass of json::object for SARIF objects that can
@@ -142,6 +147,7 @@ class sarif_logical_location : public sarif_object
 };
 
 extern std::unique_ptr<sarif_logical_location>
-make_sarif_logical_location_object (const logical_location &logical_loc);
+make_sarif_logical_location_object (logical_location logical_loc,
+                                   const logical_location_manager &mgr);
 
 #endif /* ! GCC_DIAGNOSTIC_FORMAT_SARIF_H */
index d618c3714e3879f13e9b5fb9d2fc159d393ff3e2..9340e4e3a297065ee2e2f34bf4b28d1a6ccfd4ba 100644 (file)
@@ -181,8 +181,8 @@ diagnostic_path::get_first_event_in_a_function (unsigned *out_idx) const
   for (unsigned i = 0; i < num; i++)
     {
       const diagnostic_event &event = get_event (i);
-      if (const logical_location *logical_loc = event.get_logical_location ())
-       if (logical_loc->function_p ())
+      if (logical_location logical_loc = event.get_logical_location ())
+       if (m_logical_loc_mgr.function_p (logical_loc))
          {
            *out_idx = i;
            return true;
@@ -409,8 +409,10 @@ class per_thread_summary
 {
 public:
   per_thread_summary (const diagnostic_path &path,
+                     const logical_location_manager &logical_loc_mgr,
                      label_text name, unsigned swimlane_idx)
   : m_path (path),
+    m_logical_loc_mgr (logical_loc_mgr),
     m_name (std::move (name)),
     m_swimlane_idx (swimlane_idx),
     m_last_event (nullptr),
@@ -437,6 +439,7 @@ private:
   friend struct event_range;
 
   const diagnostic_path &m_path;
+  const logical_location_manager &m_logical_loc_mgr;
 
   const label_text m_name;
 
@@ -703,7 +706,7 @@ struct event_range
 
   const diagnostic_path &m_path;
   const diagnostic_event &m_initial_event;
-  const logical_location *m_logical_loc;
+  logical_location m_logical_loc;
   int m_stack_depth;
   unsigned m_start_idx;
   unsigned m_end_idx;
@@ -729,6 +732,10 @@ struct path_summary
                bool colorize = false,
                bool show_event_links = true);
 
+  const logical_location_manager &get_logical_location_manager () const
+  {
+    return m_logical_loc_mgr;
+  }
   unsigned get_num_ranges () const { return m_ranges.length (); }
   bool multithreaded_p () const { return m_per_thread_summary.length () > 1; }
 
@@ -740,6 +747,7 @@ struct path_summary
     return **slot;
   }
 
+  const logical_location_manager &m_logical_loc_mgr;
   auto_delete_vec <event_range> m_ranges;
   auto_delete_vec <per_thread_summary> m_per_thread_summary;
   hash_map<int_hash<diagnostic_thread_id_t, -1, -2>,
@@ -756,6 +764,7 @@ private:
     const diagnostic_thread &thread = path.get_thread (tid);
     per_thread_summary *pts
       = new per_thread_summary (path,
+                               m_logical_loc_mgr,
                                thread.get_name (false),
                                m_per_thread_summary.length ());
     m_thread_id_to_events.put (tid, pts);
@@ -792,6 +801,7 @@ path_summary::path_summary (const path_print_policy &policy,
                            bool check_rich_locations,
                            bool colorize,
                            bool show_event_links)
+: m_logical_loc_mgr (path.get_logical_location_manager ())
 {
   const unsigned num_events = path.num_events ();
 
@@ -872,6 +882,7 @@ public:
   void
   print_swimlane_for_event_range (diagnostic_text_output_format &text_output,
                                  pretty_printer *pp,
+                                 const logical_location_manager &logical_loc_mgr,
                                  event_range *range,
                                  diagnostic_source_effect_info *effect_info)
   {
@@ -916,9 +927,10 @@ public:
            m_cur_indent += 5;
          }
       }
-    if (const logical_location *logical_loc = range->m_logical_loc)
+    if (range->m_logical_loc)
       {
-       label_text name (logical_loc->get_name_for_path_output ());
+       label_text name
+         (logical_loc_mgr.get_name_for_path_output (range->m_logical_loc));
        if (name.get ())
          pp_printf (pp, "%qs: ", name.get ());
       }
@@ -1113,7 +1125,9 @@ print_path_summary_as_text (const path_summary &ps,
         of this range.  */
       diagnostic_source_effect_info effect_info;
       effect_info.m_leading_in_edge_column = last_out_edge_column;
-      tep.print_swimlane_for_event_range (text_output, pp, range, &effect_info);
+      tep.print_swimlane_for_event_range (text_output, pp,
+                                         ps.get_logical_location_manager (),
+                                         range, &effect_info);
       last_out_edge_column = effect_info.m_trailing_out_edge_column;
     }
 }
@@ -1155,6 +1169,7 @@ diagnostic_text_output_format::print_path (const diagnostic_path &path)
     case DPF_SEPARATE_EVENTS:
       {
        /* A note per event.  */
+       auto &logical_loc_mgr = path.get_logical_location_manager ();
        for (unsigned i = 0; i < num_events; i++)
          {
            const diagnostic_event &event = path.get_event (i);
@@ -1166,10 +1181,11 @@ diagnostic_text_output_format::print_path (const diagnostic_path &path)
                /* -fdiagnostics-path-format=separate-events doesn't print
                   fndecl information, so with -fdiagnostics-show-path-depths
                   print the fndecls too, if any.  */
-               if (const logical_location *logical_loc
+               if (logical_location logical_loc
                      = event.get_logical_location ())
                  {
-                   label_text name (logical_loc->get_name_for_path_output ());
+                   label_text name
+                     (logical_loc_mgr.get_name_for_path_output (logical_loc));
                    inform (event.get_location (),
                            "%@ %e (fndecl %qs, depth %i)",
                            &event_id, &e_event_desc,
index 878d6ff5ae69ceecd33e820d27e556caafded7c4..4419139413bdc4b498d2883f84101dc489748223 100644 (file)
@@ -23,7 +23,9 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "diagnostic.h" /* for ATTRIBUTE_GCC_DIAG.  */
 #include "diagnostic-event-id.h"
+#include "logical-location.h"
 
+class sarif_builder;
 class sarif_object;
 
 /* A diagnostic_path is an optional additional piece of metadata associated
@@ -149,8 +151,8 @@ class diagnostic_event
   /* Print a localized (and possibly colorized) description of this event.  */
   virtual void print_desc (pretty_printer &pp) const = 0;
 
-  /* Get a logical_location for this event, or nullptr if there is none.  */
-  virtual const logical_location *get_logical_location () const = 0;
+  /* Get a logical location for this event, or null if there is none.  */
+  virtual logical_location get_logical_location () const = 0;
 
   virtual meaning get_meaning () const = 0;
 
@@ -163,7 +165,8 @@ class diagnostic_event
   /* Hook for SARIF output to allow for adding diagnostic-specific
      properties to the threadFlowLocation object's property bag.  */
   virtual void
-  maybe_add_sarif_properties (sarif_object &/*thread_flow_loc_obj*/) const
+  maybe_add_sarif_properties (sarif_builder &,
+                             sarif_object &/*thread_flow_loc_obj*/) const
   {
   }
 
@@ -203,8 +206,21 @@ class diagnostic_path
   bool interprocedural_p () const;
   bool multithreaded_p () const;
 
+  const logical_location_manager &get_logical_location_manager () const
+  {
+    return m_logical_loc_mgr;
+  }
+
+protected:
+  diagnostic_path (const logical_location_manager &logical_loc_mgr)
+  : m_logical_loc_mgr (logical_loc_mgr)
+  {
+  }
+
 private:
   bool get_first_event_in_a_function (unsigned *out_idx) const;
+
+  const logical_location_manager &m_logical_loc_mgr;
 };
 
 /* Concrete subclasses of the above can be found in
index c3ea1b34d2f2544f0901f1d16aa53bf61992f171..b43fc907ed131c9065302813375d71b8ebf538ac 100644 (file)
@@ -580,6 +580,14 @@ diagnostic_context::pop_urlifier ()
     delete node.m_urlifier;
 }
 
+const logical_location_manager *
+diagnostic_context::get_logical_location_manager () const
+{
+  if (!m_client_data_hooks)
+    return nullptr;
+  return m_client_data_hooks->get_logical_location_manager ();
+}
+
 const urlifier *
 diagnostic_context::get_urlifier () const
 {
@@ -1037,14 +1045,14 @@ diagnostic_context::notes_inhibited_in_group () const
   return false;
 }
 
-/* class logical_location.  */
+/* class logical_location_manager.  */
 
 /* Return true iff this is a function or method.  */
 
 bool
-logical_location::function_p () const
+logical_location_manager::function_p (key k) const
 {
-  switch (get_kind ())
+  switch (get_kind (k))
     {
     default:
       gcc_unreachable ();
index 88288d0df2626c642f9f34a3573452ea1b9d814e..00d7812248a4ac028cfbe8c57270ae8dd80a077d 100644 (file)
@@ -217,7 +217,7 @@ public:
 
 class edit_context;
 class diagnostic_client_data_hooks;
-class logical_location;
+class logical_location_manager;
 class diagnostic_diagram;
 class diagnostic_source_effect_info;
 class diagnostic_output_format;
@@ -671,6 +671,9 @@ public:
     return m_client_data_hooks;
   }
 
+  const logical_location_manager *
+  get_logical_location_manager () const;
+
   const urlifier *get_urlifier () const;
 
   text_art::theme *get_diagram_theme () const { return m_diagrams.m_theme; }
index 1474f70390b570706baeaefcfd59e549c20fef54..37c8e25bd7c72b64e7c272068219508e7529db09 100644 (file)
@@ -91,7 +91,8 @@ class test_lazy_path : public lazy_diagnostic_path
 {
 public:
   test_lazy_path (pretty_printer &pp)
-  : m_pp (pp)
+  : lazy_diagnostic_path (m_logical_loc_mgr),
+    m_pp (pp)
   {
   }
   std::unique_ptr<diagnostic_path> make_inner_path () const final override
@@ -99,12 +100,15 @@ public:
     tree fntype_void_void
       = build_function_type_array (void_type_node, 0, NULL);
     tree fndecl_foo = build_fn_decl ("foo", fntype_void_void);
-    auto path = std::make_unique<simple_diagnostic_path> (&m_pp);
+    auto path
+      = std::make_unique<simple_diagnostic_path> (m_logical_loc_mgr,
+                                                 &m_pp);
     path->add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "first %qs", "free");
     path->add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "double %qs", "free");
     return path;
   }
 private:
+  const tree_logical_location_manager m_logical_loc_mgr;
   pretty_printer &m_pp;
 };
 
index 01564567155cc7c7b7d148d8846d8ded0574349e..9609cab029536305fccb441306f424b8a9b2ea2c 100644 (file)
@@ -48,6 +48,12 @@ class lazy_diagnostic_path : public diagnostic_path
 
   bool generated_p () const { return m_inner_path != nullptr; }
 
+protected:
+  lazy_diagnostic_path (const logical_location_manager &logical_loc_mgr)
+  : diagnostic_path (logical_loc_mgr)
+  {
+  }
+
  private:
   void lazily_generate_path () const;
   virtual std::unique_ptr<diagnostic_path> make_inner_path () const = 0;
index 8a4a159ecb7458a7b68925d325fd3aea82766e59..c085cd8e941ce187d86f1b6eac3a2d35d6d36387 100644 (file)
@@ -162,7 +162,7 @@ as_location_t (const diagnostic_physical_location *loc)
 
 /* This has to be a "struct" as it is exposed in the C API.  */
 
-struct diagnostic_logical_location : public logical_location
+struct diagnostic_logical_location
 {
   diagnostic_logical_location (enum diagnostic_logical_location_kind_t kind,
                               const diagnostic_logical_location *parent,
@@ -177,60 +177,6 @@ struct diagnostic_logical_location : public logical_location
   {
   }
 
-  const char *get_short_name () const final override
-  {
-    return m_short_name.get_str ();
-  }
-  const char *get_name_with_scope () const final override
-  {
-    return m_fully_qualified_name.get_str ();
-  }
-  const char *get_internal_name () const final override
-  {
-    return m_decorated_name.get_str ();
-  }
-  enum logical_location_kind get_kind () const final override
-  {
-    switch (m_kind)
-      {
-      default:
-       gcc_unreachable ();
-      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION:
-       return LOGICAL_LOCATION_KIND_FUNCTION;
-      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER:
-       return LOGICAL_LOCATION_KIND_MEMBER;
-      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE:
-       return LOGICAL_LOCATION_KIND_MODULE;
-      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE:
-       return LOGICAL_LOCATION_KIND_NAMESPACE;
-      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE:
-       return LOGICAL_LOCATION_KIND_TYPE;
-      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE:
-       return LOGICAL_LOCATION_KIND_RETURN_TYPE;
-      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER:
-       return LOGICAL_LOCATION_KIND_PARAMETER;
-      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE:
-       return LOGICAL_LOCATION_KIND_VARIABLE;
-      }
-  }
-
-  enum diagnostic_logical_location_kind_t get_external_kind () const
-  {
-    return m_kind;
-  }
-
-  const diagnostic_logical_location *get_parent () const { return m_parent; }
-
-  const char *get_fully_qualified_name () const
-  {
-    return m_fully_qualified_name.get_str ();
-  }
-
-  label_text get_name_for_path_output () const
-  {
-    return label_text::borrow (m_short_name.get_str ());
-  }
-
   bool
   operator< (const diagnostic_logical_location &other) const
   {
@@ -248,7 +194,6 @@ struct diagnostic_logical_location : public logical_location
     return false;
   }
 
-private:
   enum diagnostic_logical_location_kind_t m_kind;
   const diagnostic_logical_location *m_parent;
   owned_nullable_string m_short_name;
@@ -313,6 +258,80 @@ round_alloc_size (size_t s)
   return s;
 }
 
+class impl_logical_location_manager : public logical_location_manager
+{
+public:
+  static const diagnostic_logical_location *
+  ptr_from_key (logical_location k)
+  {
+    return k.cast_to<const diagnostic_logical_location *> ();
+  }
+
+  static logical_location
+  key_from_ptr (const diagnostic_logical_location *ptr)
+  {
+    return logical_location::from_ptr (ptr);
+  }
+
+  const char *get_short_name (key k) const final override
+  {
+    if (auto loc = ptr_from_key (k))
+      return loc->m_short_name.get_str ();
+    else
+      return nullptr;
+  }
+
+  const char *get_name_with_scope (key k) const final override
+  {
+    if (auto loc = ptr_from_key (k))
+      return loc->m_fully_qualified_name.get_str ();
+    else
+      return nullptr;
+  }
+
+  const char *get_internal_name (key k) const final override
+  {
+    if (auto loc = ptr_from_key (k))
+      return loc->m_decorated_name.get_str ();
+    else
+      return nullptr;
+  }
+
+  enum logical_location_kind get_kind (key k) const final override
+  {
+    auto loc = ptr_from_key (k);
+    gcc_assert (loc);
+    switch (loc->m_kind)
+      {
+      default:
+       gcc_unreachable ();
+      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION:
+       return LOGICAL_LOCATION_KIND_FUNCTION;
+      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER:
+       return LOGICAL_LOCATION_KIND_MEMBER;
+      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE:
+       return LOGICAL_LOCATION_KIND_MODULE;
+      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE:
+       return LOGICAL_LOCATION_KIND_NAMESPACE;
+      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE:
+       return LOGICAL_LOCATION_KIND_TYPE;
+      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE:
+       return LOGICAL_LOCATION_KIND_RETURN_TYPE;
+      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER:
+       return LOGICAL_LOCATION_KIND_PARAMETER;
+      case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE:
+       return LOGICAL_LOCATION_KIND_VARIABLE;
+      }
+  }
+
+  label_text get_name_for_path_output (key k) const final override
+  {
+    auto loc = ptr_from_key (k);
+    gcc_assert (loc);
+    return label_text::borrow (loc->m_short_name.get_str ());
+  }
+};
+
 class impl_diagnostic_client_data_hooks : public diagnostic_client_data_hooks
 {
 public:
@@ -321,7 +340,14 @@ public:
   {}
 
   const client_version_info *get_any_version_info () const final override;
-  const logical_location *get_current_logical_location () const final override;
+
+  const logical_location_manager *
+  get_logical_location_manager () const final override
+  {
+    return &m_logical_location_manager;
+  }
+  logical_location get_current_logical_location () const final override;
+
   const char * maybe_get_sarif_source_language (const char *filename)
     const final override;
   void add_sarif_invocation_properties (sarif_object &invocation_obj)
@@ -329,6 +355,7 @@ public:
 
 private:
   diagnostic_manager &m_mgr;
+  impl_logical_location_manager m_logical_location_manager;
 };
 
 class impl_client_version_info : public client_version_info
@@ -429,6 +456,14 @@ public:
   line_maps *get_line_table () { return &m_line_table; }
   diagnostic_context &get_dc () { return m_dc; }
 
+  const logical_location_manager &
+  get_logical_location_manager () const
+  {
+    auto mgr = m_dc.get_logical_location_manager ();
+    gcc_assert (mgr);
+    return *mgr;
+  }
+
   void write_patch (FILE *dst_stream);
 
   void add_sink (std::unique_ptr<sink> sink)
@@ -711,9 +746,9 @@ public:
       pp_string (&pp, m_desc_uncolored.get ());
   }
 
-  const logical_location *get_logical_location () const
+  logical_location get_logical_location () const final override
   {
-    return m_logical_loc;
+    return impl_logical_location_manager::key_from_ptr (m_logical_loc);
   }
 
   meaning get_meaning () const final override
@@ -777,8 +812,9 @@ private:
 
 struct diagnostic_execution_path : public diagnostic_path
 {
-  diagnostic_execution_path ()
-  : m_thread ("")
+  diagnostic_execution_path (const logical_location_manager &logical_loc_mgr)
+  : diagnostic_path (logical_loc_mgr),
+    m_thread ("")
   {
   }
 
@@ -819,9 +855,9 @@ struct diagnostic_execution_path : public diagnostic_path
   same_function_p (int event_idx_a,
                   int event_idx_b) const final override
   {
-    const logical_location *logical_loc_a
+    logical_location logical_loc_a
       = m_events[event_idx_a]->get_logical_location ();
-    const logical_location *logical_loc_b
+    logical_location logical_loc_b
       = m_events[event_idx_b]->get_logical_location ();
 
     /* Pointer equality, as we uniqify logical location instances.  */
@@ -907,7 +943,9 @@ public:
   diagnostic_execution_path *
   add_execution_path ()
   {
-    m_path = std::make_unique<diagnostic_execution_path> ();
+    m_path
+      = std::make_unique<diagnostic_execution_path>
+         (m_diag_mgr.get_logical_location_manager ());
     m_rich_loc.set_path (m_path.get ());
     return m_path.get ();
   }
@@ -978,12 +1016,13 @@ impl_diagnostic_client_data_hooks::get_any_version_info () const
   return m_mgr.get_client_version_info ();
 }
 
-const logical_location *
+logical_location
 impl_diagnostic_client_data_hooks::get_current_logical_location () const
 {
   gcc_assert (m_mgr.get_current_diag ());
 
-  return m_mgr.get_current_diag ()->get_logical_location ();
+  return impl_logical_location_manager::key_from_ptr
+    (m_mgr.get_current_diag ()->get_logical_location ());
 }
 
 const char *
@@ -1051,13 +1090,13 @@ diagnostic_text_sink::text_starter (diagnostic_text_output_format &text_output,
   if (diag_logical_loc && diag_logical_loc != mgr.get_prev_diag_logical_loc ())
     {
       pp_set_prefix (pp, nullptr);
-      switch (diag_logical_loc->get_kind ())
+      switch (diag_logical_loc->m_kind)
        {
        default:
          break;
-       case LOGICAL_LOCATION_KIND_FUNCTION:
+       case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION:
          if (const char *name
-             = diag_logical_loc->get_name_with_scope ())
+             = diag_logical_loc->m_fully_qualified_name.get_str ())
            {
              pp_printf (pp, _("In function %qs"), name);
              pp_character (pp, ':');
@@ -1135,7 +1174,9 @@ GCC_DIAGNOSTIC_POP
 diagnostic_execution_path *
 diagnostic_manager::new_execution_path ()
 {
-  return new diagnostic_execution_path ();
+  auto mgr = m_dc.get_logical_location_manager ();
+  gcc_assert (mgr);
+  return new diagnostic_execution_path (*mgr);
 }
 
 /* Error-checking at the API boundary.  */
@@ -1463,7 +1504,7 @@ diagnostic_manager_debug_dump_logical_location (const diagnostic_manager *diag_m
   if (loc)
     {
       fprintf (out, "logical_location(kind=");
-      switch (loc->get_external_kind ())
+      switch (loc->m_kind)
        {
        default:
          gcc_unreachable ();
@@ -1492,15 +1533,18 @@ diagnostic_manager_debug_dump_logical_location (const diagnostic_manager *diag_m
          fprintf (out, "variable");
          break;
        }
-      if (const diagnostic_logical_location *parent = loc->get_parent ())
-       diagnostic_manager_debug_dump_logical_location (diag_mgr,
-                                                       parent,
-                                                       out);
-      if (const char *val = loc->get_short_name ())
+      if (auto parent = loc->m_parent)
+       {
+         fprintf (out, ", parent=");
+        diagnostic_manager_debug_dump_logical_location (diag_mgr,
+                                                        parent,
+                                                        out);
+       }
+      if (const char *val = loc->m_short_name.get_str ())
        fprintf (out, ", short_name=\"%s\"", val);
-      if (const char *val = loc->get_name_with_scope ())
+      if (const char *val = loc->m_fully_qualified_name.get_str ())
        fprintf (out, ", fully_qualified_name=\"%s\"", val);
-      if (const char *val = loc->get_internal_name ())
+      if (const char *val = loc->m_decorated_name.get_str ())
        fprintf (out, ", decorated_name=\"%s\"", val);
       fprintf (out, ")");
     }
@@ -1801,7 +1845,7 @@ diagnostic_logical_location_get_kind (const diagnostic_logical_location *loc)
 {
   FAIL_IF_NULL (loc);
 
-  return loc->get_external_kind ();
+  return loc->m_kind;
 }
 
 const diagnostic_logical_location *
@@ -1809,7 +1853,7 @@ diagnostic_logical_location_get_parent (const diagnostic_logical_location *loc)
 {
   FAIL_IF_NULL (loc);
 
-  return loc->get_parent ();
+  return loc->m_parent;
 }
 
 const char *
@@ -1817,7 +1861,7 @@ diagnostic_logical_location_get_short_name (const diagnostic_logical_location *l
 {
   FAIL_IF_NULL (loc);
 
-  return loc->get_short_name ();
+  return loc->m_short_name.get_str ();
 }
 
 const char *
@@ -1825,7 +1869,7 @@ diagnostic_logical_location_get_fully_qualified_name (const diagnostic_logical_l
 {
   FAIL_IF_NULL (loc);
 
-  return loc->get_fully_qualified_name ();
+  return loc->m_fully_qualified_name.get_str ();
 }
 
 const char *
@@ -1833,5 +1877,5 @@ diagnostic_logical_location_get_decorated_name (const diagnostic_logical_locatio
 {
   FAIL_IF_NULL (loc);
 
-  return loc->get_internal_name ();
+  return loc->m_decorated_name.get_str ();
 }
index 000335cadfad101c3adfda2b9d9951b8bf9db76a..3308e2d566409c8d1d66b136d378ac5053d89d70 100644 (file)
@@ -43,38 +43,114 @@ enum logical_location_kind
   LOGICAL_LOCATION_KIND_VARIABLE
 };
 
-/* Abstract base class for passing around logical locations in the
+/* We want to efficiently support passing around logical locations in the
    diagnostics subsystem, such as:
    - "within function 'foo'", or
-   - "within method 'bar'",
-   but *without* requiring knowledge of trees
-   (see tree-logical-location.h for concrete subclasses relating to trees,
-   and selftest-logical-location.h for a concrete subclass for selftests).  */
+   - "within method 'bar'"
 
-class logical_location
+   However we want to do this *without* requiring knowledge of trees (or of
+   libgdiagnostics internals), and without requiring heap allocation of an
+   interface class when emitting a diagnostic.
+
+   To do this, we split the implementation into logical_location, which is
+   a wrapper around a (const void *), and logical_location_manager which
+   is provided by the client and has vfunc hooks for interpreting
+   logical_location instances.
+
+   Every logical_location is associated with a logical_location_manager and
+   only has meaning in relation to that manager.
+
+   A "nullptr" within a logical_location means "no logical location".
+
+   See tree-logical-location.h for concrete subclasses relating to trees,
+   where the pointer is a const_tree.
+
+   See selftest-logical-location.h for a concrete subclass for selftests.  */
+
+/* Abstract base class for giving meaning to logical_location values.
+   Typically there will just be one client-provided instance, of a
+   client-specific subclass.  */
+
+class logical_location_manager
 {
 public:
-  virtual ~logical_location () {}
-
-  /* Get a string (or NULL) suitable for use by the SARIF logicalLocation
+  /* Extrinsic state for identifying a specific logical location.
+     This will be our logical_location type.
+     This only makes sense with respect to a specific manager.
+     e.g. for a tree-based one it's a wrapper around "tree".
+     "nullptr" means "no logical location".  */
+  class key
+  {
+  public:
+    key () : m_ptr (nullptr) {}
+
+    static key from_ptr (const void *ptr)
+    {
+      return key (ptr);
+    }
+
+    operator bool () const
+    {
+      return m_ptr != nullptr;
+    }
+
+    template <typename T>
+    T cast_to () const { return static_cast<T> (m_ptr); }
+
+    bool
+    operator== (const key &other) const
+    {
+      return m_ptr == other.m_ptr;
+    }
+
+    bool
+    operator!= (const key &other) const
+    {
+      return m_ptr != other.m_ptr;
+    }
+
+    bool
+    operator< (const key &other) const
+    {
+      return m_ptr < other.m_ptr;
+    }
+
+  private:
+    explicit key (const void *ptr) : m_ptr (ptr) {}
+
+    const void *m_ptr;
+  };
+
+  virtual ~logical_location_manager () {}
+
+  /* vfuncs for interpreting logical_location values.  */
+
+  /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
      "name" property (SARIF v2.1.0 section 3.33.4).  */
-  virtual const char *get_short_name () const = 0;
+  virtual const char *get_short_name (key k) const = 0;
 
-  /* Get a string (or NULL) suitable for use by the SARIF logicalLocation
+  /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
      "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
-  virtual const char *get_name_with_scope () const = 0;
+  virtual const char *get_name_with_scope (key k) const = 0;
 
-  /* Get a string (or NULL) suitable for use by the SARIF logicalLocation
+  /* Get a string (or NULL) for K suitable for use by the SARIF logicalLocation
      "decoratedName" property (SARIF v2.1.0 section 3.33.6).  */
-  virtual const char *get_internal_name () const = 0;
+  virtual const char *get_internal_name (key k) const = 0;
 
-  /* Get what kind of SARIF logicalLocation this is (if any).  */
-  virtual enum logical_location_kind get_kind () const = 0;
+  /* Get what kind of SARIF logicalLocation K is (if any).  */
+  virtual enum logical_location_kind get_kind (key k) 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;
+  /* Get a string for location K in a form suitable for path output.  */
+  virtual label_text get_name_for_path_output (key k) const = 0;
 
-  bool function_p () const;
+  bool function_p (key k) const;
 };
 
+/* A logical location is a key for a given logical_location_manager.
+
+   Note that there is no integration with GCC's garbage collector and thus
+   logical_location instances can't be long-lived.  */
+
+typedef logical_location_manager::key logical_location;
+
 #endif /* GCC_LOGICAL_LOCATION_H.  */
index 0e80eeabebe1c6d36ef9fff5506a37318cb428db..04372e7b47b68f770af5968de12750526301d38a 100644 (file)
@@ -36,7 +36,8 @@ namespace selftest {
 /* class test_diagnostic_path : public diagnostic_path.  */
 
 test_diagnostic_path::test_diagnostic_path (pretty_printer *event_pp)
-: m_event_pp (event_pp)
+: diagnostic_path (m_test_logical_loc_mgr),
+  m_event_pp (event_pp)
 {
   add_thread ("main");
 }
@@ -75,12 +76,8 @@ 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;
+  return (m_events[event_idx_a]->get_logical_location ()
+         == m_events[event_idx_b]->get_logical_location ());
 }
 
 diagnostic_thread_id_t
@@ -121,7 +118,10 @@ test_diagnostic_path::add_event (location_t loc,
   va_end (ap);
 
   test_diagnostic_event *new_event
-    = new test_diagnostic_event (loc, funcname, depth, pp_formatted_text (pp));
+    = new test_diagnostic_event (loc,
+                                logical_location_from_funcname (funcname),
+                                depth,
+                                pp_formatted_text (pp));
   m_events.safe_push (new_event);
 
   pp_clear_output_area (pp);
@@ -154,8 +154,11 @@ test_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
   va_end (ap);
 
   test_diagnostic_event *new_event
-    = new test_diagnostic_event (loc, funcname, depth, pp_formatted_text (pp),
-                                  thread_id);
+    = new test_diagnostic_event (loc,
+                                logical_location_from_funcname (funcname),
+                                depth,
+                                pp_formatted_text (pp),
+                                thread_id);
   m_events.safe_push (new_event);
 
   pp_clear_output_area (pp);
@@ -203,18 +206,24 @@ test_diagnostic_path::add_call (const char *caller_name,
   add_entry (callee_name, caller_stack_depth + 1, thread_id);
 }
 
+logical_location
+test_diagnostic_path::logical_location_from_funcname (const char *funcname)
+{
+  return m_test_logical_loc_mgr.logical_location_from_funcname (funcname);
+}
+
 /* 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)
+                      logical_location logical_loc,
+                      int depth,
+                      const char *desc,
+                      diagnostic_thread_id_t thread_id)
 : m_loc (loc),
-  m_logical_loc (LOGICAL_LOCATION_KIND_FUNCTION, funcname),
+  m_logical_loc (logical_loc),
   m_depth (depth), m_desc (xstrdup (desc)),
   m_connected_to_next_event (false),
   m_thread_id (thread_id)
index e20986c58b570ee6f4cea6b868bc036919f7f997..8829943556e03b689591aa9438672090e0f31d68 100644 (file)
@@ -41,7 +41,9 @@ namespace selftest {
 class test_diagnostic_event : public diagnostic_event
 {
  public:
-  test_diagnostic_event (location_t loc, const char *funcname, int depth,
+  test_diagnostic_event (location_t loc,
+                        logical_location logical_loc,
+                        int depth,
                         const char *desc,
                         diagnostic_thread_id_t thread_id = 0);
   ~test_diagnostic_event ();
@@ -52,12 +54,9 @@ class test_diagnostic_event : public diagnostic_event
   {
     pp_string (&pp, m_desc);
   }
-  const logical_location *get_logical_location () const final override
+  logical_location get_logical_location () const final override
   {
-    if (m_logical_loc.get_name ())
-      return &m_logical_loc;
-    else
-      return nullptr;
+    return m_logical_loc;
   }
   meaning get_meaning () const final override
   {
@@ -77,14 +76,9 @@ class test_diagnostic_event : public diagnostic_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;
+  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;
@@ -149,6 +143,10 @@ class test_diagnostic_path : public diagnostic_path
                 diagnostic_thread_id_t thread_id = 0);
 
  private:
+  logical_location
+  logical_location_from_funcname (const char *funcname);
+
+  test_logical_location_manager m_test_logical_loc_mgr;
   auto_delete_vec<test_diagnostic_thread> m_threads;
   auto_delete_vec<test_diagnostic_event> m_events;
 
index 6c1c757ca53c2a4ef7ff785ca6c89fbc9e5525eb..5f33b48c849f2c1ac5a0f1af55a267c58c319f67 100644 (file)
@@ -21,49 +21,96 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "selftest.h"
 #include "selftest-logical-location.h"
 
 #if CHECKING_P
 
 namespace selftest {
 
-/* class test_logical_location : public logical_location.  */
+/* class test_logical_location_manager : public logical_location_manager.  */
 
-test_logical_location::test_logical_location (enum logical_location_kind kind,
-                                             const char *name)
-: m_kind (kind),
-  m_name (name)
+test_logical_location_manager::~test_logical_location_manager ()
 {
+  for (auto iter : m_name_to_item_map)
+    delete iter.second;
 }
 
 const char *
-test_logical_location::get_short_name () const
+test_logical_location_manager::get_short_name (key k) const
 {
-  return m_name;
+  auto item = item_from_key (k);
+  if (!item)
+    return nullptr;
+  return item->m_name;
 }
 
 const char *
-test_logical_location::get_name_with_scope () const
+test_logical_location_manager::get_name_with_scope (key k) const
 {
-  return m_name;
+  auto item = item_from_key (k);
+  return item->m_name;
 }
 
 const char *
-test_logical_location::get_internal_name () const
+test_logical_location_manager::get_internal_name (key k) const
 {
-  return m_name;
+  auto item = item_from_key (k);
+  return item->m_name;
 }
 
 enum logical_location_kind
-test_logical_location::get_kind () const
+test_logical_location_manager::get_kind (key k) const
 {
-  return m_kind;
+  auto item = item_from_key (k);
+  return item->m_kind;
 }
 
 label_text
-test_logical_location::get_name_for_path_output () const
+test_logical_location_manager::get_name_for_path_output (key k) const
 {
-  return label_text::borrow (m_name);
+  auto item = item_from_key (k);
+  return label_text::borrow (item->m_name);
+}
+
+logical_location
+test_logical_location_manager::
+logical_location_from_funcname (const char *funcname)
+{
+  const item *i = item_from_funcname (funcname);
+  return key::from_ptr (i);
+}
+
+const test_logical_location_manager::item *
+test_logical_location_manager::item_from_funcname (const char *funcname)
+{
+  if (!funcname)
+    return nullptr;
+
+  if (item **slot = m_name_to_item_map.get (funcname))
+    return *slot;
+
+  item *i = new item (LOGICAL_LOCATION_KIND_FUNCTION, funcname);
+  m_name_to_item_map.put (funcname, i);
+  return i;
+}
+
+/* Run all of the selftests within this file.  */
+
+void
+selftest_logical_location_cc_tests ()
+{
+  test_logical_location_manager mgr;
+
+  ASSERT_FALSE (mgr.logical_location_from_funcname (nullptr));
+
+  logical_location loc_foo = mgr.logical_location_from_funcname ("foo");
+  logical_location loc_bar = mgr.logical_location_from_funcname ("bar");
+
+  ASSERT_NE (loc_foo, loc_bar);
+
+  ASSERT_STREQ (mgr.get_short_name (loc_foo), "foo");
+  ASSERT_STREQ (mgr.get_short_name (loc_bar), "bar");
 }
 
 } // namespace selftest
index dea59d815405fd1d7dc9ba4d8f8aa340df471424..bee1419cbaf53049fbf25a91f6990a636cb98659 100644 (file)
@@ -30,24 +30,45 @@ along with GCC; see the file COPYING3.  If not see
 
 namespace selftest {
 
-/* Concrete subclass of logical_location for use in selftests.  */
+/* Concrete subclass of logical_location_manager for use in selftests.  */
 
-class test_logical_location : public logical_location
+class test_logical_location_manager : public logical_location_manager
 {
 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;
+  ~test_logical_location_manager ();
+
+  const char *get_short_name (key) const final override;
+  const char *get_name_with_scope (key) const final override;
+  const char *get_internal_name (key) const final override;
+  enum logical_location_kind get_kind (key) const final override;
+  label_text get_name_for_path_output (key) const final override;
+
+  logical_location
+  logical_location_from_funcname (const char *funcname);
+
+private:
+  struct item
+  {
+    item (enum logical_location_kind kind,
+         const char *name)
+    : m_kind (kind),
+      m_name (name)
+    {
+    }
+
+    enum logical_location_kind m_kind;
+    const char *m_name;
+  };
+
+  const item *
+  item_from_funcname (const char *funcname);
+
+  static const item *item_from_key (logical_location k)
+  {
+    return k.cast_to<const item *> ();
+  }
+
+  hash_map<nofree_string_hash, item *> m_name_to_item_map;
 };
 
 } // namespace selftest
index f705501ab59cd6522a45c37d67cf6ca43da27522..3c12e8a3ebd944cb454f690e97e747ccb2a23ab0 100644 (file)
@@ -92,6 +92,7 @@ selftest::run_tests ()
   digraph_cc_tests ();
   tristate_cc_tests ();
   ipa_modref_tree_cc_tests ();
+  selftest_logical_location_cc_tests ();
 
   /* Higher-level tests, or for components that other selftests don't
      rely on.  */
index 52ee0f1da7be9d8461636e8fdf49226461a7f13b..a0d2473424277af56e722f66de79e741ee0e8f8e 100644 (file)
@@ -257,6 +257,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 selftest_logical_location_cc_tests ();
 extern void simple_diagnostic_path_cc_tests ();
 extern void simplify_rtx_cc_tests ();
 extern void spellcheck_cc_tests ();
index 5af69b60fcef01b6795e96e8e878b6f8b0cbc272..b756cd58fbe64c9b4a4d294545658f64fd1d5bb2 100644 (file)
@@ -34,8 +34,11 @@ along with GCC; see the file COPYING3.  If not see
 
 /* class simple_diagnostic_path : public diagnostic_path.  */
 
-simple_diagnostic_path::simple_diagnostic_path (pretty_printer *event_pp)
-: m_event_pp (event_pp),
+simple_diagnostic_path::
+simple_diagnostic_path (const tree_logical_location_manager &logical_loc_mgr,
+                       pretty_printer *event_pp)
+: diagnostic_path (logical_loc_mgr),
+  m_event_pp (event_pp),
   m_localize_events (true)
 {
   add_thread ("main");
@@ -161,7 +164,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_logical_loc (fndecl),
+: m_loc (loc), m_fndecl (fndecl),
+  m_logical_loc (tree_logical_location_manager::key_from_tree (fndecl)),
   m_depth (depth), m_desc (xstrdup (desc)),
   m_connected_to_next_event (false),
   m_thread_id (thread_id)
@@ -188,11 +192,12 @@ namespace selftest {
 static void
 test_intraprocedural_path (pretty_printer *event_pp)
 {
+  tree_logical_location_manager mgr;
   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);
+  simple_diagnostic_path path (mgr, event_pp);
   path.add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "first %qs", "free");
   path.add_event (UNKNOWN_LOCATION, fndecl_foo, 0, "double %qs", "free");
 
index e9a97f2d3bb5aa183af3fa2bb8c53fed6cc20e13..d2b366e814856c49e7166db034dbe0f1a861382a 100644 (file)
@@ -40,12 +40,9 @@ class simple_diagnostic_event : public diagnostic_event
   location_t get_location () const final override { return m_loc; }
   int get_stack_depth () const final override { return m_depth; }
   void print_desc (pretty_printer &pp) const final override;
-  const logical_location *get_logical_location () const final override
+  logical_location get_logical_location () const final override
   {
-    if (m_fndecl)
-      return &m_logical_loc;
-    else
-      return nullptr;
+    return tree_logical_location_manager::key_from_tree (m_fndecl);
   }
   meaning get_meaning () const final override
   {
@@ -70,7 +67,7 @@ class simple_diagnostic_event : public diagnostic_event
  private:
   location_t m_loc;
   tree m_fndecl;
-  tree_logical_location m_logical_loc;
+  logical_location m_logical_loc;
   int m_depth;
   char *m_desc; // has been i18n-ed and formatted
   bool m_connected_to_next_event;
@@ -98,7 +95,8 @@ private:
 class simple_diagnostic_path : public diagnostic_path
 {
  public:
-  simple_diagnostic_path (pretty_printer *event_pp);
+  simple_diagnostic_path (const tree_logical_location_manager &logical_loc_mgr,
+                         pretty_printer *event_pp);
 
   unsigned num_events () const final override { return m_events.length (); }
   const diagnostic_event & get_event (int idx) const final override;
index 954538f962bbc6ecbdd8a7dd97db3472ab77c5b2..a7963fae6baa067cdb525118afdaa2fff02f735b 100644 (file)
@@ -147,7 +147,9 @@ example_1 ()
     {
       auto_diagnostic_group d;
       gcc_rich_location richloc (gimple_location (call_to_PyList_Append));
-      simple_diagnostic_path path (global_dc->get_reference_printer ());
+      tree_logical_location_manager logical_loc_mgr;
+      simple_diagnostic_path path (logical_loc_mgr,
+                                  global_dc->get_reference_printer ());
       diagnostic_event_id_t alloc_event_id
        = path.add_event (gimple_location (call_to_PyList_New),
                          example_a_fun->decl, 0,
@@ -214,7 +216,8 @@ class test_diagnostic_path : public simple_diagnostic_path
 {
  public:
   test_diagnostic_path (pretty_printer *event_pp)
-  : simple_diagnostic_path (event_pp)
+  : simple_diagnostic_path (m_logical_loc_mgr,
+                           event_pp)
   {
   }
   diagnostic_event_id_t
@@ -262,6 +265,9 @@ class test_diagnostic_path : public simple_diagnostic_path
     add_event (call_evloc.m_loc, call_evloc.m_fun->decl, caller_stack_depth,
               "calling %qs", callee);
   }
+
+private:
+  tree_logical_location_manager m_logical_loc_mgr;
 };
 
 static void
index 11701f5025b7b7cabd81da108fe5772c02578974..06a089425f005fe01d609fa942183b93316f9e2b 100644 (file)
@@ -123,12 +123,14 @@ public:
     return &m_version_info;
   }
 
-  const logical_location *get_current_logical_location () const final override
+  const logical_location_manager *get_logical_location_manager () const final override
   {
-    if (current_function_decl)
-      return &m_current_fndecl_logical_loc;
-    else
-      return NULL;
+    return &m_logical_location_manager;
+  }
+
+  logical_location_manager::key get_current_logical_location () const final override
+  {
+    return m_logical_location_manager.key_from_tree (current_function_decl);
   }
 
   const char *
@@ -159,7 +161,7 @@ public:
 
 private:
   compiler_version_info m_version_info;
-  current_fndecl_logical_location m_current_fndecl_logical_loc;
+  tree_logical_location_manager m_logical_location_manager;
 };
 
 /* Create a compiler_data_hooks (so that the class can be local
index 8f677a33f6b927740c7b8126afb5ad7822279467..854f9e839f8decf803fcad5b5a011d8e1d22468a 100644 (file)
@@ -1,4 +1,4 @@
-/* Subclasses of logical_location with knowledge of "tree".
+/* Subclass of logical_location_manager with knowledge of "tree".
    Copyright (C) 2022-2025 Free Software Foundation, Inc.
    Contributed by David Malcolm <dmalcolm@redhat.com>.
 
@@ -27,50 +27,43 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "intl.h"
 
-/* class compiler_logical_location : public logical_location.  */
-
-/* Get a string for DECL suitable for use by the SARIF logicalLocation
-   "name" property (SARIF v2.1.0 section 3.33.4).  */
+/* class tree_logical_location_manager : public logical_location_manager.  */
 
 const char *
-compiler_logical_location::get_short_name_for_tree (tree decl)
+tree_logical_location_manager::get_short_name (key k) const
 {
-  gcc_assert (decl);
-  return identifier_to_locale (lang_hooks.decl_printable_name (decl, 0));
+  tree node = tree_from_key (k);
+  gcc_assert (node);
+  return identifier_to_locale (lang_hooks.decl_printable_name (node, 0));
 }
 
-/* Get a string for DECL suitable for use by the SARIF logicalLocation
-   "fullyQualifiedName" property (SARIF v2.1.0 section 3.33.5).  */
-
 const char *
-compiler_logical_location::get_name_with_scope_for_tree (tree decl)
+tree_logical_location_manager::get_name_with_scope (key k) const
 {
-  gcc_assert (decl);
-  return identifier_to_locale (lang_hooks.decl_printable_name (decl, 1));
+  tree node = tree_from_key (k);
+  gcc_assert (node);
+  return identifier_to_locale (lang_hooks.decl_printable_name (node, 1));
 }
 
-/* Get a string for DECL suitable for use by the SARIF logicalLocation
-   "decoratedName" property (SARIF v2.1.0 section 3.33.6).  */
-
 const char *
-compiler_logical_location::get_internal_name_for_tree (tree decl)
+tree_logical_location_manager::get_internal_name (key k) const
 {
-  gcc_assert (decl);
-  if (HAS_DECL_ASSEMBLER_NAME_P (decl))
-    if (tree id = DECL_ASSEMBLER_NAME (decl))
+  tree node = tree_from_key (k);
+  gcc_assert (node);
+  if (HAS_DECL_ASSEMBLER_NAME_P (node))
+    if (tree id = DECL_ASSEMBLER_NAME (node))
       return IDENTIFIER_POINTER (id);
   return NULL;
 }
 
-/* Get what kind of SARIF logicalLocation DECL is (if any).  */
-
 enum logical_location_kind
-compiler_logical_location::get_kind_for_tree (tree decl)
+tree_logical_location_manager::get_kind (key k) const
 {
-  if (!decl)
+  tree node = tree_from_key (k);
+  if (!node)
     return LOGICAL_LOCATION_KIND_UNKNOWN;
 
-  switch (TREE_CODE (decl))
+  switch (TREE_CODE (node))
     {
     default:
       return LOGICAL_LOCATION_KIND_UNKNOWN;
@@ -84,90 +77,12 @@ compiler_logical_location::get_kind_for_tree (tree decl)
 }
 
 label_text
-compiler_logical_location::get_name_for_tree_for_path_output (tree decl)
+tree_logical_location_manager::get_name_for_path_output (key k) const
 {
-  gcc_assert (decl);
-  const char *n = DECL_NAME (decl)
-    ? identifier_to_locale (lang_hooks.decl_printable_name (decl, 2))
+  tree node = tree_from_key (k);
+  gcc_assert (node);
+  const char *n = DECL_NAME (node)
+    ? identifier_to_locale (lang_hooks.decl_printable_name (node, 2))
     : _("<anonymous>");
   return label_text::borrow (n);
 }
-
-/* class tree_logical_location : public compiler_logical_location.  */
-
-/* Implementation of the logical_location vfuncs, using m_decl.  */
-
-const char *
-tree_logical_location::get_short_name () const
-{
-  gcc_assert (m_decl);
-  return get_short_name_for_tree (m_decl);
-}
-
-const char *
-tree_logical_location::get_name_with_scope () const
-{
-  gcc_assert (m_decl);
-  return get_name_with_scope_for_tree (m_decl);
-}
-
-const char *
-tree_logical_location::get_internal_name () const
-{
-  gcc_assert (m_decl);
-  return get_internal_name_for_tree (m_decl);
-}
-
-enum logical_location_kind
-tree_logical_location::get_kind () const
-{
-  gcc_assert (m_decl);
-  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
-   current_function_decl.  */
-
-const char *
-current_fndecl_logical_location::get_short_name () const
-{
-  gcc_assert (current_function_decl);
-  return get_short_name_for_tree (current_function_decl);
-}
-
-const char *
-current_fndecl_logical_location::get_name_with_scope () const
-{
-  gcc_assert (current_function_decl);
-  return get_name_with_scope_for_tree (current_function_decl);
-}
-
-const char *
-current_fndecl_logical_location::get_internal_name () const
-{
-  gcc_assert (current_function_decl);
-  return get_internal_name_for_tree (current_function_decl);
-}
-
-enum logical_location_kind
-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);
-}
index 1e15beefffaf0fc197ed0b5a9cf34820b13462aa..bd9637a5d3d441eaf93727eea0ebb3031dc69307 100644 (file)
@@ -1,4 +1,4 @@
-/* Subclasses of logical_location with knowledge of "tree".
+/* Subclass of logical_location_manager with knowledge of "tree".
    Copyright (C) 2022-2025 Free Software Foundation, Inc.
    Contributed by David Malcolm <dmalcolm@redhat.com>.
 
@@ -23,48 +23,27 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "logical-location.h"
 
-/* Abstract subclass of logical_location, with knowledge of "tree", but
-   for no specific tree.  */
-
-class compiler_logical_location : public logical_location
-{
- protected:
-  static const char *get_short_name_for_tree (tree);
-  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
-   tree.  */
-
-class tree_logical_location : public compiler_logical_location
-{
-public:
-  tree_logical_location (tree decl) : m_decl (decl) {}
-
-  const char *get_short_name () const final override;
-  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;
-};
-
-/* Concrete subclass of logical_location, with reference to
-   current_function_decl.  */
-
-class current_fndecl_logical_location : public compiler_logical_location
+/* A subclass of logical_location_manager in which the keys are
+   "tree".
+   Note that there is no integration with the garbage collector,
+   and so logical_location instances can only be short-lived.  */
+class tree_logical_location_manager : public logical_location_manager
 {
 public:
-  const char *get_short_name () const final override;
-  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;
+  const char *get_short_name (key) const final override;
+  const char *get_name_with_scope (key) const final override;
+  const char *get_internal_name (key) const final override;
+  enum logical_location_kind get_kind (key) const final override;
+  label_text get_name_for_path_output (key) const final override;
+
+  static tree tree_from_key (logical_location k)
+  {
+    return const_cast<tree> (k.cast_to<const_tree> ());
+  }
+  static logical_location key_from_tree (tree node)
+  {
+    return logical_location::from_ptr (node);
+  }
 };
 
 #endif /* GCC_TREE_LOGICAL_LOCATION_H.  */