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)
{
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);
}
}
}
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/"
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
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)
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; }
}
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; }
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
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
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)
{}
/* 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);
}
}
+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. */
}
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;
#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;
/* 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. */
#include "diagnostic-buffer.h"
#include "json.h"
#include "selftest.h"
+#include "diagnostic-client-data-hooks.h"
#include "logical-location.h"
class json_output_format;
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));
}
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);
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,
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,
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;
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 ()));
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 ())),
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,
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 ();
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));
}
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
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). */
}
}
-/* 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
{
/* 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>
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
#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. */
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
};
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 */
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;
{
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),
friend struct event_range;
const diagnostic_path &m_path;
+ const logical_location_manager &m_logical_loc_mgr;
const label_text m_name;
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;
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; }
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>,
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);
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 ();
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)
{
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 ());
}
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;
}
}
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);
/* -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,
#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
/* 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;
/* 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
{
}
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
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
{
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 ();
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;
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; }
{
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
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;
};
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;
/* 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,
{
}
- 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
{
return false;
}
-private:
enum diagnostic_logical_location_kind_t m_kind;
const diagnostic_logical_location *m_parent;
owned_nullable_string m_short_name;
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:
{}
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)
private:
diagnostic_manager &m_mgr;
+ impl_logical_location_manager m_logical_location_manager;
};
class impl_client_version_info : public client_version_info
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)
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
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 ("")
{
}
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. */
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 ();
}
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 *
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, ':');
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. */
if (loc)
{
fprintf (out, "logical_location(kind=");
- switch (loc->get_external_kind ())
+ switch (loc->m_kind)
{
default:
gcc_unreachable ();
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, ")");
}
{
FAIL_IF_NULL (loc);
- return loc->get_external_kind ();
+ return loc->m_kind;
}
const diagnostic_logical_location *
{
FAIL_IF_NULL (loc);
- return loc->get_parent ();
+ return loc->m_parent;
}
const char *
{
FAIL_IF_NULL (loc);
- return loc->get_short_name ();
+ return loc->m_short_name.get_str ();
}
const char *
{
FAIL_IF_NULL (loc);
- return loc->get_fully_qualified_name ();
+ return loc->m_fully_qualified_name.get_str ();
}
const char *
{
FAIL_IF_NULL (loc);
- return loc->get_internal_name ();
+ return loc->m_decorated_name.get_str ();
}
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. */
/* 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");
}
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
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);
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);
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)
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 ();
{
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
{
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;
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;
#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
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
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. */
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 ();
/* 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");
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)
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");
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
{
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;
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;
{
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,
{
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
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
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 *
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
-/* 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>.
#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;
}
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);
-}
-/* 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>.
#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. */