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. 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 r16-413-g8ab6899dce92e6. 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. --- gcc/analyzer/checker-event.cc | 25 ++- gcc/analyzer/checker-event.h | 15 +- gcc/analyzer/checker-path.h | 5 +- gcc/analyzer/diagnostic-manager.cc | 12 +- gcc/analyzer/diagnostic-manager.h | 3 + gcc/diagnostic-client-data-hooks.h | 11 +- gcc/diagnostic-format-json.cc | 13 +- gcc/diagnostic-format-sarif.cc | 83 +++++-- gcc/diagnostic-format-sarif.h | 12 +- gcc/diagnostic-path.cc | 32 ++- gcc/diagnostic-path.h | 22 +- gcc/diagnostic.cc | 14 +- gcc/diagnostic.h | 5 +- gcc/lazy-diagnostic-path.cc | 8 +- gcc/lazy-diagnostic-path.h | 6 + gcc/libgdiagnostics.cc | 210 +++++++++++------- gcc/logical-location.h | 114 ++++++++-- gcc/selftest-diagnostic-path.cc | 39 ++-- gcc/selftest-diagnostic-path.h | 22 +- gcc/selftest-logical-location.cc | 77 +++++-- gcc/selftest-logical-location.h | 51 +++-- gcc/selftest-run-tests.cc | 1 + gcc/selftest.h | 1 + gcc/simple-diagnostic-path.cc | 13 +- gcc/simple-diagnostic-path.h | 12 +- .../plugin/diagnostic_plugin_test_paths.cc | 10 +- gcc/tree-diagnostic-client-data-hooks.cc | 14 +- gcc/tree-logical-location.cc | 133 ++--------- gcc/tree-logical-location.h | 61 ++--- 29 files changed, 624 insertions(+), 400 deletions(-) diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc index 958cdbf394d0..e041778e8d19 100644 --- a/gcc/analyzer/checker-event.cc +++ b/gcc/analyzer/checker-event.cc @@ -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) diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h index f3ab89984183..2f26b8daaa6a 100644 --- a/gcc/analyzer/checker-event.h +++ b/gcc/analyzer/checker-event.h @@ -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 diff --git a/gcc/analyzer/checker-path.h b/gcc/analyzer/checker-path.h index dfc782d45205..80c975c6a745 100644 --- a/gcc/analyzer/checker-path.h +++ b/gcc/analyzer/checker-path.h @@ -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) {} diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 7575b16c86cd..e5d1a2571a04 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -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. */ diff --git a/gcc/analyzer/diagnostic-manager.h b/gcc/analyzer/diagnostic-manager.h index b62fc7a258e5..aa0bd79faedb 100644 --- a/gcc/analyzer/diagnostic-manager.h +++ b/gcc/analyzer/diagnostic-manager.h @@ -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; diff --git a/gcc/diagnostic-client-data-hooks.h b/gcc/diagnostic-client-data-hooks.h index 0057b803bc9e..990917278198 100644 --- a/gcc/diagnostic-client-data-hooks.h +++ b/gcc/diagnostic-client-data-hooks.h @@ -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. */ diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc index c28804e78fbf..205678dbe041 100644 --- a/gcc/diagnostic-format-json.cc +++ b/gcc/diagnostic-format-json.cc @@ -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)); } diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc index bc6abdff5e4e..e9a387291421 100644 --- a/gcc/diagnostic-format-sarif.cc +++ b/gcc/diagnostic-format-sarif.cc @@ -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 diff --git a/gcc/diagnostic-format-sarif.h b/gcc/diagnostic-format-sarif.h index 644625747cc8..354f18a6c690 100644 --- a/gcc/diagnostic-format-sarif.h +++ b/gcc/diagnostic-format-sarif.h @@ -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 */ diff --git a/gcc/diagnostic-path.cc b/gcc/diagnostic-path.cc index d618c3714e38..9340e4e3a297 100644 --- a/gcc/diagnostic-path.cc +++ b/gcc/diagnostic-path.cc @@ -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, diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h index 878d6ff5ae69..4419139413bd 100644 --- a/gcc/diagnostic-path.h +++ b/gcc/diagnostic-path.h @@ -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 diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index c3ea1b34d2f2..b43fc907ed13 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -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 (); diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 88288d0df262..00d7812248a4 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -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; } diff --git a/gcc/lazy-diagnostic-path.cc b/gcc/lazy-diagnostic-path.cc index 1474f70390b5..37c8e25bd7c7 100644 --- a/gcc/lazy-diagnostic-path.cc +++ b/gcc/lazy-diagnostic-path.cc @@ -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; }; diff --git a/gcc/lazy-diagnostic-path.h b/gcc/lazy-diagnostic-path.h index 01564567155c..9609cab02953 100644 --- a/gcc/lazy-diagnostic-path.h +++ b/gcc/lazy-diagnostic-path.h @@ -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; diff --git a/gcc/libgdiagnostics.cc b/gcc/libgdiagnostics.cc index 8a4a159ecb74..c085cd8e941c 100644 --- a/gcc/libgdiagnostics.cc +++ b/gcc/libgdiagnostics.cc @@ -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 (); } diff --git a/gcc/logical-location.h b/gcc/logical-location.h index 000335cadfad..3308e2d56640 100644 --- a/gcc/logical-location.h +++ b/gcc/logical-location.h @@ -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. */ diff --git a/gcc/selftest-diagnostic-path.cc b/gcc/selftest-diagnostic-path.cc index 0e80eeabebe1..04372e7b47b6 100644 --- a/gcc/selftest-diagnostic-path.cc +++ b/gcc/selftest-diagnostic-path.cc @@ -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) diff --git a/gcc/selftest-diagnostic-path.h b/gcc/selftest-diagnostic-path.h index e20986c58b57..8829943556e0 100644 --- a/gcc/selftest-diagnostic-path.h +++ b/gcc/selftest-diagnostic-path.h @@ -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; diff --git a/gcc/selftest-logical-location.cc b/gcc/selftest-logical-location.cc index 6c1c757ca53c..5f33b48c849f 100644 --- a/gcc/selftest-logical-location.cc +++ b/gcc/selftest-logical-location.cc @@ -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 diff --git a/gcc/selftest-logical-location.h b/gcc/selftest-logical-location.h index dea59d815405..bee1419cbaf5 100644 --- a/gcc/selftest-logical-location.h +++ b/gcc/selftest-logical-location.h @@ -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 diff --git a/gcc/selftest-run-tests.cc b/gcc/selftest-run-tests.cc index f705501ab59c..3c12e8a3ebd9 100644 --- a/gcc/selftest-run-tests.cc +++ b/gcc/selftest-run-tests.cc @@ -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. */ diff --git a/gcc/selftest.h b/gcc/selftest.h index 52ee0f1da7be..a0d247342427 100644 --- a/gcc/selftest.h +++ b/gcc/selftest.h @@ -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 (); diff --git a/gcc/simple-diagnostic-path.cc b/gcc/simple-diagnostic-path.cc index 5af69b60fcef..b756cd58fbe6 100644 --- a/gcc/simple-diagnostic-path.cc +++ b/gcc/simple-diagnostic-path.cc @@ -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"); diff --git a/gcc/simple-diagnostic-path.h b/gcc/simple-diagnostic-path.h index e9a97f2d3bb5..d2b366e81485 100644 --- a/gcc/simple-diagnostic-path.h +++ b/gcc/simple-diagnostic-path.h @@ -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; diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc index 954538f962bb..a7963fae6baa 100644 --- a/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc +++ b/gcc/testsuite/gcc.dg/plugin/diagnostic_plugin_test_paths.cc @@ -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 diff --git a/gcc/tree-diagnostic-client-data-hooks.cc b/gcc/tree-diagnostic-client-data-hooks.cc index 11701f5025b7..06a089425f00 100644 --- a/gcc/tree-diagnostic-client-data-hooks.cc +++ b/gcc/tree-diagnostic-client-data-hooks.cc @@ -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 diff --git a/gcc/tree-logical-location.cc b/gcc/tree-logical-location.cc index 8f677a33f6b9..854f9e839f8d 100644 --- a/gcc/tree-logical-location.cc +++ b/gcc/tree-logical-location.cc @@ -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 <dmalc...@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); -} diff --git a/gcc/tree-logical-location.h b/gcc/tree-logical-location.h index 1e15beefffaf..bd9637a5d3d4 100644 --- a/gcc/tree-logical-location.h +++ b/gcc/tree-logical-location.h @@ -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 <dmalc...@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. */ -- 2.26.3