diff options
Diffstat (limited to 'gcc/libgdiagnostics.cc')
-rw-r--r-- | gcc/libgdiagnostics.cc | 424 |
1 files changed, 342 insertions, 82 deletions
diff --git a/gcc/libgdiagnostics.cc b/gcc/libgdiagnostics.cc index c2eb975..74814c7 100644 --- a/gcc/libgdiagnostics.cc +++ b/gcc/libgdiagnostics.cc @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see #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 "libgdiagnostics.h" @@ -162,7 +163,7 @@ as_location_t (const diagnostic_physical_location *loc) /* This has to be a "struct" as it is exposed in the C API. */ -struct diagnostic_logical_location : public logical_location +struct diagnostic_logical_location { diagnostic_logical_location (enum diagnostic_logical_location_kind_t kind, const diagnostic_logical_location *parent, @@ -177,55 +178,6 @@ struct diagnostic_logical_location : public logical_location { } - const char *get_short_name () const final override - { - return m_short_name.get_str (); - } - const char *get_name_with_scope () const final override - { - return m_fully_qualified_name.get_str (); - } - const char *get_internal_name () const final override - { - return m_decorated_name.get_str (); - } - enum logical_location_kind get_kind () const final override - { - switch (m_kind) - { - default: - gcc_unreachable (); - case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION: - return LOGICAL_LOCATION_KIND_FUNCTION; - case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER: - return LOGICAL_LOCATION_KIND_MEMBER; - case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE: - return LOGICAL_LOCATION_KIND_MODULE; - case DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE: - return LOGICAL_LOCATION_KIND_NAMESPACE; - case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE: - return LOGICAL_LOCATION_KIND_TYPE; - case DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE: - return LOGICAL_LOCATION_KIND_RETURN_TYPE; - case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER: - return LOGICAL_LOCATION_KIND_PARAMETER; - case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE: - return LOGICAL_LOCATION_KIND_VARIABLE; - } - } - - enum diagnostic_logical_location_kind_t get_external_kind () const - { - return m_kind; - } - - const diagnostic_logical_location *get_parent () const { return m_parent; } - - label_text get_name_for_path_output () const - { - return label_text::borrow (m_short_name.get_str ()); - } - bool operator< (const diagnostic_logical_location &other) const { @@ -243,7 +195,6 @@ struct diagnostic_logical_location : public logical_location return false; } -private: enum diagnostic_logical_location_kind_t m_kind; const diagnostic_logical_location *m_parent; owned_nullable_string m_short_name; @@ -308,6 +259,112 @@ round_alloc_size (size_t s) return s; } +class impl_logical_location_manager : public logical_location_manager +{ +public: + static const diagnostic_logical_location * + ptr_from_key (logical_location k) + { + return k.cast_to<const diagnostic_logical_location *> (); + } + + static logical_location + key_from_ptr (const diagnostic_logical_location *ptr) + { + return logical_location::from_ptr (ptr); + } + + const char *get_short_name (key k) const final override + { + if (auto loc = ptr_from_key (k)) + return loc->m_short_name.get_str (); + else + return nullptr; + } + + const char *get_name_with_scope (key k) const final override + { + if (auto loc = ptr_from_key (k)) + return loc->m_fully_qualified_name.get_str (); + else + return nullptr; + } + + const char *get_internal_name (key k) const final override + { + if (auto loc = ptr_from_key (k)) + return loc->m_decorated_name.get_str (); + else + return nullptr; + } + + enum logical_location_kind get_kind (key k) const final override + { + auto loc = ptr_from_key (k); + gcc_assert (loc); + switch (loc->m_kind) + { + default: + gcc_unreachable (); + + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION: + return logical_location_kind::function; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER: + return logical_location_kind::member; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE: + return logical_location_kind::module_; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE: + return logical_location_kind::namespace_; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE: + return logical_location_kind::type; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE: + return logical_location_kind::return_type; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER: + return logical_location_kind::parameter; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE: + return logical_location_kind::variable; + + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT: + return logical_location_kind::element; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE: + return logical_location_kind::attribute; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT: + return logical_location_kind::text; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT: + return logical_location_kind::comment; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION: + return logical_location_kind::processing_instruction; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD: + return logical_location_kind::dtd; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION: + return logical_location_kind::declaration; + + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT: + return logical_location_kind::object; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY: + return logical_location_kind::array; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY: + return logical_location_kind::property; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE: + return logical_location_kind::value; + } + } + + label_text get_name_for_path_output (key k) const final override + { + auto loc = ptr_from_key (k); + gcc_assert (loc); + return label_text::borrow (loc->m_short_name.get_str ()); + } + + key get_parent (key k) const final override + { + auto loc = ptr_from_key (k); + gcc_assert (loc); + return key_from_ptr (loc->m_parent); + } +}; + class impl_diagnostic_client_data_hooks : public diagnostic_client_data_hooks { public: @@ -316,7 +373,14 @@ public: {} const client_version_info *get_any_version_info () const final override; - const logical_location *get_current_logical_location () const final override; + + const logical_location_manager * + get_logical_location_manager () const final override + { + return &m_logical_location_manager; + } + logical_location get_current_logical_location () const final override; + const char * maybe_get_sarif_source_language (const char *filename) const final override; void add_sarif_invocation_properties (sarif_object &invocation_obj) @@ -324,6 +388,7 @@ public: private: diagnostic_manager &m_mgr; + impl_logical_location_manager m_logical_location_manager; }; class impl_client_version_info : public client_version_info @@ -424,6 +489,14 @@ public: line_maps *get_line_table () { return &m_line_table; } diagnostic_context &get_dc () { return m_dc; } + const logical_location_manager & + get_logical_location_manager () const + { + auto mgr = m_dc.get_logical_location_manager (); + gcc_assert (mgr); + return *mgr; + } + void write_patch (FILE *dst_stream); void add_sink (std::unique_ptr<sink> sink) @@ -706,9 +779,9 @@ public: pp_string (&pp, m_desc_uncolored.get ()); } - const logical_location *get_logical_location () const + logical_location get_logical_location () const final override { - return m_logical_loc; + return impl_logical_location_manager::key_from_ptr (m_logical_loc); } meaning get_meaning () const final override @@ -772,8 +845,9 @@ private: struct diagnostic_execution_path : public diagnostic_path { - diagnostic_execution_path () - : m_thread ("") + diagnostic_execution_path (const logical_location_manager &logical_loc_mgr) + : diagnostic_path (logical_loc_mgr), + m_thread ("") { } @@ -814,9 +888,9 @@ struct diagnostic_execution_path : public diagnostic_path same_function_p (int event_idx_a, int event_idx_b) const final override { - const logical_location *logical_loc_a + logical_location logical_loc_a = m_events[event_idx_a]->get_logical_location (); - const logical_location *logical_loc_b + logical_location logical_loc_b = m_events[event_idx_b]->get_logical_location (); /* Pointer equality, as we uniqify logical location instances. */ @@ -902,7 +976,9 @@ public: diagnostic_execution_path * add_execution_path () { - m_path = std::make_unique<diagnostic_execution_path> (); + m_path + = std::make_unique<diagnostic_execution_path> + (m_diag_mgr.get_logical_location_manager ()); m_rich_loc.set_path (m_path.get ()); return m_path.get (); } @@ -973,12 +1049,13 @@ impl_diagnostic_client_data_hooks::get_any_version_info () const return m_mgr.get_client_version_info (); } -const logical_location * +logical_location impl_diagnostic_client_data_hooks::get_current_logical_location () const { gcc_assert (m_mgr.get_current_diag ()); - return m_mgr.get_current_diag ()->get_logical_location (); + return impl_logical_location_manager::key_from_ptr + (m_mgr.get_current_diag ()->get_logical_location ()); } const char * @@ -1046,21 +1123,57 @@ diagnostic_text_sink::text_starter (diagnostic_text_output_format &text_output, if (diag_logical_loc && diag_logical_loc != mgr.get_prev_diag_logical_loc ()) { pp_set_prefix (pp, nullptr); - switch (diag_logical_loc->get_kind ()) + + /* This macro is used to ensure that all format strings are visible to gettext + and checked at compile time. */ + +#define CASE(KIND, MSGID) \ + case KIND: \ + if (const char *name \ + = diag_logical_loc->m_fully_qualified_name.get_str ()) \ + { \ + pp_printf (pp, (MSGID), name); \ + pp_character (pp, ':'); \ + pp_newline (pp); \ + } \ + break; + + switch (diag_logical_loc->m_kind) { default: break; - case LOGICAL_LOCATION_KIND_FUNCTION: - if (const char *name - = diag_logical_loc->get_name_with_scope ()) - { - pp_printf (pp, _("In function %qs"), name); - pp_character (pp, ':'); - pp_newline (pp); - } - break; - // TODO: handle other cases + + /* Kinds within executable code. */ + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION, _("In function %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER, _("In member %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE, _("In module %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE, _("In namespace %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE, _("In type %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE, + _("In return type %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER, _("In parameter %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE, _("In variable %qs")) + + /* Kinds within XML or HTML documents. */ + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT, _("In element %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE, _("In attribute %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT, _("In text %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT, _("In comment %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION, + _("In processing instruction %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD, _("In DTD %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION, + _("In declaration %qs")) + + /* Kinds within JSON documents. */ + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT, _("In JSON object %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY, _("In JSON array %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY, + _("In JSON property %qs")) + CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE, _("In JSON value %qs")) } + +#undef CASE } pp_set_prefix (pp, text_output.build_prefix (*info)); @@ -1079,10 +1192,10 @@ sarif_sink::sarif_sink (diagnostic_manager &mgr, auto serialization = std::make_unique<sarif_serialization_format_json> (true); auto inner_sink = make_sarif_sink (mgr.get_dc (), *mgr.get_line_table (), - main_input_file->get_name (), std::move (serialization), sarif_gen_opts, std::move (output_file)); + inner_sink->set_main_input_filename (main_input_file->get_name ()); mgr.get_dc ().add_sink (std::move (inner_sink)); } @@ -1130,7 +1243,9 @@ GCC_DIAGNOSTIC_POP diagnostic_execution_path * diagnostic_manager::new_execution_path () { - return new diagnostic_execution_path (); + auto mgr = m_dc.get_logical_location_manager (); + gcc_assert (mgr); + return new diagnostic_execution_path (*mgr); } /* Error-checking at the API boundary. */ @@ -1458,10 +1573,11 @@ diagnostic_manager_debug_dump_logical_location (const diagnostic_manager *diag_m if (loc) { fprintf (out, "logical_location(kind="); - switch (loc->get_external_kind ()) + switch (loc->m_kind) { default: gcc_unreachable (); + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION: fprintf (out, "function"); break; @@ -1486,16 +1602,54 @@ diagnostic_manager_debug_dump_logical_location (const diagnostic_manager *diag_m case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE: fprintf (out, "variable"); break; + + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT: + fprintf (out, "element"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE: + fprintf (out, "attribute"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT: + fprintf (out, "text"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT: + fprintf (out, "comment"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION: + fprintf (out, "processing_instruction"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD: + fprintf (out, "dtd"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION: + fprintf (out, "declaration"); + break; + + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT: + fprintf (out, "object"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY: + fprintf (out, "array"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY: + fprintf (out, "property"); + break; + case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE: + fprintf (out, "value"); + break; + } + if (auto parent = loc->m_parent) + { + fprintf (out, ", parent="); + diagnostic_manager_debug_dump_logical_location (diag_mgr, + parent, + out); } - if (const diagnostic_logical_location *parent = loc->get_parent ()) - diagnostic_manager_debug_dump_logical_location (diag_mgr, - parent, - out); - if (const char *val = loc->get_short_name ()) + if (const char *val = loc->m_short_name.get_str ()) fprintf (out, ", short_name=\"%s\"", val); - if (const char *val = loc->get_name_with_scope ()) + if (const char *val = loc->m_fully_qualified_name.get_str ()) fprintf (out, ", fully_qualified_name=\"%s\"", val); - if (const char *val = loc->get_internal_name ()) + if (const char *val = loc->m_decorated_name.get_str ()) fprintf (out, ", decorated_name=\"%s\"", val); fprintf (out, ")"); } @@ -1788,3 +1942,109 @@ diagnostic_physical_location_get_file (const diagnostic_physical_location *physi return physical_loc->get_file (); } + +/* Public entrypoints for accessing logical location data. */ + +enum diagnostic_logical_location_kind_t +diagnostic_logical_location_get_kind (const diagnostic_logical_location *loc) +{ + FAIL_IF_NULL (loc); + + return loc->m_kind; +} + +const diagnostic_logical_location * +diagnostic_logical_location_get_parent (const diagnostic_logical_location *loc) +{ + FAIL_IF_NULL (loc); + + return loc->m_parent; +} + +const char * +diagnostic_logical_location_get_short_name (const diagnostic_logical_location *loc) +{ + FAIL_IF_NULL (loc); + + return loc->m_short_name.get_str (); +} + +const char * +diagnostic_logical_location_get_fully_qualified_name (const diagnostic_logical_location *loc) +{ + FAIL_IF_NULL (loc); + + return loc->m_fully_qualified_name.get_str (); +} + +const char * +diagnostic_logical_location_get_decorated_name (const diagnostic_logical_location *loc) +{ + FAIL_IF_NULL (loc); + + return loc->m_decorated_name.get_str (); +} + +namespace { + +struct spec_context : public diagnostics_output_spec::context +{ +public: + spec_context (const char *option_name, + diagnostic_manager &affected_mgr, + diagnostic_manager &control_mgr) + : context (option_name, affected_mgr.get_line_table ()), + m_control_mgr (control_mgr) + {} + + void report_error_va (const char *gmsgid, va_list *ap) const final override + { + diagnostic *diag + = diagnostic_begin (&m_control_mgr, DIAGNOSTIC_LEVEL_ERROR); + diagnostic_finish_va (diag, gmsgid, ap); + } + + const char * + get_base_filename () const final override + { + return nullptr; + } + +private: + diagnostic_manager &m_control_mgr; +}; + +} // anon namespace + +/* Public entrypoint. */ + +int +diagnostic_manager_add_sink_from_spec (diagnostic_manager *affected_mgr, + const char *option_name, + const char *spec, + diagnostic_manager *control_mgr) +{ + FAIL_IF_NULL (affected_mgr); + FAIL_IF_NULL (option_name); + FAIL_IF_NULL (spec); + FAIL_IF_NULL (control_mgr); + + spec_context ctxt (option_name, *affected_mgr, *control_mgr); + auto inner_sink = ctxt.parse_and_make_sink (spec, affected_mgr->get_dc ()); + if (!inner_sink) + return -1; + affected_mgr->get_dc ().add_sink (std::move (inner_sink)); + return 0; +} + +/* Public entrypoint. */ + +void +diagnostic_manager_set_analysis_target (diagnostic_manager *mgr, + const diagnostic_file *file) +{ + FAIL_IF_NULL (mgr); + FAIL_IF_NULL (file); + + mgr->get_dc ().set_main_input_filename (file->get_name ()); +} |