|  | /* A C++ wrapper API around libgdiagnostics.h for emitting diagnostics. | 
|  | Copyright (C) 2023-2025 Free Software Foundation, Inc. | 
|  |  | 
|  | This file is part of GCC. | 
|  |  | 
|  | GCC is free software; you can redistribute it and/or modify it | 
|  | under the terms of the GNU General Public License as published by | 
|  | the Free Software Foundation; either version 3, or (at your option) | 
|  | any later version. | 
|  |  | 
|  | GCC is distributed in the hope that it will be useful, but | 
|  | WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | General Public License for more details. | 
|  |  | 
|  | You should have received a copy of the GNU General Public License | 
|  | along with GCC; see the file COPYING3.  If not see | 
|  | <http://www.gnu.org/licenses/>.  */ | 
|  |  | 
|  | #ifndef LIBGDIAGNOSTICSPP_H | 
|  | #define LIBGDIAGNOSTICSPP_H | 
|  |  | 
|  | #include "libgdiagnostics.h" | 
|  |  | 
|  | namespace libgdiagnostics { | 
|  |  | 
|  | typedef diagnostic_line_num_t line_num_t; | 
|  | typedef diagnostic_column_num_t column_num_t; | 
|  |  | 
|  | class file; | 
|  | class physical_location; | 
|  | class logical_location; | 
|  | class execution_path; | 
|  | class group; | 
|  | class manager; | 
|  | class diagnostic; | 
|  | class graph; | 
|  | class node; | 
|  | class edge; | 
|  | class message_buffer; | 
|  |  | 
|  | /* Wrapper around a borrowed diagnostic_text_sink *.  */ | 
|  |  | 
|  | class text_sink | 
|  | { | 
|  | public: | 
|  | text_sink (diagnostic_text_sink *inner) | 
|  | : m_inner (inner) | 
|  | { | 
|  | } | 
|  |  | 
|  | void | 
|  | set_source_printing_enabled (int value) | 
|  | { | 
|  | diagnostic_text_sink_set_source_printing_enabled (m_inner, value); | 
|  | } | 
|  |  | 
|  | void | 
|  | set_colorize (enum diagnostic_colorize colorize) | 
|  | { | 
|  | diagnostic_text_sink_set_colorize (m_inner, colorize); | 
|  | } | 
|  |  | 
|  | void | 
|  | set_labelled_source_colorization_enabled (int value) | 
|  | { | 
|  | diagnostic_text_sink_set_labelled_source_colorization_enabled (m_inner, | 
|  | value); | 
|  | } | 
|  |  | 
|  | diagnostic_text_sink *m_inner; | 
|  | }; | 
|  |  | 
|  | /* Wrapper around a diagnostic_file *.  */ | 
|  |  | 
|  | class file | 
|  | { | 
|  | public: | 
|  | file () : m_inner (nullptr) {} | 
|  | file (diagnostic_file *file) : m_inner (file) {} | 
|  | file (const file &other) : m_inner (other.m_inner) {} | 
|  | file &operator= (const file &other) { m_inner = other.m_inner; return *this; } | 
|  |  | 
|  | void set_buffered_content (const char *data, size_t sz); | 
|  |  | 
|  | diagnostic_file * m_inner; | 
|  | }; | 
|  |  | 
|  | /* Wrapper around a const diagnostic_physical_location *.  */ | 
|  |  | 
|  | class physical_location | 
|  | { | 
|  | public: | 
|  | physical_location () : m_inner (nullptr) {} | 
|  |  | 
|  | physical_location (const diagnostic_physical_location *location) | 
|  | : m_inner (location) | 
|  | {} | 
|  |  | 
|  | file get_file () const; | 
|  |  | 
|  | const diagnostic_physical_location *m_inner; | 
|  | }; | 
|  |  | 
|  | /* Wrapper around a const diagnostic_logical_location *.  */ | 
|  |  | 
|  | class logical_location | 
|  | { | 
|  | public: | 
|  | logical_location () : m_inner (nullptr) {} | 
|  |  | 
|  | logical_location (const diagnostic_logical_location *logical_loc) | 
|  | : m_inner (logical_loc) | 
|  | {} | 
|  |  | 
|  | operator bool() { return m_inner != nullptr; } | 
|  |  | 
|  | // Various accessors | 
|  | enum diagnostic_logical_location_kind_t get_kind () const; | 
|  | logical_location get_parent () const; | 
|  | const char *get_short_name () const; | 
|  | const char *get_fully_qualified_name () const; | 
|  | const char *get_decorated_name () const; | 
|  |  | 
|  | bool operator== (const logical_location &other) const | 
|  | { | 
|  | return m_inner == other.m_inner; | 
|  | } | 
|  |  | 
|  | bool operator!= (const logical_location &other) const | 
|  | { | 
|  | return m_inner != other.m_inner; | 
|  | } | 
|  |  | 
|  | const diagnostic_logical_location *m_inner; | 
|  | }; | 
|  |  | 
|  | /* Wrapper around a diagnostic_message_buffer *, with ownership.  */ | 
|  |  | 
|  | class message_buffer | 
|  | { | 
|  | public: | 
|  | message_buffer () : m_inner (nullptr) {} | 
|  | message_buffer (diagnostic_message_buffer *inner) : m_inner (inner) {} | 
|  | ~message_buffer () | 
|  | { | 
|  | if (m_inner) | 
|  | diagnostic_message_buffer_release (m_inner); | 
|  | } | 
|  | message_buffer (const message_buffer &) = delete; | 
|  | message_buffer (message_buffer &&other) | 
|  | { | 
|  | m_inner = other.m_inner; | 
|  | other.m_inner = nullptr; | 
|  | } | 
|  | message_buffer& operator= (const message_buffer &) = delete; | 
|  | message_buffer& operator= (message_buffer &&other) | 
|  | { | 
|  | if (m_inner) | 
|  | diagnostic_message_buffer_release (m_inner); | 
|  | m_inner = other.m_inner; | 
|  | other.m_inner = nullptr; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | message_buffer& | 
|  | operator+= (const char *str) | 
|  | { | 
|  | diagnostic_message_buffer_append_str (m_inner, str); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | message_buffer& | 
|  | operator+= (char ch) | 
|  | { | 
|  | diagnostic_message_buffer_append_byte (m_inner, ch); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | message_buffer & | 
|  | begin_url (const char *url) | 
|  | { | 
|  | diagnostic_message_buffer_begin_url (m_inner, url); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | message_buffer & | 
|  | end_url () | 
|  | { | 
|  | diagnostic_message_buffer_end_url (m_inner); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | diagnostic_message_buffer *m_inner; | 
|  | }; | 
|  |  | 
|  | /* RAII class around a diagnostic_execution_path *.  */ | 
|  |  | 
|  | class execution_path | 
|  | { | 
|  | public: | 
|  | execution_path () : m_inner (nullptr), m_owned (false) {} | 
|  |  | 
|  | execution_path (diagnostic_execution_path *path) | 
|  | : m_inner (path), m_owned (true) | 
|  | {} | 
|  |  | 
|  | execution_path (const diagnostic_execution_path *path) | 
|  | : m_inner (const_cast<diagnostic_execution_path *> (path)), | 
|  | m_owned (false) | 
|  | {} | 
|  |  | 
|  | execution_path (const execution_path &other) = delete; | 
|  | execution_path &operator= (const execution_path &other) = delete; | 
|  |  | 
|  | execution_path (execution_path &&other) | 
|  | : m_inner (other.m_inner), | 
|  | m_owned (other.m_owned) | 
|  | { | 
|  | other.m_inner = nullptr; | 
|  | other.m_owned = false; | 
|  | } | 
|  |  | 
|  | execution_path &operator= (execution_path &&other) | 
|  | { | 
|  | m_inner = other.m_inner; | 
|  | m_owned = other.m_owned; | 
|  | other.m_inner = nullptr; | 
|  | other.m_owned = false; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | ~execution_path () | 
|  | { | 
|  | if (m_owned) | 
|  | diagnostic_execution_path_release (m_inner); | 
|  | } | 
|  |  | 
|  | diagnostic_event_id | 
|  | add_event (physical_location physical_loc, | 
|  | logical_location logical_loc, | 
|  | unsigned stack_depth, | 
|  | const char *fmt, ...) | 
|  | LIBGDIAGNOSTICS_PARAM_GCC_FORMAT_STRING (5, 6); | 
|  |  | 
|  | diagnostic_event_id | 
|  | add_event_va (physical_location physical_loc, | 
|  | logical_location logical_loc, | 
|  | unsigned stack_depth, | 
|  | const char *fmt, | 
|  | va_list *args) | 
|  | LIBGDIAGNOSTICS_PARAM_GCC_FORMAT_STRING (5, 0); | 
|  |  | 
|  | diagnostic_event_id | 
|  | add_event_via_msg_buf (physical_location physical_loc, | 
|  | logical_location logical_loc, | 
|  | unsigned stack_depth, | 
|  | message_buffer &&msg_buf); | 
|  |  | 
|  | diagnostic_execution_path *m_inner; | 
|  | bool m_owned; | 
|  | }; | 
|  |  | 
|  | /* RAII class for starting/ending a group within a diagnostic_manager.  */ | 
|  |  | 
|  | class group | 
|  | { | 
|  | public: | 
|  | group (manager &mgr); | 
|  | ~group (); | 
|  |  | 
|  | private: | 
|  | manager &m_mgr; | 
|  | }; | 
|  |  | 
|  | /* Wrapper around a diagnostic *.  */ | 
|  |  | 
|  | class diagnostic | 
|  | { | 
|  | public: | 
|  | diagnostic (::diagnostic *d) : m_inner (d) {} | 
|  |  | 
|  | void | 
|  | set_cwe (unsigned cwe_id); | 
|  |  | 
|  | void | 
|  | add_rule (const char *title, const char *url); | 
|  |  | 
|  | void | 
|  | set_location (physical_location loc); | 
|  |  | 
|  | void | 
|  | add_location (physical_location loc); | 
|  |  | 
|  | void | 
|  | add_location_with_label (physical_location loc, | 
|  | const char *text); | 
|  |  | 
|  | void | 
|  | add_location_with_label (physical_location loc, | 
|  | message_buffer &&text); | 
|  |  | 
|  | void | 
|  | set_logical_location (logical_location loc); | 
|  |  | 
|  | void | 
|  | add_fix_it_hint_insert_before (physical_location loc, | 
|  | const char *addition); | 
|  | void | 
|  | add_fix_it_hint_insert_after (physical_location loc, | 
|  | const char *addition); | 
|  | void | 
|  | add_fix_it_hint_replace (physical_location loc, | 
|  | const char *replacement); | 
|  | void | 
|  | add_fix_it_hint_delete (physical_location loc); | 
|  |  | 
|  | void | 
|  | take_execution_path (execution_path path); | 
|  |  | 
|  | void | 
|  | take_graph (graph g); | 
|  |  | 
|  | void | 
|  | finish (const char *fmt, ...) | 
|  | LIBGDIAGNOSTICS_PARAM_MUST_BE_NON_NULL (2) | 
|  | LIBGDIAGNOSTICS_PARAM_GCC_FORMAT_STRING (2, 3); | 
|  |  | 
|  | void | 
|  | finish_va (const char *fmt, va_list *args) | 
|  | LIBGDIAGNOSTICS_PARAM_MUST_BE_NON_NULL (2) | 
|  | LIBGDIAGNOSTICS_PARAM_GCC_FORMAT_STRING (2, 0); | 
|  |  | 
|  | void | 
|  | finish_via_msg_buf (message_buffer &&msg_buf); | 
|  |  | 
|  | ::diagnostic * const m_inner; | 
|  | }; | 
|  |  | 
|  | /* Wrapper around a diagnostic_manager *, possibly with ownership.  */ | 
|  |  | 
|  | class manager | 
|  | { | 
|  | public: | 
|  | manager () | 
|  | : m_inner (diagnostic_manager_new ()), | 
|  | m_owned (true) | 
|  | { | 
|  | } | 
|  | manager (diagnostic_manager *inner, bool owned) | 
|  | : m_inner (inner), | 
|  | m_owned (owned) | 
|  | { | 
|  | } | 
|  | ~manager () | 
|  | { | 
|  | if (m_owned) | 
|  | diagnostic_manager_release (m_inner); | 
|  | } | 
|  |  | 
|  | manager (const manager &other) = delete; | 
|  | manager (manager &&other) | 
|  | : m_inner (other.m_inner), | 
|  | m_owned (other.m_owned) | 
|  | { | 
|  | other.m_inner = nullptr; | 
|  | } | 
|  |  | 
|  | void | 
|  | set_tool_name (const char *value) | 
|  | { | 
|  | diagnostic_manager_set_tool_name (m_inner, value); | 
|  | } | 
|  |  | 
|  | void | 
|  | set_full_name (const char *value) | 
|  | { | 
|  | diagnostic_manager_set_full_name (m_inner, value); | 
|  | } | 
|  |  | 
|  | void | 
|  | set_version_string (const char *value) | 
|  | { | 
|  | diagnostic_manager_set_version_string (m_inner, value); | 
|  | } | 
|  |  | 
|  | void | 
|  | set_version_url (const char *value) | 
|  | { | 
|  | diagnostic_manager_set_version_url (m_inner, value); | 
|  | } | 
|  |  | 
|  | text_sink | 
|  | add_text_sink (FILE *dst_stream, | 
|  | enum diagnostic_colorize colorize) | 
|  | { | 
|  | return text_sink | 
|  | (diagnostic_manager_add_text_sink (m_inner, dst_stream, colorize)); | 
|  | } | 
|  |  | 
|  | void | 
|  | add_sarif_sink (FILE *dst_stream, | 
|  | file main_input_file, | 
|  | enum diagnostic_sarif_version version) | 
|  | { | 
|  | diagnostic_manager_add_sarif_sink (m_inner, dst_stream, | 
|  | main_input_file.m_inner, | 
|  | version); | 
|  | } | 
|  |  | 
|  | bool | 
|  | add_sink_from_spec (const char *option_name, | 
|  | const char *spec, | 
|  | manager control_mgr) | 
|  | { | 
|  | return diagnostic_manager_add_sink_from_spec (m_inner, | 
|  | option_name, | 
|  | spec, | 
|  | control_mgr.m_inner); | 
|  | } | 
|  |  | 
|  | void | 
|  | write_patch (FILE *dst_stream) | 
|  | { | 
|  | diagnostic_manager_write_patch (m_inner, dst_stream); | 
|  | } | 
|  |  | 
|  | /* Location management.  */ | 
|  |  | 
|  | file | 
|  | new_file (const char *name, | 
|  | const char *sarif_source_language) | 
|  | LIBGDIAGNOSTICS_PARAM_MUST_BE_NON_NULL (2) | 
|  | LIBGDIAGNOSTICS_PARAM_CAN_BE_NULL (3); | 
|  |  | 
|  | void | 
|  | debug_dump (file f, | 
|  | FILE *out); | 
|  |  | 
|  | physical_location | 
|  | new_location_from_file_and_line (file f, diagnostic_line_num_t line_num); | 
|  |  | 
|  | physical_location | 
|  | new_location_from_file_line_column (file f, | 
|  | line_num_t line_num, | 
|  | column_num_t column_num); | 
|  |  | 
|  | physical_location | 
|  | new_location_from_range (physical_location loc_caret, | 
|  | physical_location loc_start, | 
|  | physical_location loc_end); | 
|  |  | 
|  | void | 
|  | debug_dump (physical_location loc, | 
|  | FILE *out); | 
|  |  | 
|  | logical_location | 
|  | new_logical_location (enum diagnostic_logical_location_kind_t kind, | 
|  | logical_location parent, | 
|  | const char *short_name, | 
|  | const char *fully_qualified_name, | 
|  | const char *decorated_name); | 
|  |  | 
|  | void | 
|  | debug_dump (logical_location loc, | 
|  | FILE *out); | 
|  |  | 
|  | execution_path | 
|  | new_execution_path (); | 
|  |  | 
|  | diagnostic | 
|  | begin_diagnostic (enum diagnostic_level level); | 
|  |  | 
|  | void | 
|  | set_analysis_target (file f); | 
|  |  | 
|  | void | 
|  | take_global_graph (graph g); | 
|  |  | 
|  | diagnostic_manager *m_inner; | 
|  | bool m_owned; | 
|  | }; | 
|  |  | 
|  | class graph | 
|  | { | 
|  | public: | 
|  | graph () : m_inner (nullptr), m_owned (false) {} | 
|  |  | 
|  | graph (diagnostic_graph *graph) | 
|  | : m_inner (graph), m_owned (true) | 
|  | {} | 
|  |  | 
|  | graph (const diagnostic_graph *graph) | 
|  | : m_inner (const_cast<diagnostic_graph *> (graph)), | 
|  | m_owned (false) | 
|  | {} | 
|  |  | 
|  | graph (const graph &other) = delete; | 
|  | graph &operator= (const graph &other) = delete; | 
|  |  | 
|  | graph (graph &&other) | 
|  | : m_inner (other.m_inner), | 
|  | m_owned (other.m_owned) | 
|  | { | 
|  | other.m_inner = nullptr; | 
|  | other.m_owned = false; | 
|  | } | 
|  |  | 
|  | graph &operator= (graph &&other) | 
|  | { | 
|  | m_inner = other.m_inner; | 
|  | m_owned = other.m_owned; | 
|  | other.m_inner = nullptr; | 
|  | other.m_owned = false; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | ~graph () | 
|  | { | 
|  | if (m_owned) | 
|  | diagnostic_graph_release (m_inner); | 
|  | } | 
|  |  | 
|  | void | 
|  | set_description (const char *); | 
|  | void | 
|  | set_description (message_buffer &&); | 
|  |  | 
|  | node | 
|  | get_node_by_id (const char *id) const; | 
|  |  | 
|  | edge | 
|  | get_edge_by_id (const char *id) const; | 
|  |  | 
|  | edge | 
|  | add_edge (const char *id, node src_node, node dst_node, const char *label); | 
|  | edge | 
|  | add_edge (const char *id, node src_node, node dst_node, message_buffer &&label); | 
|  |  | 
|  | diagnostic_graph *m_inner; | 
|  | bool m_owned; | 
|  | }; | 
|  |  | 
|  | // Borrowed pointer to a diagnostic_node. | 
|  |  | 
|  | class node | 
|  | { | 
|  | public: | 
|  | node () : m_inner (nullptr) {} | 
|  | node (diagnostic_node *node_) : m_inner (node_) {} | 
|  |  | 
|  | void | 
|  | set_label (const char *); | 
|  | void | 
|  | set_label (message_buffer &&); | 
|  |  | 
|  | void | 
|  | set_location (physical_location loc); | 
|  |  | 
|  | void | 
|  | set_logical_location (logical_location loc); | 
|  |  | 
|  | diagnostic_node *m_inner; | 
|  | }; | 
|  |  | 
|  | // Borrowed edge to a diagnostic_edge. | 
|  |  | 
|  | class edge | 
|  | { | 
|  | public: | 
|  | edge (diagnostic_edge *edge_) : m_inner (edge_) {} | 
|  |  | 
|  | diagnostic_edge *m_inner; | 
|  | }; | 
|  |  | 
|  | // Implementation | 
|  |  | 
|  | // class file | 
|  |  | 
|  | inline void | 
|  | file::set_buffered_content (const char *data, size_t sz) | 
|  | { | 
|  | diagnostic_file_set_buffered_content (m_inner, data, sz); | 
|  | } | 
|  |  | 
|  | // class physical_location | 
|  |  | 
|  | inline file | 
|  | physical_location::get_file () const | 
|  | { | 
|  | return file (diagnostic_physical_location_get_file (m_inner)); | 
|  | } | 
|  |  | 
|  | // class logical_location | 
|  |  | 
|  | inline enum diagnostic_logical_location_kind_t | 
|  | logical_location::get_kind () const | 
|  | { | 
|  | // m_inner must be non-null | 
|  | return diagnostic_logical_location_get_kind (m_inner); | 
|  | } | 
|  |  | 
|  | inline logical_location | 
|  | logical_location::get_parent () const | 
|  | { | 
|  | if (m_inner) | 
|  | return diagnostic_logical_location_get_parent (m_inner); | 
|  | else | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | inline const char * | 
|  | logical_location::get_short_name () const | 
|  | { | 
|  | if (m_inner) | 
|  | return diagnostic_logical_location_get_short_name (m_inner); | 
|  | else | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | inline const char * | 
|  | logical_location::get_fully_qualified_name () const | 
|  | { | 
|  | if (m_inner) | 
|  | return diagnostic_logical_location_get_fully_qualified_name (m_inner); | 
|  | else | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | inline const char * | 
|  | logical_location::get_decorated_name () const | 
|  | { | 
|  | if (m_inner) | 
|  | return diagnostic_logical_location_get_decorated_name (m_inner); | 
|  | else | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | // class execution_path | 
|  |  | 
|  | inline diagnostic_event_id | 
|  | execution_path::add_event (physical_location physical_loc, | 
|  | logical_location logical_loc, | 
|  | unsigned stack_depth, | 
|  | const char *fmt, ...) | 
|  | { | 
|  | va_list args; | 
|  | va_start (args, fmt); | 
|  | diagnostic_event_id result = add_event_va (physical_loc, | 
|  | logical_loc, | 
|  | stack_depth, | 
|  | fmt, &args); | 
|  | va_end (args); | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | inline diagnostic_event_id | 
|  | execution_path::add_event_va (physical_location physical_loc, | 
|  | logical_location logical_loc, | 
|  | unsigned stack_depth, | 
|  | const char *fmt, | 
|  | va_list *args) | 
|  | { | 
|  | return diagnostic_execution_path_add_event_va (m_inner, | 
|  | physical_loc.m_inner, | 
|  | logical_loc.m_inner, | 
|  | stack_depth, | 
|  | fmt, | 
|  | args); | 
|  | } | 
|  |  | 
|  | inline diagnostic_event_id | 
|  | execution_path::add_event_via_msg_buf (physical_location physical_loc, | 
|  | logical_location logical_loc, | 
|  | unsigned stack_depth, | 
|  | message_buffer &&msg_buf) | 
|  | { | 
|  | diagnostic_message_buffer *inner_msg_buf = msg_buf.m_inner; | 
|  | msg_buf.m_inner = nullptr; | 
|  | return diagnostic_execution_path_add_event_via_msg_buf (m_inner, | 
|  | physical_loc.m_inner, | 
|  | logical_loc.m_inner, | 
|  | stack_depth, | 
|  | inner_msg_buf); | 
|  | } | 
|  |  | 
|  | // class group | 
|  |  | 
|  | inline | 
|  | group::group (manager &mgr) | 
|  | : m_mgr (mgr) | 
|  | { | 
|  | diagnostic_manager_begin_group (m_mgr.m_inner); | 
|  | } | 
|  |  | 
|  | inline | 
|  | group::~group () | 
|  | { | 
|  | diagnostic_manager_end_group (m_mgr.m_inner); | 
|  | } | 
|  |  | 
|  | // class diagnostic | 
|  |  | 
|  | inline void | 
|  | diagnostic::set_cwe (unsigned cwe_id) | 
|  | { | 
|  | diagnostic_set_cwe (m_inner, cwe_id); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::add_rule (const char *title, const char *url) | 
|  | { | 
|  | diagnostic_add_rule (m_inner, title, url); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::set_location (physical_location loc) | 
|  | { | 
|  | diagnostic_set_location (m_inner, loc.m_inner); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::add_location_with_label (physical_location loc, | 
|  | const char *text) | 
|  | { | 
|  | diagnostic_add_location_with_label (m_inner, loc.m_inner, text); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::add_location_with_label (physical_location loc, | 
|  | message_buffer &&msg_buf) | 
|  | { | 
|  | diagnostic_message_buffer *inner_msg_buf = msg_buf.m_inner; | 
|  | msg_buf.m_inner = nullptr; | 
|  | diagnostic_add_location_with_label_via_msg_buf (m_inner, | 
|  | loc.m_inner, | 
|  | inner_msg_buf); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::add_location (physical_location loc) | 
|  | { | 
|  | diagnostic_add_location (m_inner, loc.m_inner); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::set_logical_location (logical_location loc) | 
|  | { | 
|  | diagnostic_set_logical_location (m_inner, loc.m_inner); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::add_fix_it_hint_insert_before (physical_location loc, | 
|  | const char *addition) | 
|  | { | 
|  | diagnostic_add_fix_it_hint_insert_before (m_inner, | 
|  | loc.m_inner, | 
|  | addition); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::add_fix_it_hint_insert_after (physical_location loc, | 
|  | const char *addition) | 
|  | { | 
|  | diagnostic_add_fix_it_hint_insert_after (m_inner, | 
|  | loc.m_inner, | 
|  | addition); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::add_fix_it_hint_replace (physical_location loc, | 
|  | const char *replacement) | 
|  | { | 
|  | diagnostic_add_fix_it_hint_replace (m_inner, | 
|  | loc.m_inner, | 
|  | replacement); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::add_fix_it_hint_delete (physical_location loc) | 
|  | { | 
|  | diagnostic_add_fix_it_hint_delete (m_inner, | 
|  | loc.m_inner); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::take_execution_path (execution_path path) | 
|  | { | 
|  | diagnostic_take_execution_path (m_inner, | 
|  | path.m_inner); | 
|  | path.m_owned = false; | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::take_graph (graph g) | 
|  | { | 
|  | diagnostic_take_graph (m_inner, | 
|  | g.m_inner); | 
|  | g.m_owned = false; | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::finish (const char *fmt, ...) | 
|  | { | 
|  | va_list ap; | 
|  | va_start (ap, fmt); | 
|  | diagnostic_finish_va (m_inner, fmt, &ap); | 
|  | va_end (ap); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::finish_va (const char *fmt, va_list *args) | 
|  | { | 
|  | diagnostic_finish_va (m_inner, fmt, args); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | diagnostic::finish_via_msg_buf (message_buffer &&msg_buf) | 
|  | { | 
|  | diagnostic_message_buffer *inner_msg_buf = msg_buf.m_inner; | 
|  | msg_buf.m_inner = nullptr; | 
|  | diagnostic_finish_via_msg_buf (m_inner, inner_msg_buf); | 
|  | } | 
|  |  | 
|  | // class manager | 
|  |  | 
|  | inline file | 
|  | manager::new_file (const char *name, | 
|  | const char *sarif_source_language) | 
|  | { | 
|  | return file | 
|  | (diagnostic_manager_new_file (m_inner, name, sarif_source_language)); | 
|  | } | 
|  |  | 
|  | inline physical_location | 
|  | manager::new_location_from_file_and_line (file f, | 
|  | diagnostic_line_num_t line_num) | 
|  | { | 
|  | return physical_location | 
|  | (diagnostic_manager_new_location_from_file_and_line (m_inner, | 
|  | f.m_inner, | 
|  | line_num)); | 
|  | } | 
|  |  | 
|  | inline physical_location | 
|  | manager::new_location_from_file_line_column (file f, | 
|  | line_num_t line_num, | 
|  | column_num_t column_num) | 
|  | { | 
|  | return physical_location | 
|  | (diagnostic_manager_new_location_from_file_line_column (m_inner, | 
|  | f.m_inner, | 
|  | line_num, | 
|  | column_num)); | 
|  | } | 
|  |  | 
|  | inline physical_location | 
|  | manager::new_location_from_range (physical_location loc_caret, | 
|  | physical_location loc_start, | 
|  | physical_location loc_end) | 
|  | { | 
|  | return physical_location | 
|  | (diagnostic_manager_new_location_from_range (m_inner, | 
|  | loc_caret.m_inner, | 
|  | loc_start.m_inner, | 
|  | loc_end.m_inner)); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | manager::debug_dump (physical_location loc, | 
|  | FILE *out) | 
|  | { | 
|  | diagnostic_manager_debug_dump_location (m_inner, | 
|  | loc.m_inner, | 
|  | out); | 
|  | } | 
|  | inline logical_location | 
|  | manager::new_logical_location (enum diagnostic_logical_location_kind_t kind, | 
|  | logical_location parent, | 
|  | const char *short_name, | 
|  | const char *fully_qualified_name, | 
|  | const char *decorated_name) | 
|  | { | 
|  | return logical_location | 
|  | (diagnostic_manager_new_logical_location (m_inner, | 
|  | kind, | 
|  | parent.m_inner, | 
|  | short_name, | 
|  | fully_qualified_name, | 
|  | decorated_name)); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | manager::debug_dump (logical_location loc, | 
|  | FILE *out) | 
|  | { | 
|  | diagnostic_manager_debug_dump_logical_location (m_inner, | 
|  | loc.m_inner, | 
|  | out); | 
|  | } | 
|  |  | 
|  | inline execution_path | 
|  | manager::new_execution_path () | 
|  | { | 
|  | return execution_path (diagnostic_manager_new_execution_path (m_inner)); | 
|  | } | 
|  |  | 
|  | inline diagnostic | 
|  | manager::begin_diagnostic (enum diagnostic_level level) | 
|  | { | 
|  | return diagnostic (diagnostic_begin (m_inner, level)); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | manager::set_analysis_target (file f) | 
|  | { | 
|  | diagnostic_manager_set_analysis_target (m_inner, f.m_inner); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | manager::take_global_graph (graph g) | 
|  | { | 
|  | diagnostic_manager_take_global_graph (m_inner, | 
|  | g.m_inner); | 
|  | g.m_owned = false; | 
|  | } | 
|  |  | 
|  | // class graph | 
|  |  | 
|  | inline void | 
|  | graph::set_description (const char *desc) | 
|  | { | 
|  | diagnostic_graph_set_description (m_inner, desc); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | graph::set_description (message_buffer &&msg_buf) | 
|  | { | 
|  | diagnostic_message_buffer *inner_msg_buf = msg_buf.m_inner; | 
|  | msg_buf.m_inner = nullptr; | 
|  | diagnostic_graph_set_description_via_msg_buf (m_inner, inner_msg_buf); | 
|  | } | 
|  |  | 
|  | inline node | 
|  | graph::get_node_by_id (const char *id) const | 
|  | { | 
|  | return node (diagnostic_graph_get_node_by_id (m_inner, id)); | 
|  | } | 
|  |  | 
|  | inline edge | 
|  | graph::get_edge_by_id (const char *id) const | 
|  | { | 
|  | return edge (diagnostic_graph_get_edge_by_id (m_inner, id)); | 
|  | } | 
|  |  | 
|  | inline edge | 
|  | graph::add_edge (const char *id, | 
|  | node src_node, node dst_node, | 
|  | const char *label) | 
|  | { | 
|  | return edge (diagnostic_graph_add_edge (m_inner, | 
|  | id, | 
|  | src_node.m_inner, | 
|  | dst_node.m_inner, | 
|  | label)); | 
|  | } | 
|  |  | 
|  | inline edge | 
|  | graph::add_edge (const char *id, | 
|  | node src_node, node dst_node, | 
|  | message_buffer &&label) | 
|  | { | 
|  | diagnostic_message_buffer *inner_label = label.m_inner; | 
|  | label.m_inner = nullptr; | 
|  | return edge (diagnostic_graph_add_edge_via_msg_buf (m_inner, | 
|  | id, | 
|  | src_node.m_inner, | 
|  | dst_node.m_inner, | 
|  | inner_label)); | 
|  | } | 
|  |  | 
|  | // class node | 
|  |  | 
|  | inline void | 
|  | node::set_label (const char *label) | 
|  | { | 
|  | diagnostic_node_set_label (m_inner, label); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | node::set_label (message_buffer &&label) | 
|  | { | 
|  | diagnostic_message_buffer *inner_label = label.m_inner; | 
|  | label.m_inner = nullptr; | 
|  | diagnostic_node_set_label_via_msg_buf (m_inner, inner_label); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | node::set_location (physical_location loc) | 
|  | { | 
|  | diagnostic_node_set_location (m_inner, loc.m_inner); | 
|  | } | 
|  |  | 
|  | inline void | 
|  | node::set_logical_location (logical_location loc) | 
|  | { | 
|  | diagnostic_node_set_logical_location (m_inner, loc.m_inner); | 
|  | } | 
|  |  | 
|  | } // namespace libgdiagnostics | 
|  |  | 
|  | #endif // #ifndef LIBGDIAGNOSTICSPP_H |