diff options
Diffstat (limited to 'gcc/libgdiagnostics.cc')
-rw-r--r-- | gcc/libgdiagnostics.cc | 1283 |
1 files changed, 1133 insertions, 150 deletions
diff --git a/gcc/libgdiagnostics.cc b/gcc/libgdiagnostics.cc index 74814c7..784e281 100644 --- a/gcc/libgdiagnostics.cc +++ b/gcc/libgdiagnostics.cc @@ -19,22 +19,30 @@ 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" #include "intl.h" #include "diagnostic.h" -#include "diagnostic-color.h" -#include "diagnostic-url.h" -#include "diagnostic-metadata.h" -#include "diagnostic-path.h" -#include "diagnostic-client-data-hooks.h" -#include "diagnostic-format-sarif.h" -#include "diagnostic-format-text.h" -#include "diagnostic-output-spec.h" -#include "logical-location.h" -#include "edit-context.h" +#include "diagnostics/color.h" +#include "diagnostics/file-cache.h" +#include "diagnostics/url.h" +#include "diagnostics/metadata.h" +#include "diagnostics/paths.h" +#include "diagnostics/client-data-hooks.h" +#include "diagnostics/sarif-sink.h" +#include "diagnostics/text-sink.h" +#include "diagnostics/output-spec.h" +#include "diagnostics/digraphs.h" +#include "diagnostics/state-graphs.h" +#include "diagnostics/logical-locations.h" +#include "diagnostics/changes.h" #include "libgdiagnostics.h" +#include "libgdiagnostics-private.h" +#include "pretty-print-format-impl.h" +#include "pretty-print-markup.h" +#include "auto-obstack.h" class owned_nullable_string { @@ -203,7 +211,7 @@ struct diagnostic_logical_location }; static diagnostic_event_id -as_diagnostic_event_id (diagnostic_event_id_t id) +as_diagnostic_event_id (diagnostics::paths::event_id_t id) { return id.zero_based (); } @@ -225,7 +233,7 @@ public: FILE *dst_stream, enum diagnostic_colorize colorize); - diagnostic_source_printing_options &get_source_printing_options () + diagnostics::source_printing_options &get_source_printing_options () { return m_source_printing; } @@ -234,12 +242,103 @@ public: set_colorize (enum diagnostic_colorize colorize); static void - text_starter (diagnostic_text_output_format &text_output, - const diagnostic_info *diagnostic); + text_starter (diagnostics::text_sink &text_output, + const diagnostics::diagnostic_info *diagnostic); private: - diagnostic_text_output_format *m_inner_sink; // borrowed from dc - diagnostic_source_printing_options m_source_printing; + diagnostics::text_sink *m_inner_sink; // borrowed from dc + diagnostics::source_printing_options m_source_printing; +}; + +/* A token_printer that makes a deep copy of the pp_token_list + into another obstack. */ + +class copying_token_printer : public token_printer +{ +public: + copying_token_printer (obstack &dst_obstack, + pp_token_list &dst_token_list) + : m_dst_obstack (dst_obstack), + m_dst_token_list (dst_token_list) + { + } + + void + print_tokens (pretty_printer *, + const pp_token_list &tokens) final override + { + for (auto iter = tokens.m_first; iter; iter = iter->m_next) + switch (iter->m_kind) + { + default: + gcc_unreachable (); + + case pp_token::kind::text: + { + const pp_token_text *sub = as_a <const pp_token_text *> (iter); + /* Copy the text, with null terminator. */ + obstack_grow (&m_dst_obstack, sub->m_value.get (), + strlen (sub->m_value.get ()) + 1); + m_dst_token_list.push_back_text + (label_text::borrow (XOBFINISH (&m_dst_obstack, + const char *))); + } + break; + + case pp_token::kind::begin_color: + { + pp_token_begin_color *sub = as_a <pp_token_begin_color *> (iter); + /* Copy the color, with null terminator. */ + obstack_grow (&m_dst_obstack, sub->m_value.get (), + strlen (sub->m_value.get ()) + 1); + m_dst_token_list.push_back<pp_token_begin_color> + (label_text::borrow (XOBFINISH (&m_dst_obstack, + const char *))); + } + break; + case pp_token::kind::end_color: + m_dst_token_list.push_back<pp_token_end_color> (); + break; + + case pp_token::kind::begin_quote: + m_dst_token_list.push_back<pp_token_begin_quote> (); + break; + case pp_token::kind::end_quote: + m_dst_token_list.push_back<pp_token_end_quote> (); + break; + + case pp_token::kind::begin_url: + { + pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter); + /* Copy the URL, with null terminator. */ + obstack_grow (&m_dst_obstack, sub->m_value.get (), + strlen (sub->m_value.get ()) + 1); + m_dst_token_list.push_back<pp_token_begin_url> + (label_text::borrow (XOBFINISH (&m_dst_obstack, + const char *))); + } + break; + case pp_token::kind::end_url: + m_dst_token_list.push_back<pp_token_end_url> (); + break; + + case pp_token::kind::event_id: + { + pp_token_event_id *sub = as_a <pp_token_event_id *> (iter); + m_dst_token_list.push_back<pp_token_event_id> (sub->m_event_id); + } + break; + + case pp_token::kind::custom_data: + /* These should have been eliminated by replace_custom_tokens. */ + gcc_unreachable (); + break; + } + } + +private: + obstack &m_dst_obstack; + pp_token_list &m_dst_token_list; }; class sarif_sink : public sink @@ -248,7 +347,108 @@ public: sarif_sink (diagnostic_manager &mgr, FILE *dst_stream, const diagnostic_file *main_input_file, - const sarif_generation_options &sarif_gen_opts); + const diagnostics::sarif_generation_options &sarif_gen_opts); +}; + +struct diagnostic_message_buffer +{ + diagnostic_message_buffer () + : m_tokens (m_obstack) + { + } + + diagnostic_message_buffer (const char *gmsgid, + va_list *args) + : m_tokens (m_obstack) + { + text_info text (gmsgid, args, errno); + pretty_printer pp; + pp.set_output_stream (nullptr); + copying_token_printer tok_printer (m_obstack, m_tokens); + pp.set_token_printer (&tok_printer); + pp_format (&pp, &text); + pp_output_formatted_text (&pp, nullptr); + } + + + std::string to_string () const; + + auto_obstack m_obstack; + pp_token_list m_tokens; +}; + +/* A pp_element subclass that replays the saved tokens in a + diagnostic_message_buffer. */ + +class pp_element_message_buffer : public pp_element +{ +public: + pp_element_message_buffer (diagnostic_message_buffer &msg_buf) + : m_msg_buf (msg_buf) + { + } + + void add_to_phase_2 (pp_markup::context &ctxt) final override + { + /* Convert to text, possibly with colorization, URLs, etc. */ + for (auto iter = m_msg_buf.m_tokens.m_first; iter; iter = iter->m_next) + switch (iter->m_kind) + { + default: + gcc_unreachable (); + + case pp_token::kind::text: + { + pp_token_text *sub = as_a <pp_token_text *> (iter); + pp_string (&ctxt.m_pp, sub->m_value.get ()); + ctxt.push_back_any_text (); + } + break; + + case pp_token::kind::begin_color: + { + pp_token_begin_color *sub = as_a <pp_token_begin_color *> (iter); + ctxt.begin_highlight_color (sub->m_value.get ()); + } + break; + case pp_token::kind::end_color: + ctxt.end_highlight_color (); + break; + + case pp_token::kind::begin_quote: + ctxt.begin_quote (); + break; + case pp_token::kind::end_quote: + ctxt.end_quote (); + break; + + case pp_token::kind::begin_url: + { + pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter); + ctxt.begin_url (sub->m_value.get ()); + } + break; + case pp_token::kind::end_url: + ctxt.end_url (); + break; + + case pp_token::kind::event_id: + { + pp_token_event_id *sub = as_a <pp_token_event_id *> (iter); + gcc_assert (sub->m_event_id.known_p ()); + ctxt.add_event_id (sub->m_event_id); + } + break; + + case pp_token::kind::custom_data: + /* We don't have a way of handling custom_data tokens here. */ + gcc_unreachable (); + break; + } + } + +private: + diagnostic_message_buffer &m_msg_buf; }; /* Helper for the linemap code. */ @@ -259,19 +459,23 @@ round_alloc_size (size_t s) return s; } -class impl_logical_location_manager : public logical_location_manager +class impl_logical_location_manager + : public diagnostics::logical_locations::manager { public: + using key = diagnostics::logical_locations::key; + using kind = diagnostics::logical_locations::kind; + static const diagnostic_logical_location * - ptr_from_key (logical_location k) + ptr_from_key (key k) { return k.cast_to<const diagnostic_logical_location *> (); } - static logical_location + static key key_from_ptr (const diagnostic_logical_location *ptr) { - return logical_location::from_ptr (ptr); + return key::from_ptr (ptr); } const char *get_short_name (key k) const final override @@ -298,7 +502,7 @@ public: return nullptr; } - enum logical_location_kind get_kind (key k) const final override + kind get_kind (key k) const final override { auto loc = ptr_from_key (k); gcc_assert (loc); @@ -308,45 +512,45 @@ public: gcc_unreachable (); case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION: - return logical_location_kind::function; + return kind::function; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER: - return logical_location_kind::member; + return kind::member; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE: - return logical_location_kind::module_; + return kind::module_; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE: - return logical_location_kind::namespace_; + return kind::namespace_; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE: - return logical_location_kind::type; + return kind::type; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE: - return logical_location_kind::return_type; + return kind::return_type; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER: - return logical_location_kind::parameter; + return kind::parameter; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE: - return logical_location_kind::variable; + return kind::variable; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT: - return logical_location_kind::element; + return kind::element; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE: - return logical_location_kind::attribute; + return kind::attribute; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT: - return logical_location_kind::text; + return kind::text; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT: - return logical_location_kind::comment; + return kind::comment; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION: - return logical_location_kind::processing_instruction; + return kind::processing_instruction; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD: - return logical_location_kind::dtd; + return kind::dtd; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION: - return logical_location_kind::declaration; + return kind::declaration; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT: - return logical_location_kind::object; + return kind::object; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY: - return logical_location_kind::array; + return kind::array; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY: - return logical_location_kind::property; + return kind::property; case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE: - return logical_location_kind::value; + return kind::value; } } @@ -365,25 +569,28 @@ public: } }; -class impl_diagnostic_client_data_hooks : public diagnostic_client_data_hooks +class impl_diagnostic_client_data_hooks : public diagnostics::client_data_hooks { public: impl_diagnostic_client_data_hooks (diagnostic_manager &mgr) : m_mgr (mgr) {} - const client_version_info *get_any_version_info () const final override; + const diagnostics::client_version_info * + get_any_version_info () const final override; - const logical_location_manager * + const diagnostics::logical_locations::manager * get_logical_location_manager () const final override { return &m_logical_location_manager; } - logical_location get_current_logical_location () const final override; + diagnostics::logical_locations::key + 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) + void + add_sarif_invocation_properties (diagnostics::sarif_object &invocation_obj) const final override; private: @@ -391,7 +598,7 @@ private: impl_logical_location_manager m_logical_location_manager; }; -class impl_client_version_info : public client_version_info +class impl_client_version_info : public diagnostics::client_version_info { public: const char *get_tool_name () const final override @@ -432,7 +639,8 @@ struct diagnostic_manager public: diagnostic_manager () : m_current_diag (nullptr), - m_prev_diag_logical_loc (nullptr) + m_prev_diag_logical_loc (nullptr), + m_debug_physical_locations (false) { linemap_init (&m_line_table, BUILTINS_LOCATION); m_line_table.m_reallocator = xrealloc; @@ -450,23 +658,26 @@ public: m_dc.set_show_cwe (true); m_dc.set_show_rules (true); m_dc.m_show_column = true; - m_dc.m_source_printing.enabled = true; - m_dc.m_source_printing.colorize_source_p = true; + auto &source_printing_opts = m_dc.get_source_printing_options (); + source_printing_opts.enabled = true; + source_printing_opts.colorize_source_p = true; /* We don't currently expose a way for clients to manipulate the following. */ - m_dc.m_source_printing.show_labels_p = true; - m_dc.m_source_printing.show_line_numbers_p = true; - m_dc.m_source_printing.min_margin_width = 6; + source_printing_opts.show_labels_p = true; + source_printing_opts.show_line_numbers_p = true; + source_printing_opts.min_margin_width = 6; m_dc.set_path_format (DPF_INLINE_EVENTS); m_dc.m_client_aux_data = this; m_dc.set_client_data_hooks (std::make_unique<impl_diagnostic_client_data_hooks> (*this)); - diagnostic_text_starter (&m_dc) = diagnostic_text_sink::text_starter; + diagnostics::text_starter (&m_dc) = diagnostic_text_sink::text_starter; - m_edit_context = std::make_unique <edit_context> (m_dc.get_file_cache ()); + m_change_set + = std::make_unique <diagnostics::changes::change_set> + (m_dc.get_file_cache ()); } ~diagnostic_manager () @@ -487,9 +698,9 @@ public: } line_maps *get_line_table () { return &m_line_table; } - diagnostic_context &get_dc () { return m_dc; } + diagnostics::context &get_dc () { return m_dc; } - const logical_location_manager & + const diagnostics::logical_locations::manager & get_logical_location_manager () const { auto mgr = m_dc.get_logical_location_manager (); @@ -504,9 +715,15 @@ public: m_sinks.push_back (std::move (sink)); } - void emit (diagnostic &diag, const char *msgid, va_list *args) + void emit_va (diagnostic &diag, const char *msgid, va_list *args) LIBGDIAGNOSTICS_PARAM_GCC_FORMAT_STRING(3, 0); + void emit (diagnostic &diag, const char *msgid, ...) + LIBGDIAGNOSTICS_PARAM_GCC_FORMAT_STRING(3, 4); + + void emit_msg_buf (diagnostic &diag, + diagnostic_message_buffer &msg_buf); + diagnostic_file * new_file (const char *name, const char *sarif_source_language) @@ -531,6 +748,9 @@ public: new_location_from_file_and_line (const diagnostic_file *file, diagnostic_line_num_t line_num) { + if (m_debug_physical_locations) + fprintf (stderr, "new_location_from_file_and_line (%s, %i)", + file->get_name (), line_num); ensure_linemap_for_file_and_line (file, line_num); location_t loc = linemap_position_for_column (&m_line_table, 0); return new_location (loc); @@ -541,6 +761,9 @@ public: diagnostic_line_num_t line_num, diagnostic_column_num_t column_num) { + if (m_debug_physical_locations) + fprintf (stderr, "new_location_from_file_line_column (%s, %i, %i)", + file->get_name (), line_num, column_num); ensure_linemap_for_file_and_line (file, line_num); location_t loc = linemap_position_for_column (&m_line_table, column_num); return new_location (loc); @@ -551,12 +774,23 @@ public: const diagnostic_physical_location *loc_start, const diagnostic_physical_location *loc_end) { + if (m_debug_physical_locations) + fprintf (stderr, "new_location_from_range (%p, %p, %p)", + (const void *)loc_caret, + (const void *)loc_start, + (const void *)loc_end); return new_location (m_line_table.make_location (as_location_t (loc_caret), as_location_t (loc_start), as_location_t (loc_end))); } + void + set_debug_physical_locations (bool value) + { + m_debug_physical_locations = value; + } + const diagnostic_logical_location * new_logical_location (enum diagnostic_logical_location_kind_t kind, const diagnostic_logical_location *parent, @@ -613,7 +847,8 @@ public: const diagnostic *get_current_diag () { return m_current_diag; } - const client_version_info *get_client_version_info () const + const diagnostics::client_version_info * + get_client_version_info () const { return &m_client_version_info; } @@ -644,6 +879,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, @@ -654,11 +892,17 @@ private: linemap_add (&m_line_table, LC_ENTER, false, file->get_name (), 0); else { - line_map *map - = const_cast<line_map *> - (linemap_add (&m_line_table, LC_RENAME_VERBATIM, false, - file->get_name (), 0)); - ((line_map_ordinary *)map)->included_from = UNKNOWN_LOCATION; + line_map_ordinary *last_map + = LINEMAPS_LAST_ORDINARY_MAP (&m_line_table); + if (last_map->to_file != file->get_name () + || linenum < last_map->to_line) + { + line_map *map + = const_cast<line_map *> + (linemap_add (&m_line_table, LC_RENAME_VERBATIM, false, + file->get_name (), 0)); + ((line_map_ordinary *)map)->included_from = UNKNOWN_LOCATION; + } } linemap_line_start (&m_line_table, linenum, 100); } @@ -668,15 +912,23 @@ private: { if (loc == UNKNOWN_LOCATION) return nullptr; + if (m_debug_physical_locations) + fprintf (stderr, ": new_location (%lx)", loc); if (diagnostic_physical_location **slot = m_location_t_map.get (loc)) - return *slot; + { + if (m_debug_physical_locations) + fprintf (stderr, ": cache hit: %p\n", (const void *)*slot); + return *slot; + } diagnostic_physical_location *phys_loc = new diagnostic_physical_location (this, loc); m_location_t_map.put (loc, phys_loc); + if (m_debug_physical_locations) + fprintf (stderr, ": cache miss: %p\n", (const void *)phys_loc); return phys_loc; } - diagnostic_context m_dc; + diagnostics::context m_dc; line_maps m_line_table; impl_client_version_info m_client_version_info; std::vector<std::unique_ptr<sink>> m_sinks; @@ -688,7 +940,8 @@ private: logical_locs_map_t m_logical_locs; const diagnostic *m_current_diag; const diagnostic_logical_location *m_prev_diag_logical_loc; - std::unique_ptr<edit_context> m_edit_context; + std::unique_ptr<diagnostics::changes::change_set> m_change_set; + bool m_debug_physical_locations; }; class impl_rich_location : public rich_location @@ -717,7 +970,7 @@ private: char *m_text; }; -class impl_rule : public diagnostic_metadata::rule +class impl_rule : public diagnostics::metadata::rule { public: impl_rule (const char *title, const char *url) @@ -743,23 +996,58 @@ private: owned_nullable_string m_url; }; -class libgdiagnostics_path_event : public diagnostic_event +struct diagnostic_graph : public diagnostics::digraphs::digraph +{ + diagnostic_graph (diagnostic_manager &) {} + + diagnostic_node * + add_node_with_id (std::string node_id, + diagnostic_node *parent_node); + diagnostic_edge * + add_edge_with_label (const char *edge_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 diagnostics::paths::event { public: libgdiagnostics_path_event (const diagnostic_physical_location *physical_loc, const diagnostic_logical_location *logical_loc, unsigned stack_depth, - const char *gmsgid, - va_list *args) + std::unique_ptr<diagnostic_graph> state_graph, + std::unique_ptr<diagnostic_message_buffer> msg_buf) : 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_msg_buf (std::move (msg_buf)) { - m_desc_uncolored = make_desc (gmsgid, args, false); - m_desc_colored = make_desc (gmsgid, args, true); + gcc_assert (m_msg_buf); } - /* diagnostic_event vfunc implementations. */ + /* diagnostics::paths::event vfunc implementations. */ location_t get_location () const final override { @@ -773,13 +1061,15 @@ public: void print_desc (pretty_printer &pp) const final override { - if (pp_show_color (&pp)) - pp_string (&pp, m_desc_colored.get ()); - else - pp_string (&pp, m_desc_uncolored.get ()); + if (m_msg_buf) + { + pp_element_message_buffer e_msg_buf (*m_msg_buf); + pp_printf (&pp, "%e", &e_msg_buf); + } } - logical_location get_logical_location () const final override + diagnostics::logical_locations::key + get_logical_location () const final override { return impl_logical_location_manager::key_from_ptr (m_logical_loc); } @@ -794,11 +1084,20 @@ public: return false; // TODO } - diagnostic_thread_id_t get_thread_id () const final override + diagnostics::paths::thread_id_t get_thread_id () const final override { 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,11 +1123,11 @@ private: const diagnostic_physical_location *m_physical_loc; const diagnostic_logical_location *m_logical_loc; unsigned m_stack_depth; - label_text m_desc_uncolored; - label_text m_desc_colored; + std::unique_ptr<diagnostic_graph> m_state_graph; + std::unique_ptr<diagnostic_message_buffer> m_msg_buf; }; -class libgdiagnostics_path_thread : public diagnostic_thread +class libgdiagnostics_path_thread : public diagnostics::paths::thread { public: libgdiagnostics_path_thread (const char *name) : m_name (name) {} @@ -843,43 +1142,62 @@ private: /* This has to be a "struct" as it is exposed in the C API. */ -struct diagnostic_execution_path : public diagnostic_path +struct diagnostic_execution_path : public diagnostics::paths::path { - diagnostic_execution_path (const logical_location_manager &logical_loc_mgr) - : diagnostic_path (logical_loc_mgr), + diagnostic_execution_path (const diagnostics::logical_locations::manager &logical_loc_mgr) + : diagnostics::paths::path (logical_loc_mgr), m_thread ("") { } - diagnostic_event_id_t + diagnostics::paths::event_id_t 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) { + auto msg_buf = std::make_unique<diagnostic_message_buffer> (gmsgid, args); + + m_events.push_back + (std::make_unique<libgdiagnostics_path_event> (physical_loc, + logical_loc, + stack_depth, + std::move (state_graph), + std::move (msg_buf))); + return m_events.size () - 1; + } + + diagnostic_event_id_t + add_event_via_msg_buf (const diagnostic_physical_location *physical_loc, + const diagnostic_logical_location *logical_loc, + unsigned stack_depth, + std::unique_ptr<diagnostic_graph> state_graph, + std::unique_ptr<diagnostic_message_buffer> msg_buf) + { m_events.push_back (std::make_unique<libgdiagnostics_path_event> (physical_loc, logical_loc, stack_depth, - gmsgid, - args)); + std::move (state_graph), + std::move (msg_buf))); return m_events.size () - 1; } - /* diagnostic_path vfunc implementations. */ + /* diagnostics::paths::path vfunc implementations. */ unsigned num_events () const final override { return m_events.size (); } - const diagnostic_event & get_event (int idx) const final override + const diagnostics::paths::event & get_event (int idx) const final override { return *m_events[idx]; } unsigned num_threads () const final override { return 1; } - const diagnostic_thread & - get_thread (diagnostic_thread_id_t) const final override + const diagnostics::paths::thread & + get_thread (diagnostics::paths::thread_id_t) const final override { return m_thread; } @@ -888,9 +1206,10 @@ struct diagnostic_execution_path : public diagnostic_path same_function_p (int event_idx_a, int event_idx_b) const final override { + using logical_location = diagnostics::logical_locations::key; logical_location logical_loc_a = m_events[event_idx_a]->get_logical_location (); - 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. */ @@ -902,6 +1221,28 @@ private: std::vector<std::unique_ptr<libgdiagnostics_path_event>> m_events; }; +class prebuilt_digraphs + : public lazily_created<std::vector<std::unique_ptr<diagnostics::digraphs::digraph>>> +{ +public: + using digraph = diagnostics::digraphs::digraph; + + std::unique_ptr<std::vector<std::unique_ptr<digraph>>> + create_object () 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 @@ -913,8 +1254,11 @@ public: m_level (level), m_rich_loc (diag_mgr.get_line_table ()), m_logical_loc (nullptr), - m_path (nullptr) - {} + m_path (nullptr), + m_nesting_level (0) + { + m_metadata.set_lazy_digraphs (&m_graphs); + } diagnostic_manager &get_manager () const { @@ -924,7 +1268,7 @@ public: enum diagnostic_level get_level () const { return m_level; } rich_location *get_rich_location () { return &m_rich_loc; } - const diagnostic_metadata *get_metadata () { return &m_metadata; } + const diagnostics::metadata *get_metadata () { return &m_metadata; } void set_cwe (unsigned cwe_id) { @@ -964,6 +1308,19 @@ public: } void + add_location_with_label (const diagnostic_physical_location *loc, + std::unique_ptr<diagnostic_message_buffer> msg_buf) + { + std::string str = msg_buf->to_string (); + std::unique_ptr<range_label> label + = std::make_unique <impl_range_label> (str.c_str ()); + m_rich_loc.add_range (as_location_t (loc), + SHOW_RANGE_WITHOUT_CARET, + label.get ()); + m_labels.push_back (std::move (label)); + } + + void set_logical_location (const diagnostic_logical_location *logical_loc) { m_logical_loc = logical_loc; @@ -990,32 +1347,49 @@ 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; + } + + int get_nesting_level () const { return m_nesting_level; } + void set_nesting_level (int value) { m_nesting_level = value; } + 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; + diagnostics::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; + int m_nesting_level; }; -static diagnostic_t -diagnostic_t_from_diagnostic_level (enum diagnostic_level level) +static enum diagnostics::kind +diagnostics_kind_from_diagnostic_level (enum diagnostic_level level) { switch (level) { default: gcc_unreachable (); case DIAGNOSTIC_LEVEL_ERROR: - return DK_ERROR; + return diagnostics::kind::error; case DIAGNOSTIC_LEVEL_WARNING: - return DK_WARNING; + return diagnostics::kind::warning; case DIAGNOSTIC_LEVEL_NOTE: - return DK_NOTE; + return diagnostics::kind::note; case DIAGNOSTIC_LEVEL_SORRY: - return DK_SORRY; + return diagnostics::kind::sorry; } } @@ -1025,7 +1399,7 @@ diagnostic_file::set_buffered_content (const char *buf, size_t sz) m_content = std::make_unique<content_buffer> (buf, sz); // Populate file_cache: - file_cache &fc = m_mgr.get_dc ().get_file_cache (); + diagnostics::file_cache &fc = m_mgr.get_dc ().get_file_cache (); fc.add_buffered_content (m_name.get_str (), buf, sz); } @@ -1043,13 +1417,13 @@ diagnostic_physical_location::get_file () const /* class impl_diagnostic_client_data_hooks. */ -const client_version_info * +const diagnostics::client_version_info * impl_diagnostic_client_data_hooks::get_any_version_info () const { return m_mgr.get_client_version_info (); } -logical_location +diagnostics::logical_locations::key impl_diagnostic_client_data_hooks::get_current_logical_location () const { gcc_assert (m_mgr.get_current_diag ()); @@ -1067,7 +1441,7 @@ maybe_get_sarif_source_language (const char *filename) const void impl_diagnostic_client_data_hooks:: -add_sarif_invocation_properties (sarif_object &) const +add_sarif_invocation_properties (diagnostics::sarif_object &) const { // No-op. } @@ -1078,10 +1452,10 @@ diagnostic_text_sink::diagnostic_text_sink (diagnostic_manager &mgr, FILE *dst_stream, enum diagnostic_colorize colorize) : sink (mgr), - m_source_printing (mgr.get_dc ().m_source_printing) + m_source_printing (mgr.get_dc ().get_source_printing_options ()) { auto inner_sink - = std::make_unique<diagnostic_text_output_format> (mgr.get_dc (), + = std::make_unique<diagnostics::text_sink> (mgr.get_dc (), &m_source_printing); inner_sink->get_printer ()->set_output_stream (dst_stream); m_inner_sink = inner_sink.get (); @@ -1111,11 +1485,11 @@ diagnostic_text_sink::set_colorize (enum diagnostic_colorize colorize) } void -diagnostic_text_sink::text_starter (diagnostic_text_output_format &text_output, - const diagnostic_info *info) +diagnostic_text_sink::text_starter (diagnostics::text_sink &text_output, + const diagnostics::diagnostic_info *info) { - gcc_assert (info->x_data); - const diagnostic &diag = *static_cast<const diagnostic *> (info->x_data); + gcc_assert (info->m_x_data); + const diagnostic &diag = *static_cast<const diagnostic *> (info->m_x_data); pretty_printer *pp = text_output.get_printer (); const diagnostic_logical_location *diag_logical_loc = diag.get_logical_location (); @@ -1181,15 +1555,17 @@ diagnostic_text_sink::text_starter (diagnostic_text_output_format &text_output, /* class sarif_sink : public sink. */ -sarif_sink::sarif_sink (diagnostic_manager &mgr, - FILE *dst_stream, - const diagnostic_file *main_input_file, - const sarif_generation_options &sarif_gen_opts) +sarif_sink:: +sarif_sink (diagnostic_manager &mgr, + FILE *dst_stream, + const diagnostic_file *main_input_file, + const diagnostics::sarif_generation_options &sarif_gen_opts) : sink (mgr) { - diagnostic_output_file output_file (dst_stream, false, - label_text::borrow ("sarif_sink")); - auto serialization = std::make_unique<sarif_serialization_format_json> (true); + diagnostics::output_file output_file (dst_stream, false, + label_text::borrow ("sarif_sink")); + auto serialization + = std::make_unique<diagnostics::sarif_serialization_format_json> (true); auto inner_sink = make_sarif_sink (mgr.get_dc (), *mgr.get_line_table (), std::move (serialization), @@ -1199,6 +1575,64 @@ sarif_sink::sarif_sink (diagnostic_manager &mgr, mgr.get_dc ().add_sink (std::move (inner_sink)); } +// struct diagnostic_message_buffer + +std::string +diagnostic_message_buffer::to_string () const +{ + std::string result; + + /* Convert to text, dropping colorization, URLs, etc. */ + for (auto iter = m_tokens.m_first; iter; iter = iter->m_next) + switch (iter->m_kind) + { + default: + gcc_unreachable (); + + case pp_token::kind::text: + { + pp_token_text *sub = as_a <pp_token_text *> (iter); + result += sub->m_value.get (); + } + break; + + case pp_token::kind::begin_color: + case pp_token::kind::end_color: + // Skip + break; + + case pp_token::kind::begin_quote: + result += open_quote; + break; + + case pp_token::kind::end_quote: + result += close_quote; + break; + + case pp_token::kind::begin_url: + case pp_token::kind::end_url: + // Skip + break; + + case pp_token::kind::event_id: + { + pp_token_event_id *sub = as_a <pp_token_event_id *> (iter); + gcc_assert (sub->m_event_id.known_p ()); + result += '('; + result += std::to_string (sub->m_event_id.one_based ()); + result += ')'; + } + break; + + case pp_token::kind::custom_data: + /* We don't have a way of handling custom_data tokens here. */ + gcc_unreachable (); + break; + } + + return result; +} + /* struct diagnostic_manager. */ void @@ -1206,12 +1640,12 @@ diagnostic_manager::write_patch (FILE *dst_stream) { pretty_printer pp; pp.set_output_stream (dst_stream); - m_edit_context->print_diff (&pp, true); + m_change_set->print_diff (&pp, true); pp_flush (&pp); } void -diagnostic_manager::emit (diagnostic &diag, const char *msgid, va_list *args) +diagnostic_manager::emit_va (diagnostic &diag, const char *msgid, va_list *args) { set_line_table_global (); @@ -1220,26 +1654,46 @@ diagnostic_manager::emit (diagnostic &diag, const char *msgid, va_list *args) { m_dc.begin_group (); - diagnostic_info info; + diagnostics::diagnostic_info info; GCC_DIAGNOSTIC_PUSH_IGNORED(-Wsuggest-attribute=format) diagnostic_set_info (&info, msgid, args, diag.get_rich_location (), - diagnostic_t_from_diagnostic_level (diag.get_level ())); + diagnostics_kind_from_diagnostic_level + (diag.get_level ())); GCC_DIAGNOSTIC_POP - info.metadata = diag.get_metadata (); - info.x_data = &diag; + info.m_metadata = diag.get_metadata (); + info.m_x_data = &diag; + m_dc.set_nesting_level (diag.get_nesting_level ()); diagnostic_report_diagnostic (&m_dc, &info); - + m_dc.set_nesting_level (0); m_dc.end_group (); } rich_location *rich_loc = diag.get_rich_location (); if (rich_loc->fixits_can_be_auto_applied_p ()) - m_edit_context->add_fixits (rich_loc); + m_change_set->add_fixits (rich_loc); m_prev_diag_logical_loc = diag.get_logical_location (); m_current_diag = nullptr; } +void +diagnostic_manager::emit (diagnostic &diag, const char *msgid, ...) +{ + va_list args; + va_start (args, msgid); + emit_va (diag, msgid, &args); + va_end (args); +} + +void +diagnostic_manager::emit_msg_buf (diagnostic &diag, + diagnostic_message_buffer &msg_buf) +{ + + pp_element_message_buffer e_msg_buf (msg_buf); + emit (diag, "%e", &e_msg_buf); +} + diagnostic_execution_path * diagnostic_manager::new_execution_path () { @@ -1248,13 +1702,36 @@ 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 lazily_created<diagnostics::digraphs::digraph> + { + public: + prebuilt_lazy_digraph (std::unique_ptr<diagnostic_graph> graph) + : m_graph (std::move (graph)) + { + } + + std::unique_ptr<diagnostics::digraphs::digraph> + create_object () 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) \ - do { \ - volatile const void *p = (PTR_ARG); \ - if (!p) { \ - fprintf (stderr, "%s: %s must be non-NULL\n", \ + do { \ + volatile const void *ptr_arg = (PTR_ARG); \ + if (!ptr_arg) { \ + fprintf (stderr, "%s: %s must be non-NULL\n", \ __func__, #PTR_ARG); \ abort (); \ } \ @@ -1388,7 +1865,7 @@ diagnostic_manager_add_sarif_sink (diagnostic_manager *diag_mgr, FAIL_IF_NULL (dst_stream); FAIL_IF_NULL (main_input_file); - sarif_generation_options sarif_gen_opts; + diagnostics::sarif_generation_options sarif_gen_opts; switch (version) { default: @@ -1396,10 +1873,11 @@ diagnostic_manager_add_sarif_sink (diagnostic_manager *diag_mgr, __func__, (int)version); abort (); case DIAGNOSTIC_SARIF_VERSION_2_1_0: - sarif_gen_opts.m_version = sarif_version::v2_1_0; + sarif_gen_opts.m_version = diagnostics::sarif_version::v2_1_0; break; case DIAGNOSTIC_SARIF_VERSION_2_2_PRERELEASE: - sarif_gen_opts.m_version = sarif_version::v2_2_prerelease_2024_08_08; + sarif_gen_opts.m_version + = diagnostics::sarif_version::v2_2_prerelease_2024_08_08; break; } @@ -1529,12 +2007,12 @@ diagnostic_manager_debug_dump_location (const diagnostic_manager *diag_mgr, diag_mgr->set_line_table_global (); const expanded_location exp_loc (expand_location (cpplib_loc)); - diagnostic_context dc; + diagnostics::context dc; diagnostic_initialize (&dc, 0); dc.m_show_column = true; - diagnostic_text_output_format text_format (dc); - label_text loc_text = text_format.get_location_text (exp_loc); + diagnostics::text_sink text_output (dc); + label_text loc_text = text_output.get_location_text (exp_loc); fprintf (out, "%s", loc_text.get ()); diagnostic_finish (&dc); @@ -1873,10 +2351,12 @@ diagnostic_execution_path_add_event (diagnostic_execution_path *path, va_list args; va_start (args, gmsgid); - diagnostic_event_id_t result = path->add_event_va (physical_loc, - logical_loc, - stack_depth, - gmsgid, &args); + diagnostics::paths::event_id_t result + = path->add_event_va (physical_loc, + logical_loc, + stack_depth, + nullptr, + gmsgid, &args); va_end (args); return as_diagnostic_event_id (result); @@ -1895,10 +2375,12 @@ diagnostic_execution_path_add_event_va (diagnostic_execution_path *path, FAIL_IF_NULL (path); FAIL_IF_NULL (gmsgid); - diagnostic_event_id_t result = path->add_event_va (physical_loc, - logical_loc, - stack_depth, - gmsgid, args); + diagnostics::paths::event_id_t result + = path->add_event_va (physical_loc, + logical_loc, + stack_depth, + nullptr, + gmsgid, args); return as_diagnostic_event_id (result); } @@ -1928,7 +2410,7 @@ diagnostic_finish_va (diagnostic *diag, const char *gmsgid, va_list *args) else progname = "progname"; auto_diagnostic_group d; - diag->get_manager ().emit (*diag, gmsgid, args); + diag->get_manager ().emit_va (*diag, gmsgid, args); delete diag; } @@ -1987,7 +2469,7 @@ diagnostic_logical_location_get_decorated_name (const diagnostic_logical_locatio namespace { -struct spec_context : public diagnostics_output_spec::context +struct spec_context : public diagnostics::output_spec::context { public: spec_context (const char *option_name, @@ -2048,3 +2530,504 @@ diagnostic_manager_set_analysis_target (diagnostic_manager *mgr, mgr->get_dc ().set_main_input_filename (file->get_name ()); } + +/* Public entrypoint. */ + +diagnostic_node * +diagnostic_graph::add_node_with_id (std::string node_id, + diagnostic_node *parent_node) +{ + auto node_up + = std::make_unique<diagnostic_node> (*this, std::move (node_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; +} + +/* Public entrypoint. */ + +diagnostic_edge * +diagnostic_graph::add_edge_with_label (const char *edge_id, + diagnostic_node &src_node, + diagnostic_node &dst_node, + const char *label) +{ + auto edge_up + = std::make_unique<diagnostic_edge> (*this, edge_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); +} + +/* Public entrypoint. */ + +diagnostic_node * +diagnostic_graph_add_node (diagnostic_graph *graph, + const char *node_id, + diagnostic_node *parent_node) +{ + FAIL_IF_NULL (graph); + FAIL_IF_NULL (node_id); + + return graph->add_node_with_id (node_id, parent_node); +} + +/* Public entrypoint. */ + +diagnostic_edge * +diagnostic_graph_add_edge (diagnostic_graph *graph, + const char *edge_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 (edge_id, *src_node, *dst_node, label); +} + +/* Public entrypoint. */ + +diagnostic_node * +diagnostic_graph_get_node_by_id (diagnostic_graph *graph, + const char *node_id) +{ + FAIL_IF_NULL (graph); + FAIL_IF_NULL (node_id); + + return static_cast<diagnostic_node *> (graph->get_node_by_id (node_id)); +} + +/* Public entrypoint. */ + +diagnostic_edge * +diagnostic_graph_get_edge_by_id (diagnostic_graph *graph, + const char *edge_id) +{ + FAIL_IF_NULL (graph); + FAIL_IF_NULL (edge_id); + + return static_cast<diagnostic_edge *> (graph->get_edge_by_id (edge_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); +} + +/* Public entrypoint. */ + +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. */ + +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)); +} + +/* Public entrypoint. */ + +diagnostic_message_buffer * +diagnostic_message_buffer_new () +{ + return new diagnostic_message_buffer (); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_release (diagnostic_message_buffer *msg_buf) +{ + FAIL_IF_NULL (msg_buf); + delete msg_buf; +} + +void +diagnostic_message_buffer_append_str (diagnostic_message_buffer *msg_buf, + const char *p) +{ + FAIL_IF_NULL (msg_buf); + FAIL_IF_NULL (p); + msg_buf->m_tokens.push_back_text (label_text::take (xstrdup (p))); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_append_text (diagnostic_message_buffer *msg_buf, + const char *p, + size_t len) +{ + FAIL_IF_NULL (msg_buf); + FAIL_IF_NULL (p); + msg_buf->m_tokens.push_back_text (label_text::take (xstrndup (p, len))); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_append_byte (diagnostic_message_buffer *msg_buf, + char ch) +{ + FAIL_IF_NULL (msg_buf); + msg_buf->m_tokens.push_back_byte (ch); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_append_printf (diagnostic_message_buffer *msg_buf, + const char *fmt, ...) +{ + FAIL_IF_NULL (msg_buf); + FAIL_IF_NULL (fmt); + + va_list args; + va_start (args, fmt); + + char *formatted_buf = xvasprintf (fmt, args); + + va_end (args); + + msg_buf->m_tokens.push_back_text (label_text::take (formatted_buf)); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_append_event_id (diagnostic_message_buffer *msg_buf, + diagnostic_event_id event_id) +{ + FAIL_IF_NULL (msg_buf); + msg_buf->m_tokens.push_back<pp_token_event_id> (event_id); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_begin_url (diagnostic_message_buffer *msg_buf, + const char *url) +{ + FAIL_IF_NULL (msg_buf); + FAIL_IF_NULL (url); + msg_buf->m_tokens.push_back<pp_token_begin_url> + (label_text::take (xstrdup (url))); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_end_url (diagnostic_message_buffer *msg_buf) +{ + FAIL_IF_NULL (msg_buf); + msg_buf->m_tokens.push_back<pp_token_end_url> (); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_begin_quote (diagnostic_message_buffer *msg_buf) +{ + FAIL_IF_NULL (msg_buf); + msg_buf->m_tokens.push_back<pp_token_begin_quote> (); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_end_quote (diagnostic_message_buffer *msg_buf) +{ + FAIL_IF_NULL (msg_buf); + msg_buf->m_tokens.push_back<pp_token_end_quote> (); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_begin_color (diagnostic_message_buffer *msg_buf, + const char *color) +{ + FAIL_IF_NULL (msg_buf); + FAIL_IF_NULL (color); + msg_buf->m_tokens.push_back<pp_token_begin_color> + (label_text::take (xstrdup (color))); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_end_color (diagnostic_message_buffer *msg_buf) +{ + FAIL_IF_NULL (msg_buf); + msg_buf->m_tokens.push_back<pp_token_end_color> (); +} + +/* Public entrypoint. */ + +void +diagnostic_message_buffer_dump (const diagnostic_message_buffer *msg_buf, + FILE *outf) +{ + FAIL_IF_NULL (msg_buf); + FAIL_IF_NULL (outf); + + msg_buf->m_tokens.dump (outf); +} + +/* Public entrypoint. */ + +void +diagnostic_finish_via_msg_buf (diagnostic *diag, + diagnostic_message_buffer *msg_buf) +{ + FAIL_IF_NULL (diag); + FAIL_IF_NULL (msg_buf); + + if (const char *tool_name + = diag->get_manager ().get_client_version_info ()->m_name.get_str ()) + progname = tool_name; + else + progname = "progname"; + auto_diagnostic_group d; + diag->get_manager ().emit_msg_buf (*diag, *msg_buf); + delete diag; + delete msg_buf; +} + +/* Public entrypoint. */ + +void +diagnostic_add_location_with_label_via_msg_buf (diagnostic *diag, + const diagnostic_physical_location *loc, + diagnostic_message_buffer *msg_buf) +{ + FAIL_IF_NULL (diag); + diag->get_manager ().assert_valid_diagnostic_physical_location (loc); + FAIL_IF_NULL (msg_buf); + + std::unique_ptr<diagnostic_message_buffer> msg_buf_up (msg_buf); + diag->add_location_with_label (loc, std::move (msg_buf_up)); +} + +/* Public entrypoint. */ + +diagnostic_event_id +diagnostic_execution_path_add_event_via_msg_buf (diagnostic_execution_path *path, + const diagnostic_physical_location *physical_loc, + const diagnostic_logical_location *logical_loc, + unsigned stack_depth, + diagnostic_message_buffer *msg_buf) +{ + FAIL_IF_NULL (path); + FAIL_IF_NULL (msg_buf); + + std::unique_ptr<diagnostic_message_buffer> msg_buf_up (msg_buf); + diagnostic_event_id_t result + = path->add_event_via_msg_buf (physical_loc, + logical_loc, + stack_depth, + nullptr, + std::move (msg_buf_up)); + return as_diagnostic_event_id (result); +} + +/* Public entrypoint. */ + +void +diagnostic_graph_set_description_via_msg_buf (diagnostic_graph *graph, + diagnostic_message_buffer *desc) +{ + FAIL_IF_NULL (graph); + + if (desc) + graph->set_description (desc->to_string ()); + else + graph->set_description (nullptr); +} + +/* Public entrypoint. */ + +diagnostic_edge * +diagnostic_graph_add_edge_via_msg_buf (diagnostic_graph *graph, + const char *edge_id, + diagnostic_node *src_node, + diagnostic_node *dst_node, + diagnostic_message_buffer *label) +{ + FAIL_IF_NULL (graph); + FAIL_IF_NULL (src_node); + FAIL_IF_NULL (dst_node); + + if (label) + { + std::string label_str (label->to_string ()); + return graph->add_edge_with_label (edge_id, *src_node, *dst_node, + label_str.c_str ()); + } + else + return graph->add_edge_with_label (edge_id, *src_node, *dst_node, + nullptr); +} + +/* Public entrypoint. */ + +void +diagnostic_node_set_label_via_msg_buf (diagnostic_node *node, + diagnostic_message_buffer *label) +{ + FAIL_IF_NULL (node); + + if (label) + node->set_label (label->to_string ()); + else + node->set_label (nullptr); +} + +/* Private entrypoint. */ + +diagnostic_event_id +private_diagnostic_execution_path_add_event_3 (diagnostic_execution_path *path, + const diagnostic_physical_location *physical_loc, + const diagnostic_logical_location *logical_loc, + unsigned stack_depth, + diagnostic_graph *state_graph, + diagnostic_message_buffer *msg_buf) +{ + FAIL_IF_NULL (path); + FAIL_IF_NULL (msg_buf); + + diagnostic_event_id_t result + = path->add_event_via_msg_buf + (physical_loc, + logical_loc, + stack_depth, + std::unique_ptr <diagnostic_graph> (state_graph), + std::unique_ptr <diagnostic_message_buffer> (msg_buf)); + + return as_diagnostic_event_id (result); +} + +/* Public entrypoint. */ + +void +diagnostic_manager_set_debug_physical_locations (diagnostic_manager *mgr, + int value) +{ + FAIL_IF_NULL (mgr); + mgr->set_debug_physical_locations (value); +} + +/* Private entrypoint. */ + +void +private_diagnostic_set_nesting_level (diagnostic *diag, + int nesting_level) +{ + FAIL_IF_NULL (diag); + diag->set_nesting_level (nesting_level); +} |