mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
1024 lines
22 KiB
C++
1024 lines
22 KiB
C++
/* A C++ wrapper API around libgdiagnostics.h for emitting diagnostics.
|
|
Copyright (C) 2023-2026 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);
|
|
|
|
void
|
|
set_debug_physical_locations (bool value);
|
|
|
|
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;
|
|
}
|
|
|
|
inline void
|
|
manager::set_debug_physical_locations (bool value)
|
|
{
|
|
diagnostic_manager_set_debug_physical_locations (m_inner,
|
|
value ? 1 : 0);
|
|
}
|
|
|
|
// 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
|