aboutsummaryrefslogtreecommitdiff
path: root/gcc/libgdiagnostics.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/libgdiagnostics.cc')
-rw-r--r--gcc/libgdiagnostics.cc340
1 files changed, 338 insertions, 2 deletions
diff --git a/gcc/libgdiagnostics.cc b/gcc/libgdiagnostics.cc
index 74814c7..04812dc 100644
--- a/gcc/libgdiagnostics.cc
+++ b/gcc/libgdiagnostics.cc
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#define INCLUDE_MAP
+#define INCLUDE_STRING
#define INCLUDE_VECTOR
#include "system.h"
#include "coretypes.h"
@@ -32,9 +33,12 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-format-sarif.h"
#include "diagnostic-format-text.h"
#include "diagnostic-output-spec.h"
+#include "diagnostic-digraphs.h"
+#include "diagnostic-state-graphs.h"
#include "logical-location.h"
#include "edit-context.h"
#include "libgdiagnostics.h"
+#include "libgdiagnostics-private.h"
class owned_nullable_string
{
@@ -644,6 +648,9 @@ public:
return m_prev_diag_logical_loc;
}
+ void
+ take_global_graph (std::unique_ptr<diagnostic_graph> graph);
+
private:
void
ensure_linemap_for_file_and_line (const diagnostic_file *file,
@@ -743,17 +750,53 @@ private:
owned_nullable_string m_url;
};
+struct diagnostic_graph : public diagnostics::digraphs::digraph
+{
+ diagnostic_graph (diagnostic_manager &) {}
+
+ diagnostic_node *
+ add_node_with_id (std::string id,
+ diagnostic_node *parent_node);
+ diagnostic_edge *
+ add_edge_with_label (const char *id,
+ diagnostic_node &src_node,
+ diagnostic_node &dst_node,
+ const char *label);
+};
+
+struct diagnostic_node : public diagnostics::digraphs::node
+{
+ diagnostic_node (diagnostic_graph &g,
+ std::string id)
+ : node (g, std::move (id))
+ {
+ }
+};
+
+struct diagnostic_edge : public diagnostics::digraphs::edge
+{
+ diagnostic_edge (diagnostic_graph &g,
+ const char *id,
+ diagnostic_node &src_node,
+ diagnostic_node &dst_node)
+ : edge (g, id, src_node, dst_node)
+ {
+ }
+};
+
class libgdiagnostics_path_event : public diagnostic_event
{
public:
libgdiagnostics_path_event (const diagnostic_physical_location *physical_loc,
const diagnostic_logical_location *logical_loc,
unsigned stack_depth,
+ std::unique_ptr<diagnostic_graph> state_graph,
const char *gmsgid,
va_list *args)
: m_physical_loc (physical_loc),
m_logical_loc (logical_loc),
- m_stack_depth (stack_depth)
+ m_stack_depth (stack_depth),
+ m_state_graph (std::move (state_graph))
{
m_desc_uncolored = make_desc (gmsgid, args, false);
m_desc_colored = make_desc (gmsgid, args, true);
@@ -799,6 +842,15 @@ public:
return 0;
}
+ std::unique_ptr<diagnostics::digraphs::digraph>
+ maybe_make_diagnostic_state_graph (bool) const final override
+ {
+ if (!m_state_graph)
+ return nullptr;
+
+ return m_state_graph->clone ();
+ }
+
private:
static label_text make_desc (const char *gmsgid,
va_list *args,
@@ -824,6 +876,7 @@ private:
const diagnostic_physical_location *m_physical_loc;
const diagnostic_logical_location *m_logical_loc;
unsigned m_stack_depth;
+ std::unique_ptr<diagnostic_graph> m_state_graph;
label_text m_desc_uncolored;
label_text m_desc_colored;
};
@@ -855,6 +908,7 @@ struct diagnostic_execution_path : public diagnostic_path
add_event_va (const diagnostic_physical_location *physical_loc,
const diagnostic_logical_location *logical_loc,
unsigned stack_depth,
+ std::unique_ptr<diagnostic_graph> state_graph,
const char *gmsgid,
va_list *args)
{
@@ -862,6 +916,7 @@ struct diagnostic_execution_path : public diagnostic_path
(std::make_unique<libgdiagnostics_path_event> (physical_loc,
logical_loc,
stack_depth,
+ std::move (state_graph),
gmsgid,
args));
return m_events.size () - 1;
@@ -902,6 +957,27 @@ private:
std::vector<std::unique_ptr<libgdiagnostics_path_event>> m_events;
};
+class prebuilt_digraphs : public diagnostics::digraphs::lazy_digraphs
+{
+public:
+ using digraph = diagnostics::digraphs::digraph;
+
+ std::unique_ptr<std::vector<std::unique_ptr<digraph>>>
+ create_digraphs () const final override
+ {
+ return std::make_unique<std::vector<std::unique_ptr<digraph>>> (std::move (m_digraphs));
+ }
+
+ void
+ take_graph (std::unique_ptr<diagnostic_graph> graph)
+ {
+ m_digraphs.push_back (std::move (graph));
+ }
+
+private:
+ mutable std::vector<std::unique_ptr<digraph>> m_digraphs;
+};
+
/* This has to be a "struct" as it is exposed in the C API. */
struct diagnostic
@@ -914,7 +990,9 @@ public:
m_rich_loc (diag_mgr.get_line_table ()),
m_logical_loc (nullptr),
m_path (nullptr)
- {}
+ {
+ m_metadata.set_lazy_digraphs (&m_graphs);
+ }
diagnostic_manager &get_manager () const
{
@@ -990,12 +1068,25 @@ public:
m_rich_loc.set_path (path);
}
+ void
+ take_graph (std::unique_ptr<diagnostic_graph> graph)
+ {
+ m_graphs.take_graph (std::move (graph));
+ }
+
+ const prebuilt_digraphs &
+ get_graphs () const
+ {
+ return m_graphs;
+ }
+
private:
diagnostic_manager &m_diag_mgr;
enum diagnostic_level m_level;
impl_rich_location m_rich_loc;
const diagnostic_logical_location *m_logical_loc;
diagnostic_metadata m_metadata;
+ prebuilt_digraphs m_graphs;
std::vector<std::unique_ptr<range_label>> m_labels;
std::vector<std::unique_ptr<impl_rule>> m_rules;
std::unique_ptr<diagnostic_execution_path> m_path;
@@ -1248,6 +1339,29 @@ diagnostic_manager::new_execution_path ()
return new diagnostic_execution_path (*mgr);
}
+void
+diagnostic_manager::take_global_graph (std::unique_ptr<diagnostic_graph> graph)
+{
+ class prebuilt_lazy_digraph : public diagnostics::digraphs::lazy_digraph
+ {
+ public:
+ prebuilt_lazy_digraph (std::unique_ptr<diagnostic_graph> graph)
+ : m_graph (std::move (graph))
+ {
+ }
+
+ std::unique_ptr<diagnostics::digraphs::digraph>
+ create_digraph () const final override
+ {
+ return std::move (m_graph);
+ }
+
+ private:
+ mutable std::unique_ptr<diagnostic_graph> m_graph;
+ };
+
+ m_dc.report_global_digraph (prebuilt_lazy_digraph (std::move (graph)));
+}
/* Error-checking at the API boundary. */
#define FAIL_IF_NULL(PTR_ARG) \
@@ -1876,6 +1990,7 @@ diagnostic_execution_path_add_event (diagnostic_execution_path *path,
diagnostic_event_id_t result = path->add_event_va (physical_loc,
logical_loc,
stack_depth,
+ nullptr,
gmsgid, &args);
va_end (args);
@@ -1898,6 +2013,7 @@ diagnostic_execution_path_add_event_va (diagnostic_execution_path *path,
diagnostic_event_id_t result = path->add_event_va (physical_loc,
logical_loc,
stack_depth,
+ nullptr,
gmsgid, args);
return as_diagnostic_event_id (result);
}
@@ -2048,3 +2164,223 @@ diagnostic_manager_set_analysis_target (diagnostic_manager *mgr,
mgr->get_dc ().set_main_input_filename (file->get_name ());
}
+
+// struct diagnostic_graph : public diagnostics::digraphs::graph<foo_traits>
+
+diagnostic_node *
+diagnostic_graph::add_node_with_id (std::string id,
+ diagnostic_node *parent_node)
+{
+ auto node_up = std::make_unique<diagnostic_node> (*this, std::move (id));
+ diagnostic_node *new_node = node_up.get ();
+ if (parent_node)
+ parent_node->add_child (std::move (node_up));
+ else
+ add_node (std::move (node_up));
+ return new_node;
+}
+
+diagnostic_edge *
+diagnostic_graph::add_edge_with_label (const char *id,
+ diagnostic_node &src_node,
+ diagnostic_node &dst_node,
+ const char *label)
+{
+ auto edge_up
+ = std::make_unique<diagnostic_edge> (*this, id,
+ src_node, dst_node);
+ diagnostic_edge *new_edge = edge_up.get ();
+ if (label)
+ new_edge->set_label (label);
+ add_edge (std::move (edge_up));
+ return new_edge;
+}
+
+/* Public entrypoint. */
+
+diagnostic_graph *
+diagnostic_manager_new_graph (diagnostic_manager *manager)
+{
+ FAIL_IF_NULL (manager);
+
+ return new diagnostic_graph (*manager);
+}
+
+/* Public entrypoint. */
+
+void
+diagnostic_manager_take_global_graph (diagnostic_manager *manager,
+ diagnostic_graph *graph)
+{
+ FAIL_IF_NULL (manager);
+ FAIL_IF_NULL (graph);
+
+ manager->take_global_graph (std::unique_ptr<diagnostic_graph> (graph));
+}
+
+void
+diagnostic_take_graph (diagnostic *diag,
+ diagnostic_graph *graph)
+{
+ FAIL_IF_NULL (diag);
+ FAIL_IF_NULL (graph);
+
+ diag->take_graph (std::unique_ptr<diagnostic_graph> (graph));
+}
+
+/* Public entrypoint. */
+
+void
+diagnostic_graph_release (diagnostic_graph *graph)
+{
+ delete graph;
+}
+
+/* Public entrypoint. */
+
+void
+diagnostic_graph_set_description (diagnostic_graph *graph,
+ const char *desc)
+{
+ FAIL_IF_NULL (graph);
+
+ graph->set_description (desc);
+}
+
+diagnostic_node *
+diagnostic_graph_add_node (diagnostic_graph *graph,
+ const char *id,
+ diagnostic_node *parent_node)
+{
+ FAIL_IF_NULL (graph);
+ FAIL_IF_NULL (id);
+
+ return graph->add_node_with_id (id, parent_node);
+}
+
+/* Public entrypoint. */
+
+diagnostic_edge *
+diagnostic_graph_add_edge (diagnostic_graph *graph,
+ const char *id,
+ diagnostic_node *src_node,
+ diagnostic_node *dst_node,
+ const char *label)
+{
+ FAIL_IF_NULL (graph);
+ FAIL_IF_NULL (src_node);
+ FAIL_IF_NULL (dst_node);
+
+ return graph->add_edge_with_label (id, *src_node, *dst_node, label);
+}
+
+/* Public entrypoint. */
+
+diagnostic_node *
+diagnostic_graph_get_node_by_id (diagnostic_graph *graph,
+ const char *id)
+{
+ FAIL_IF_NULL (graph);
+ FAIL_IF_NULL (id);
+
+ return static_cast<diagnostic_node *> (graph->get_node_by_id (id));
+}
+
+/* Public entrypoint. */
+
+diagnostic_edge *
+diagnostic_graph_get_edge_by_id (diagnostic_graph *graph,
+ const char *id)
+{
+ FAIL_IF_NULL (graph);
+ FAIL_IF_NULL (id);
+
+ return static_cast<diagnostic_edge *> (graph->get_edge_by_id (id));
+}
+
+/* Public entrypoint. */
+
+void
+diagnostic_node_set_location (diagnostic_node *node,
+ const diagnostic_physical_location *loc)
+{
+ FAIL_IF_NULL (node);
+
+ node->set_physical_loc (loc ? loc->m_inner : UNKNOWN_LOCATION);
+}
+
+/* Public entrypoint. */
+
+void
+diagnostic_node_set_label (diagnostic_node *node,
+ const char *label)
+{
+ FAIL_IF_NULL (node);
+
+ node->set_label (label);
+}
+
+void
+diagnostic_node_set_logical_location (diagnostic_node *node,
+ const diagnostic_logical_location *logical_loc)
+{
+ FAIL_IF_NULL (node);
+
+ node->set_logical_loc
+ (impl_logical_location_manager::key_from_ptr (logical_loc));
+}
+
+/* Private entrypoint. */
+
+diagnostic_event_id
+private_diagnostic_execution_path_add_event_2 (diagnostic_execution_path *path,
+ const diagnostic_physical_location *physical_loc,
+ const diagnostic_logical_location *logical_loc,
+ unsigned stack_depth,
+ diagnostic_graph *state_graph,
+ const char *gmsgid, ...)
+
+{
+ FAIL_IF_NULL (path);
+ FAIL_IF_NULL (gmsgid);
+
+ va_list args;
+ va_start (args, gmsgid);
+ diagnostic_event_id_t result
+ = path->add_event_va (physical_loc,
+ logical_loc,
+ stack_depth,
+ std::unique_ptr <diagnostic_graph> (state_graph),
+ gmsgid, &args);
+ va_end (args);
+
+ return as_diagnostic_event_id (result);
+
+}
+
+/* Private entrypoint. */
+
+void
+private_diagnostic_graph_set_property_bag (diagnostic_graph &graph,
+ std::unique_ptr<json::object> properties)
+{
+ graph.set_property_bag (std::move (properties));
+}
+
+/* Private entrypoint. */
+
+void
+private_diagnostic_node_set_property_bag (diagnostic_node &node,
+ std::unique_ptr<json::object> properties)
+{
+ node.set_property_bag (std::move (properties));
+}
+
+/* Private entrypoint. */
+
+void
+private_diagnostic_edge_set_property_bag (diagnostic_edge &edge,
+ std::unique_ptr<json::object> properties)
+{
+ edge.set_property_bag (std::move (properties));
+}