diff options
author | David Malcolm <dmalcolm@redhat.com> | 2025-08-29 14:39:37 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2025-08-29 14:39:37 -0400 |
commit | 9e98b37f32f8bff72885904fc66ea7ec8fefec58 (patch) | |
tree | 3d109ac25532ba394efbf36ed868097fec7910c6 /gcc | |
parent | ba9d4b3ce59432f3e7cef5c650b088a12e7ff877 (diff) | |
download | gcc-9e98b37f32f8bff72885904fc66ea7ec8fefec58.zip gcc-9e98b37f32f8bff72885904fc66ea7ec8fefec58.tar.gz gcc-9e98b37f32f8bff72885904fc66ea7ec8fefec58.tar.bz2 |
diagnostics: add GCC_DIAGNOSTICS_LOG
Whilst experimenting with PR diagnostics/121039 (potentially capturing
suppressed diagnostics in SARIF output), I found it very useful to have
a text log from the diagnostic subsystem to track what it's doing and
the decisions it's making (e.g. exactly when and why a diagnostic is
being rejected).
This patch adds a simple logging mechanism to the diagnostics subsystem,
enabled by setting GCC_DIAGNOSTICS_LOG in the environment, which emits
nested text like this to stderr (or a named file):
warning (option_id: 668, gmsgid: "%<-Wformat-security%> ignored without %<-Wformat%>")
diagnostics::context::diagnostic_impl (option_id: 668, kind: warning, gmsgid: "%<-Wformat-security%> ignored without %<-Wformat%>")
diagnostics::context::report_diagnostic
rejecting: diagnostic not enabled
false <- diagnostics::context::diagnostic_impl
false <- warning
This logging mechanism doesn't use pretty_printer because it can be
helpful to use it to debug pretty_printer itself.
gcc/ChangeLog:
* Makefile.in (OBJS-libcommon): Add diagnostics/logging.o.
* diagnostic-global-context.cc: Include "diagnostics/logging.h".
(log_function_params, auto_inc_log_depth): New "using" decls.
(verbatim): Add logging.
(emit_diagnostic): Likewise.
(emit_diagnostic_valist): Likewise.
(emit_diagnostic_valist_meta): Likewise.
(inform): Likewise.
(inform_n): Likewise.
(warning): Likewise.
(warning_at): Likewise.
(warning_meta): Likewise.
(warning_n): Likewise.
(pedwarn): Likewise.
(permerror): Likewise.
(permerror_opt): Likewise.
* diagnostics/context.cc: Include "diagnostics/logging.h".
(context::initialize): Initialize m_logger. Add logging.
(context::finish): Add logging. Clean up m_logger.
(context::dump): Add indent param.
(context::set_sink): Add logging.
(context::add_sink): Add logging.
(diagnostic_kind_debug_text): New.
(get_debug_string_for_kind): New.
(context::report_diagnostic): Add logging.
(context::diagnostic_impl): Likewise.
(context::diagnostic_n_impl): Likewise.
(context::end_group): Likewise.
* diagnostics/context.h: Include "diagnostics/logging.h".
(context::dump): Add indent param.
(context::get_logger): New accessor.
(context::classify_diagnostics): Add logging.
(context::push_diagnostics): Likewise.
(context::pop_diagnostics): Likewise.
(context::m_logger): New field.
* diagnostics/html-sink.cc: Include "diagnostics/logging.h".
(html_builder::flush_to_file): Add logging.
(html_sink::on_report_diagnostic): Likewise.
* diagnostics/kinds.h (get_debug_string_for_kind): New decl.
* diagnostics/logging.cc: New file.
* diagnostics/logging.h: New file.
* diagnostics/output-file.h: Include "label-text.h".
* diagnostics/sarif-sink.cc: Include "diagnostics/logging.h".
(sarif_builder::flush_to_object): Add logging.
(sarif_builder::flush_to_file): Likewise.
(sarif_sink::on_report_diagnostic): Likewise.
* diagnostics/sink.h (sink::get_logger): New.
* diagnostics/text-sink.cc: Include "diagnostics/logging.h".
(text_sink::on_report_diagnostic): Add logging.
* doc/invoke.texi (Environment Variables): Document
GCC_DIAGNOSTICS_LOG.
* opts-diagnostic.cc: Include "diagnostics/logging.h".
(handle_OPT_fdiagnostics_add_output_): Add loggging.
(handle_OPT_fdiagnostics_set_output_): Likewise.
gcc/analyzer/ChangeLog:
* pending-diagnostic.cc: Include "diagnostics/logging.h".
(diagnostic_emission_context::warn): Add logging.
(diagnostic_emission_context::inform): Likewise.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/Makefile.in | 1 | ||||
-rw-r--r-- | gcc/analyzer/pending-diagnostic.cc | 18 | ||||
-rw-r--r-- | gcc/diagnostic-global-context.cc | 267 | ||||
-rw-r--r-- | gcc/diagnostics/context.cc | 161 | ||||
-rw-r--r-- | gcc/diagnostics/context.h | 31 | ||||
-rw-r--r-- | gcc/diagnostics/html-sink.cc | 6 | ||||
-rw-r--r-- | gcc/diagnostics/kinds.h | 1 | ||||
-rw-r--r-- | gcc/diagnostics/logging.cc | 72 | ||||
-rw-r--r-- | gcc/diagnostics/logging.h | 230 | ||||
-rw-r--r-- | gcc/diagnostics/output-file.h | 2 | ||||
-rw-r--r-- | gcc/diagnostics/sarif-sink.cc | 8 | ||||
-rw-r--r-- | gcc/diagnostics/sink.h | 2 | ||||
-rw-r--r-- | gcc/diagnostics/text-sink.cc | 6 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 10 | ||||
-rw-r--r-- | gcc/opts-diagnostic.cc | 5 |
15 files changed, 784 insertions, 36 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in index d2744db..d35fced 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1864,6 +1864,7 @@ OBJS-libcommon = \ diagnostics/sarif-sink.o \ diagnostics/text-sink.o \ diagnostics/lazy-paths.o \ + diagnostics/logging.o \ diagnostics/macro-unwinding.o \ diagnostics/option-classifier.o \ diagnostics/paths.o \ diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc index cc2d795..14d8f9f 100644 --- a/gcc/analyzer/pending-diagnostic.cc +++ b/gcc/analyzer/pending-diagnostic.cc @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/common.h" #include "diagnostics/event-id.h" +#include "diagnostics/logging.h" #include "cpplib.h" #include "digraph.h" #include "ordered-hash-map.h" @@ -88,6 +89,12 @@ diagnostic_emission_context::get_pending_diagnostic () const bool diagnostic_emission_context::warn (const char *gmsgid, ...) { + auto dc_logger = global_dc->get_logger (); + diagnostics::logging::log_function_params + (dc_logger, "ana::diagnostic_emission_context::warn") + .log_param_string ("gmsgid", gmsgid); + diagnostics::logging::auto_inc_depth depth_sentinel (dc_logger); + const pending_diagnostic &pd = get_pending_diagnostic (); auto_diagnostic_group d; va_list ap; @@ -97,6 +104,11 @@ diagnostic_emission_context::warn (const char *gmsgid, ...) pd.get_controlling_option (), gmsgid, &ap); va_end (ap); + + if (dc_logger) + dc_logger->log_bool_return ("ana::diagnostic_emission_context::warn", + result); + return result; } @@ -106,6 +118,12 @@ diagnostic_emission_context::warn (const char *gmsgid, ...) void diagnostic_emission_context::inform (const char *gmsgid, ...) { + auto dc_logger = global_dc->get_logger (); + diagnostics::logging::log_function_params + (dc_logger, "ana::diagnostic_emission_context::inform") + .log_param_string ("gmsgid", gmsgid); + diagnostics::logging::auto_inc_depth depth_sentinel (dc_logger); + const pending_diagnostic &pd = get_pending_diagnostic (); auto_diagnostic_group d; va_list ap; diff --git a/gcc/diagnostic-global-context.cc b/gcc/diagnostic-global-context.cc index 500f19c..30fc190 100644 --- a/gcc/diagnostic-global-context.cc +++ b/gcc/diagnostic-global-context.cc @@ -28,11 +28,15 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "diagnostic.h" #include "diagnostics/sink.h" +#include "diagnostics/logging.h" /* A diagnostics::context surrogate for stderr. */ static diagnostics::context global_diagnostic_context; diagnostics::context *global_dc = &global_diagnostic_context; +using log_function_params = diagnostics::logging::log_function_params; +using auto_inc_log_depth = diagnostics::logging::auto_inc_depth; + /* Standard error reporting routines in increasing order of severity. */ /* Text to be emitted verbatim to the error message stream; this @@ -41,8 +45,12 @@ diagnostics::context *global_dc = &global_diagnostic_context; void verbatim (const char *gmsgid, ...) { - va_list ap; + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + va_list ap; va_start (ap, gmsgid); text_info text (_(gmsgid), &ap, errno); global_dc->report_verbatim (text); @@ -58,6 +66,13 @@ emit_diagnostic (enum diagnostics::kind kind, diagnostics::option_id option_id, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -65,6 +80,10 @@ emit_diagnostic (enum diagnostics::kind kind, bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id, gmsgid, &ap, kind); va_end (ap); + + if (logger) + logger->log_bool_return ("emit_diagnostic", ret); + return ret; } @@ -76,12 +95,23 @@ emit_diagnostic (enum diagnostics::kind kind, diagnostics::option_id option_id, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); bool ret = global_dc->diagnostic_impl (richloc, nullptr, option_id, gmsgid, &ap, kind); va_end (ap); + + if (logger) + logger->log_bool_return ("emit_diagnostic", ret); + return ret; } @@ -93,9 +123,21 @@ emit_diagnostic_valist (enum diagnostics::kind kind, diagnostics::option_id option_id, const char *gmsgid, va_list *ap) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + rich_location richloc (line_table, location); - return global_dc->diagnostic_impl (&richloc, nullptr, option_id, - gmsgid, ap, kind); + bool ret = global_dc->diagnostic_impl (&richloc, nullptr, option_id, + gmsgid, ap, kind); + + if (logger) + logger->log_bool_return ("emit_diagnostic_valist", ret); + + return ret; } /* As above, but with rich_location and metadata. */ @@ -107,8 +149,20 @@ emit_diagnostic_valist_meta (enum diagnostics::kind kind, diagnostics::option_id option_id, const char *gmsgid, va_list *ap) { - return global_dc->diagnostic_impl (richloc, metadata, option_id, - gmsgid, ap, kind); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + + bool ret = global_dc->diagnostic_impl (richloc, metadata, option_id, + gmsgid, ap, kind); + + if (logger) + logger->log_bool_return ("emit_diagnostic_valist_meta", ret); + + return ret; } /* An informative note at LOCATION. Use this for additional details on an error @@ -116,6 +170,12 @@ emit_diagnostic_valist_meta (enum diagnostics::kind kind, void inform (location_t location, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -131,6 +191,12 @@ inform (rich_location *richloc, const char *gmsgid, ...) { gcc_assert (richloc); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -145,6 +211,12 @@ void inform_n (location_t location, unsigned HOST_WIDE_INT n, const char *singular_gmsgid, const char *plural_gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_params_n_gmsgids (n, singular_gmsgid, plural_gmsgid); + auto_inc_log_depth depth_sentinel (logger); + va_list ap; va_start (ap, plural_gmsgid); auto_diagnostic_group d; @@ -161,6 +233,12 @@ inform_n (location_t location, unsigned HOST_WIDE_INT n, bool warning (diagnostics::option_id option_id, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -169,6 +247,10 @@ warning (diagnostics::option_id option_id, const char *gmsgid, ...) gmsgid, &ap, diagnostics::kind::warning); va_end (ap); + + if (logger) + logger->log_bool_return ("warning", ret); + return ret; } @@ -181,6 +263,13 @@ warning_at (location_t location, diagnostics::option_id option_id, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -189,6 +278,10 @@ warning_at (location_t location, gmsgid, &ap, diagnostics::kind::warning); va_end (ap); + + if (logger) + logger->log_bool_return ("warning_at", ret); + return ret; } @@ -201,6 +294,13 @@ warning_at (rich_location *richloc, { gcc_assert (richloc); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -208,6 +308,10 @@ warning_at (rich_location *richloc, gmsgid, &ap, diagnostics::kind::warning); va_end (ap); + + if (logger) + logger->log_bool_return ("warning_at", ret); + return ret; } @@ -221,6 +325,13 @@ warning_meta (rich_location *richloc, { gcc_assert (richloc); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -228,6 +339,10 @@ warning_meta (rich_location *richloc, gmsgid, &ap, diagnostics::kind::warning); va_end (ap); + + if (logger) + logger->log_bool_return ("warning_meta", ret); + return ret; } @@ -241,6 +356,13 @@ warning_n (rich_location *richloc, { gcc_assert (richloc); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_option_id ("option_id", option_id) + .log_params_n_gmsgids (n, singular_gmsgid, plural_gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, plural_gmsgid); @@ -248,6 +370,10 @@ warning_n (rich_location *richloc, singular_gmsgid, plural_gmsgid, &ap, diagnostics::kind::warning); va_end (ap); + + if (logger) + logger->log_bool_return ("warning_n", ret); + return ret; } @@ -261,6 +387,13 @@ warning_n (location_t location, unsigned HOST_WIDE_INT n, const char *singular_gmsgid, const char *plural_gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_param_option_id ("option_id", option_id) + .log_params_n_gmsgids (n, singular_gmsgid, plural_gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, plural_gmsgid); @@ -269,6 +402,10 @@ warning_n (location_t location, singular_gmsgid, plural_gmsgid, &ap, diagnostics::kind::warning); va_end (ap); + + if (logger) + logger->log_bool_return ("warning_n", ret); + return ret; } @@ -290,6 +427,13 @@ pedwarn (location_t location, diagnostics::option_id option_id, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -298,6 +442,10 @@ pedwarn (location_t location, gmsgid, &ap, diagnostics::kind::pedwarn); va_end (ap); + + if (logger) + logger->log_bool_return ("pedwarn", ret); + return ret; } @@ -310,6 +458,13 @@ pedwarn (rich_location *richloc, { gcc_assert (richloc); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -317,6 +472,10 @@ pedwarn (rich_location *richloc, gmsgid, &ap, diagnostics::kind::pedwarn); va_end (ap); + + if (logger) + logger->log_bool_return ("pedwarn", ret); + return ret; } @@ -330,6 +489,12 @@ pedwarn (rich_location *richloc, bool permerror (location_t location, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -337,6 +502,10 @@ permerror (location_t location, const char *gmsgid, ...) bool ret = global_dc->diagnostic_impl (&richloc, nullptr, -1, gmsgid, &ap, diagnostics::kind::permerror); va_end (ap); + + if (logger) + logger->log_bool_return ("permerror", ret); + return ret; } @@ -347,12 +516,22 @@ permerror (rich_location *richloc, const char *gmsgid, ...) { gcc_assert (richloc); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); bool ret = global_dc->diagnostic_impl (richloc, nullptr, -1, gmsgid, &ap, diagnostics::kind::permerror); va_end (ap); + + if (logger) + logger->log_bool_return ("permerror", ret); + return ret; } @@ -365,6 +544,13 @@ permerror_opt (location_t location, diagnostics::option_id option_id, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -373,6 +559,10 @@ permerror_opt (location_t location, gmsgid, &ap, diagnostics::kind::permerror); va_end (ap); + + if (logger) + logger->log_bool_return ("permerror_opt", ret); + return ret; } @@ -385,6 +575,13 @@ permerror_opt (rich_location *richloc, { gcc_assert (richloc); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_option_id ("option_id", option_id) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -392,6 +589,10 @@ permerror_opt (rich_location *richloc, gmsgid, &ap, diagnostics::kind::permerror); va_end (ap); + + if (logger) + logger->log_bool_return ("permerror_opt", ret); + return ret; } @@ -400,6 +601,11 @@ permerror_opt (rich_location *richloc, void error (const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -415,6 +621,12 @@ void error_n (location_t location, unsigned HOST_WIDE_INT n, const char *singular_gmsgid, const char *plural_gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("location", location) + .log_params_n_gmsgids (n, singular_gmsgid, plural_gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, plural_gmsgid); @@ -429,6 +641,12 @@ error_n (location_t location, unsigned HOST_WIDE_INT n, void error_at (location_t loc, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("loc", loc) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -445,6 +663,12 @@ error_at (rich_location *richloc, const char *gmsgid, ...) { gcc_assert (richloc); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -461,6 +685,12 @@ error_meta (rich_location *richloc, const diagnostics::metadata &metadata, { gcc_assert (richloc); + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_rich_location ("richloc", richloc) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -475,6 +705,11 @@ error_meta (rich_location *richloc, const diagnostics::metadata &metadata, void sorry (const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -488,6 +723,12 @@ sorry (const char *gmsgid, ...) void sorry_at (location_t loc, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("loc", loc) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -511,6 +752,12 @@ seen_error (void) void fatal_error (location_t loc, const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_location_t ("loc", loc) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -527,6 +774,11 @@ fatal_error (location_t loc, const char *gmsgid, ...) void internal_error (const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); @@ -544,6 +796,11 @@ internal_error (const char *gmsgid, ...) void internal_error_no_backtrace (const char *gmsgid, ...) { + auto logger = global_dc->get_logger (); + log_function_params (logger, __func__) + .log_param_string ("gmsgid", gmsgid); + auto_inc_log_depth depth_sentinel (logger); + auto_diagnostic_group d; va_list ap; va_start (ap, gmsgid); diff --git a/gcc/diagnostics/context.cc b/gcc/diagnostics/context.cc index 3668958..0f8670b 100644 --- a/gcc/diagnostics/context.cc +++ b/gcc/diagnostics/context.cc @@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostics/buffering.h" #include "diagnostics/file-cache.h" #include "diagnostics/dumping.h" +#include "diagnostics/logging.h" #ifdef HAVE_TERMIOS_H # include <termios.h> @@ -211,6 +212,7 @@ context::initialize (int n_opts) m_diagrams.m_theme = nullptr; m_original_argv = nullptr; m_diagnostic_buffer = nullptr; + m_logger = nullptr; enum diagnostic_text_art_charset text_art_charset = DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI; @@ -222,6 +224,27 @@ context::initialize (int n_opts) text_art_charset = DIAGNOSTICS_TEXT_ART_CHARSET_ASCII; } set_text_art_charset (text_art_charset); + + if (const char *name = getenv ("GCC_DIAGNOSTICS_LOG")) + { + if (name[0] != '\0') + { + /* Try to write a log to the named path. */ + if (FILE *outfile = fopen (name, "w")) + m_logger = new logging::logger + (output_file (outfile, true, + label_text::take (xstrdup (name)))); + } + else + /* Write a log to stderr. */ + m_logger = new logging::logger + (output_file + (stderr, false, + label_text::borrow ("stderr"))); + } + + if (m_logger) + m_logger->log_printf ("diagnostics::context::initialize"); } /* Maybe initialize the color support. We require clients to do this @@ -329,6 +352,15 @@ context::initialize_input_context (diagnostic_input_charset_callback ccb, void context::finish () { + if (m_logger) + { + m_logger->log_printf ("diagnostics::context::finish"); + /* We're cleaning up the logger before this function exits, + so we can't use auto_inc_depth here. */ + m_logger->inc_depth (); + dump (m_logger->get_stream (), m_logger->get_indent ()); + } + /* We might be handling a fatal error. Close any active diagnostic groups, which may trigger flushing sinks. */ @@ -381,45 +413,48 @@ context::finish () freeargv (m_original_argv); m_original_argv = nullptr; + + delete m_logger; + m_logger = nullptr; } /* Dump state of this diagnostics::context to OUT, for debugging. */ void -context::dump (FILE *outfile) const +context::dump (FILE *outfile, int indent) const { - dumping::emit_heading (outfile, 0, "diagnostics::context"); - m_diagnostic_counters.dump (outfile, 2); - dumping::emit_heading (outfile, 2, "reference printer"); + dumping::emit_heading (outfile, indent, "diagnostics::context"); + m_diagnostic_counters.dump (outfile, indent + 2); + dumping::emit_heading (outfile, indent + 2, "reference printer"); if (m_reference_printer) - m_reference_printer->dump (outfile, 4); + m_reference_printer->dump (outfile, indent + 4); else - dumping::emit_none (outfile, 4); - dumping::emit_heading (outfile, 2, "output sinks"); + dumping::emit_none (outfile, indent + 4); + dumping::emit_heading (outfile, indent + 2, "output sinks"); if (m_sinks.length () > 0) { for (unsigned i = 0; i < m_sinks.length (); ++i) { - dumping::emit_indent (outfile, 4); + dumping::emit_indent (outfile, indent + 4); const sink *s = m_sinks[i]; fprintf (outfile, "sink %i (", i); s->dump_kind (outfile); fprintf (outfile, "):\n"); - s->dump (outfile, 6); + s->dump (outfile, indent + 6); } } else - dumping::emit_none (outfile, 4); - dumping::emit_heading (outfile, 2, "diagnostic buffer"); + dumping::emit_none (outfile, indent + 4); + dumping::emit_heading (outfile, indent + 2, "diagnostic buffer"); if (m_diagnostic_buffer) - m_diagnostic_buffer->dump (outfile, 4); + m_diagnostic_buffer->dump (outfile, indent + 4); else - dumping::emit_none (outfile, 4); - dumping::emit_heading (outfile, 2, "file cache"); + dumping::emit_none (outfile, indent + 4); + dumping::emit_heading (outfile, indent + 2, "file cache"); if (m_file_cache) - m_file_cache->dump (outfile, 4); + m_file_cache->dump (outfile, indent + 4); else - dumping::emit_none (outfile, 4); + dumping::emit_none (outfile, indent + 4); } /* Return true if sufficiently severe diagnostics have been seen that @@ -445,6 +480,9 @@ context::remove_all_output_sinks () void context::set_sink (std::unique_ptr<sink> sink_) { + DIAGNOSTICS_LOG_SCOPE_PRINTF0 (m_logger, "diagnostics::context::set_sink"); + if (m_logger) + sink_->dump (m_logger->get_stream (), m_logger->get_indent ()); remove_all_output_sinks (); m_sinks.safe_push (sink_.release ()); } @@ -460,6 +498,9 @@ context::get_sink (size_t idx) const void context::add_sink (std::unique_ptr<sink> sink_) { + DIAGNOSTICS_LOG_SCOPE_PRINTF0 (m_logger, "diagnostics::context::add_sink"); + if (m_logger) + sink_->dump (m_logger->get_stream (), m_logger->get_indent ()); m_sinks.safe_push (sink_.release ()); } @@ -664,6 +705,19 @@ get_text_for_kind (enum kind kind) return diagnostic_kind_text[static_cast<int> (kind)]; } +static const char *const diagnostic_kind_debug_text[] = { +#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (#K), +#include "diagnostics/kinds.def" +#undef DEFINE_DIAGNOSTIC_KIND + "must-not-happen" +}; + +const char * +get_debug_string_for_kind (enum kind kind) +{ + return diagnostic_kind_debug_text[static_cast<int> (kind)]; +} + static const char *const diagnostic_kind_color[] = { #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C), #include "diagnostics/kinds.def" @@ -1276,6 +1330,9 @@ context::emit_diagnostic_with_group_va (enum kind kind, bool context::report_diagnostic (diagnostic_info *diagnostic) { + auto logger = get_logger (); + DIAGNOSTICS_LOG_SCOPE_PRINTF0 (logger, "diagnostics::context::report_diagnostic"); + enum kind orig_diag_kind = diagnostic->m_kind; /* Every call to report_diagnostic should be within a @@ -1290,6 +1347,8 @@ context::report_diagnostic (diagnostic_info *diagnostic) if (was_warning && m_inhibit_warnings) { inhibit_notes_in_group (); + if (m_logger) + m_logger->log_printf ("rejecting: inhibiting warnings"); return false; } @@ -1305,7 +1364,11 @@ context::report_diagnostic (diagnostic_info *diagnostic) } if (diagnostic->m_kind == kind::note && m_inhibit_notes_p) - return false; + { + if (m_logger) + m_logger->log_printf ("rejecting: inhibiting notes"); + return false; + } /* If the user requested that warnings be treated as errors, so be it. Note that we do this before the next block so that @@ -1322,6 +1385,8 @@ context::report_diagnostic (diagnostic_info *diagnostic) stack. . */ if (!diagnostic_enabled (diagnostic)) { + if (m_logger) + m_logger->log_printf ("rejecting: diagnostic not enabled"); inhibit_notes_in_group (); return false; } @@ -1330,13 +1395,21 @@ context::report_diagnostic (diagnostic_info *diagnostic) && ((!m_warn_system_headers && diagnostic->m_iinfo.m_allsyslocs) || m_inhibit_warnings)) - /* Bail if the warning is not to be reported because all locations in the - inlining stack (if there is one) are in system headers. */ - return false; + { + /* Bail if the warning is not to be reported because all locations in the + inlining stack (if there is one) are in system headers. */ + if (m_logger) + m_logger->log_printf ("rejecting: warning in system header"); + return false; + } if (diagnostic->m_kind == kind::note && notes_inhibited_in_group ()) - /* Bail for all the notes in the diagnostic_group that started to inhibit notes. */ - return false; + { + /* Bail for all the notes in the diagnostic_group that started to inhibit notes. */ + if (m_logger) + m_logger->log_printf ("rejecting: notes inhibited within group"); + return false; + } if (diagnostic->m_kind != kind::note && diagnostic->m_kind != kind::ice) check_max_errors (false); @@ -1397,8 +1470,13 @@ context::report_diagnostic (diagnostic_info *diagnostic) /* Is this the initial diagnostic within the stack of groups? */ if (m_diagnostic_groups.m_emission_count == 0) - for (auto sink_ : m_sinks) - sink_->on_begin_group (); + { + DIAGNOSTICS_LOG_SCOPE_PRINTF0 + (get_logger (), + "diagnostics::context: beginning group"); + for (auto sink_ : m_sinks) + sink_->on_begin_group (); + } m_diagnostic_groups.m_emission_count++; va_list *orig_args = diagnostic->m_message.m_args_ptr; @@ -1557,6 +1635,13 @@ context::diagnostic_impl (rich_location *richloc, const char *gmsgid, va_list *ap, enum kind kind) { + logging::log_function_params + (m_logger, "diagnostics::context::diagnostic_impl") + .log_param_option_id ("option_id", opt_id) + .log_param_kind ("kind", kind) + .log_param_string ("gmsgid", gmsgid); + logging::auto_inc_depth depth_sentinel (m_logger); + diagnostic_info diagnostic; if (kind == diagnostics::kind::permerror) { @@ -1574,7 +1659,11 @@ context::diagnostic_impl (rich_location *richloc, diagnostic.m_option_id = opt_id; } diagnostic.m_metadata = metadata; - return report_diagnostic (&diagnostic); + + bool ret = report_diagnostic (&diagnostic); + if (m_logger) + m_logger->log_bool_return ("diagnostics::context::diagnostic_impl", ret); + return ret; } /* Implement inform_n, warning_n, and error_n, as documented and @@ -1588,6 +1677,13 @@ context::diagnostic_n_impl (rich_location *richloc, const char *plural_gmsgid, va_list *ap, enum kind kind) { + logging::log_function_params + (m_logger, "diagnostics::context::diagnostic_n_impl") + .log_param_option_id ("option_id", opt_id) + .log_param_kind ("kind", kind) + .log_params_n_gmsgids (n, singular_gmsgid, plural_gmsgid); + logging::auto_inc_depth depth_sentinel (m_logger); + diagnostic_info diagnostic; unsigned long gtn; @@ -1604,7 +1700,11 @@ context::diagnostic_n_impl (rich_location *richloc, if (kind == diagnostics::kind::warning) diagnostic.m_option_id = opt_id; diagnostic.m_metadata = metadata; - return report_diagnostic (&diagnostic); + + bool ret = report_diagnostic (&diagnostic); + if (m_logger) + m_logger->log_bool_return ("diagnostics::context::diagnostic_n_impl", ret); + return ret; } @@ -1706,8 +1806,13 @@ context::end_group () If any diagnostics were emitted, give the context a chance to do something. */ if (m_diagnostic_groups.m_emission_count > 0) - for (auto sink_ : m_sinks) - sink_->on_end_group (); + { + DIAGNOSTICS_LOG_SCOPE_PRINTF0 + (get_logger (), + "diagnostics::context::end_group: ending group"); + for (auto sink_ : m_sinks) + sink_->on_end_group (); + } m_diagnostic_groups.m_emission_count = 0; } /* We're popping one level, so might need to stop inhibiting notes. */ diff --git a/gcc/diagnostics/context.h b/gcc/diagnostics/context.h index dea4588..9464f6a 100644 --- a/gcc/diagnostics/context.h +++ b/gcc/diagnostics/context.h @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostics/source-printing-options.h" #include "diagnostics/column-options.h" #include "diagnostics/counters.h" +#include "diagnostics/logging.h" namespace diagnostics { @@ -275,8 +276,10 @@ public: void finish (); - void dump (FILE *out) const; - void DEBUG_FUNCTION dump () const { dump (stderr); } + void dump (FILE *out, int indent) const; + void DEBUG_FUNCTION dump () const { dump (stderr, 0); } + + logging::logger *get_logger () { return m_logger; } bool execution_failed_p () const; @@ -335,18 +338,35 @@ public: enum kind new_kind, location_t where) { + logging::log_function_params + (m_logger, "diagnostics::context::classify_diagnostics") + .log_param_option_id ("option_id", opt_id) + .log_param_kind ("new_kind", new_kind) + .log_param_location_t ("where", where); + logging::auto_inc_depth depth_sentinel (m_logger); + return m_option_classifier.classify_diagnostic (this, opt_id, new_kind, where); } - void push_diagnostics (location_t where ATTRIBUTE_UNUSED) + void push_diagnostics (location_t where) { + logging::log_function_params + (m_logger, "diagnostics::context::push_diagnostics") + .log_param_location_t ("where", where); + logging::auto_inc_depth depth_sentinel (m_logger); + m_option_classifier.push (); } void pop_diagnostics (location_t where) { + logging::log_function_params + (m_logger, "diagnostics::context::pop_diagnostics") + .log_param_location_t ("where", where); + logging::auto_inc_depth depth_sentinel (m_logger); + m_option_classifier.pop (where); } @@ -826,6 +846,11 @@ private: later (if the buffer is flushed), moved to other buffers, or discarded (if the buffer is cleared). */ buffer *m_diagnostic_buffer; + + /* Owned by the context. + Debugging option: if non-NULL, report information to the logger + on what the context is doing. */ + logging::logger *m_logger; }; /* Client supplied function to announce a diagnostic diff --git a/gcc/diagnostics/html-sink.cc b/gcc/diagnostics/html-sink.cc index 1fd317a..64dcefe 100644 --- a/gcc/diagnostics/html-sink.cc +++ b/gcc/diagnostics/html-sink.cc @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostics/buffering.h" #include "diagnostics/paths.h" #include "diagnostics/dumping.h" +#include "diagnostics/logging.h" #include "diagnostics/client-data-hooks.h" #include "selftest.h" #include "diagnostics/selftest-context.h" @@ -1320,6 +1321,8 @@ html_builder::end_group () void html_builder::flush_to_file (FILE *outf) { + DIAGNOSTICS_LOG_SCOPE_PRINTF0 (m_context.get_logger (), + "diagnostics::html_builder::flush_to_file"); if (m_html_gen_opts.m_javascript) { gcc_assert (m_head_element); @@ -1389,6 +1392,9 @@ public: on_report_diagnostic (const diagnostic_info &diagnostic, enum kind orig_diag_kind) final override { + DIAGNOSTICS_LOG_SCOPE_PRINTF0 + (get_logger (), + "diagnostics::html_sink::on_report_diagnostic"); m_builder.on_report_diagnostic (diagnostic, orig_diag_kind, m_buffer); } void on_diagram (const diagram &d) final override diff --git a/gcc/diagnostics/kinds.h b/gcc/diagnostics/kinds.h index 7b4a168..1357be5 100644 --- a/gcc/diagnostics/kinds.h +++ b/gcc/diagnostics/kinds.h @@ -38,6 +38,7 @@ enum class kind }; extern const char *get_text_for_kind (enum diagnostics::kind); +extern const char *get_debug_string_for_kind (enum diagnostics::kind); extern const char *get_color_for_kind (enum diagnostics::kind); } // namespace diagnostics diff --git a/gcc/diagnostics/logging.cc b/gcc/diagnostics/logging.cc new file mode 100644 index 0000000..cfe23d5 --- /dev/null +++ b/gcc/diagnostics/logging.cc @@ -0,0 +1,72 @@ +/* Utilities for implementing "dump" functions for the diagnostics subsystem. + Copyright (C) 2025 Free Software Foundation, Inc. + Contributed by David Malcolm <dmalcolm@redhat.com>. + +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/>. */ + + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "diagnostics/logging.h" + +namespace diagnostics { +namespace logging { + +logger::logger (output_file outfile) +: m_outfile (std::move (outfile)), + m_log_depth (0) +{ +} + +void +logger::log_printf (const char *fmt, ...) +{ + emit_indent (); + + va_list ap; + va_start (ap, fmt); + vfprintf (get_stream (), fmt, ap); + va_end (ap); + + emit_newline (); +} + +void +logger::log_bool_return (const char *function_name, bool retval) +{ + log_printf ("%s <- %s", + retval ? "true" : "false", + function_name); +} + +/* Emit indentation to OUTFILE for the start of a log line. */ + +void +logger::emit_indent () const +{ + fprintf (get_stream (), "%*s", get_indent (), ""); +} + +void +logger::emit_newline () const +{ + fputc ('\n', get_stream ()); +} + +} // namespace logging { +} // namespace diagnostics diff --git a/gcc/diagnostics/logging.h b/gcc/diagnostics/logging.h new file mode 100644 index 0000000..2ce0166 --- /dev/null +++ b/gcc/diagnostics/logging.h @@ -0,0 +1,230 @@ +/* Debugging code for logging what the diagnostics subsystem is doing. + Copyright (C) 2025 Free Software Foundation, Inc. + Contributed by David Malcolm <dmalcolm@redhat.com>. + +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 GCC_DIAGNOSTICS_LOGGING_H +#define GCC_DIAGNOSTICS_LOGGING_H + +#include "diagnostics/output-file.h" +#include "diagnostics/option-id.h" +#include "diagnostics/kinds.h" + +namespace diagnostics { + +namespace logging { + +/* A class for emitting a temporal log of what the diagnostics subsystem + is doing, for debugging. + We can't use pretty_printer here as we could potentially be debugging + pretty-printing itself. */ + +class logger +{ +public: + logger (output_file outfile); + + /* High-level functions that emit a line of text. */ + void log_printf (const char *fmt, ...) + __attribute__ ((__format__ (printf, 2, 3))); + void log_bool_return (const char *function_name, bool retval); + + /* Lower-level functions for building up a line of text. */ + void emit_indent () const; + void emit_newline () const; + + FILE *get_stream () const + { + return m_outfile.get_open_file (); + } + + int get_indent () const { return m_log_depth * 2; } + + void inc_depth () { m_log_depth++; } + void dec_depth () { m_log_depth--; } + +private: + output_file m_outfile; + int m_log_depth; +}; + +/* RAII class for pushing/popping depth within a logger. */ + +class auto_inc_depth +{ +public: + auto_inc_depth (logger *log) + : m_logger (log) + { + if (m_logger) + m_logger->inc_depth (); + } + ~auto_inc_depth () + { + if (m_logger) + m_logger->dec_depth (); + } + +private: + logger *m_logger; +}; + +/* Class for debugging function call parameters. */ + +class log_function_params +{ +public: + log_function_params (logger *logger_, const char *name) + : m_logger (logger_), + m_first_param (true) + { + if (m_logger) + { + m_logger->emit_indent (); + fprintf (m_logger->get_stream (), "%s (", name); + } + } + ~log_function_params () + { + if (m_logger) + { + fprintf (m_logger->get_stream (), ")"); + m_logger->emit_newline (); + } + } + + log_function_params & + log_param_string (const char *name, const char *value) + { + if (m_logger) + { + add_any_comma (); + fprintf (m_logger->get_stream (), "%s: \"%s\"", name, value); + } + return *this; + } + + log_function_params & + log_param_location_t (const char *name, location_t value) + { + if (m_logger) + { + add_any_comma (); + fprintf (m_logger->get_stream (), + "%s: " HOST_SIZE_T_PRINT_HEX, + name, (size_t)value); + } + return *this; + } + + log_function_params & + log_param_rich_location (const char *name, const rich_location *richloc) + { + if (m_logger) + { + add_any_comma (); + fprintf (m_logger->get_stream (), + "%s: %p", + name, const_cast<void *> ((const void *)richloc)); + } + return *this; + } + + log_function_params & + log_param_option_id (const char *name, diagnostics::option_id value) + { + if (m_logger) + { + add_any_comma (); + fprintf (m_logger->get_stream (), "%s: %i", name, value.m_idx); + } + return *this; + } + + log_function_params & + log_param_kind (const char *name, enum diagnostics::kind value) + { + if (m_logger) + { + add_any_comma (); + fprintf (m_logger->get_stream (), "%s: %s", + name, get_debug_string_for_kind (value)); + } + return *this; + } + + log_function_params & + log_param_uhwi (const char *name, unsigned HOST_WIDE_INT value) + { + if (m_logger) + { + add_any_comma (); + fprintf (m_logger->get_stream (), + "%s: " HOST_WIDE_INT_PRINT_DEC, + name, value); + } + return *this; + } + + log_function_params & + log_params_n_gmsgids (unsigned HOST_WIDE_INT n, + const char *singular_gmsgid, + const char *plural_gmsgid) + { + return log_param_uhwi ("n", n) + .log_param_string ("singular_gmsgid", singular_gmsgid) + .log_param_string ("plural_gmsgid", plural_gmsgid); + } + +private: + void + add_any_comma () + { + gcc_assert (m_logger); + if (m_first_param) + m_first_param = false; + else + fprintf (m_logger->get_stream (), ", "); + } + + logger *m_logger; + bool m_first_param; +}; + +} // namespace logging +} // namespace diagnostics + +/* Various macros for logging a formatted line, and indenting + further log messages within a scope. */ + +#define DIAGNOSTICS_LOG_SCOPE_PRINTF0(LOGGER, FMT) \ + if (LOGGER) \ + (LOGGER)->log_printf ((FMT)); \ + diagnostics::logging::auto_inc_depth depth_sentinel (LOGGER); + +#define DIAGNOSTICS_LOG_SCOPE_PRINTF1(LOGGER, FMT, ARG0) \ + if (LOGGER) \ + (LOGGER)->log_printf ((FMT), (ARG0)); \ + diagnostics::logging::auto_inc_depth depth_sentinel (LOGGER); + +#define DIAGNOSTICS_LOG_SCOPE_PRINTF2(LOGGER, FMT, ARG0, ARG1) \ + if (LOGGER) \ + (LOGGER)->log_printf ((FMT), (ARG0), (ARG1)); \ + diagnostics::logging::auto_inc_depth depth_sentinel (LOGGER); + +#endif /* ! GCC_DIAGNOSTICS_LOGGING_H */ diff --git a/gcc/diagnostics/output-file.h b/gcc/diagnostics/output-file.h index f936387..827adcd 100644 --- a/gcc/diagnostics/output-file.h +++ b/gcc/diagnostics/output-file.h @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_DIAGNOSTICS_OUTPUT_FILE_H #define GCC_DIAGNOSTICS_OUTPUT_FILE_H +#include "label-text.h" + namespace diagnostics { /* RAII class for wrapping a FILE * that could be borrowed or owned, diff --git a/gcc/diagnostics/sarif-sink.cc b/gcc/diagnostics/sarif-sink.cc index 7526c16..c85a35e 100644 --- a/gcc/diagnostics/sarif-sink.cc +++ b/gcc/diagnostics/sarif-sink.cc @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostics/sink.h" #include "diagnostics/buffering.h" #include "diagnostics/dumping.h" +#include "diagnostics/logging.h" #include "json.h" #include "cpplib.h" #include "diagnostics/logical-locations.h" @@ -1944,6 +1945,8 @@ report_global_digraph (const lazily_created<digraphs::digraph> &ldg) std::unique_ptr<sarif_log> sarif_builder::flush_to_object () { + DIAGNOSTICS_LOG_SCOPE_PRINTF0 (m_context.get_logger (), + "diagnostics::sarif_builder::flush_to_object"); m_invocation_obj->prepare_to_flush (*this); std::unique_ptr<sarif_log> top = make_top_level_object (std::move (m_invocation_obj), @@ -1959,6 +1962,8 @@ sarif_builder::flush_to_object () void sarif_builder::flush_to_file (FILE *outf) { + DIAGNOSTICS_LOG_SCOPE_PRINTF0 (m_context.get_logger (), + "diagnostics::sarif_builder::flush_to_file"); std::unique_ptr<sarif_log> top = flush_to_object (); m_serialization_format->write_to_file (outf, *top); } @@ -3940,6 +3945,9 @@ public: on_report_diagnostic (const diagnostic_info &diagnostic, enum kind orig_diag_kind) final override { + DIAGNOSTICS_LOG_SCOPE_PRINTF0 + (get_logger (), + "diagnostics::sarif_sink::on_report_diagnostic"); m_builder.on_report_diagnostic (diagnostic, orig_diag_kind, m_buffer); } void on_diagram (const diagram &d) final override diff --git a/gcc/diagnostics/sink.h b/gcc/diagnostics/sink.h index 24eb707..aaa6c50 100644 --- a/gcc/diagnostics/sink.h +++ b/gcc/diagnostics/sink.h @@ -90,6 +90,8 @@ public: void DEBUG_FUNCTION dump () const { dump (stderr, 0); } + logging::logger *get_logger () { return m_context.get_logger (); } + protected: sink (context &dc) : m_context (dc), diff --git a/gcc/diagnostics/text-sink.cc b/gcc/diagnostics/text-sink.cc index 48b369c..d4cfb89 100644 --- a/gcc/diagnostics/text-sink.cc +++ b/gcc/diagnostics/text-sink.cc @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostics/text-sink.h" #include "diagnostics/buffering.h" #include "diagnostics/dumping.h" +#include "diagnostics/logging.h" #include "text-art/theme.h" /* Disable warnings about quoting issues in the pp_xxx calls below @@ -205,6 +206,11 @@ void text_sink::on_report_diagnostic (const diagnostic_info &diagnostic, enum kind orig_diag_kind) { + auto logger = get_logger (); + DIAGNOSTICS_LOG_SCOPE_PRINTF0 + (logger, + "diagnostics::text_sink::on_report_diagnostic"); + pretty_printer *pp = get_printer (); (*text_starter (&m_context)) (*this, &diagnostic); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index fa051f2..5c05217 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -37907,6 +37907,16 @@ compilation which is to be used as input to the next stage: for example, the output of the preprocessor, which is the input to the compiler proper. +@vindex GCC_DIAGNOSTICS_LOG +@item GCC_DIAGNOSTICS_LOG +If @env{GCC_DIAGNOSTICS_LOG} is set, then additional information +about the diagnostics subsystem will be emitted. If it is set to an empty +value, then the information will be written to stderr; otherwise, GCC will +attempt to open that file and write the information there. + +The precise content and format of the information is subject to change; +it is intended for use by GCC developers, rather than end-users. + @vindex GCC_COMPARE_DEBUG @item GCC_COMPARE_DEBUG Setting @env{GCC_COMPARE_DEBUG} is nearly equivalent to passing diff --git a/gcc/opts-diagnostic.cc b/gcc/opts-diagnostic.cc index 70d7d74..0e0296a 100644 --- a/gcc/opts-diagnostic.cc +++ b/gcc/opts-diagnostic.cc @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "diagnostic.h" #include "diagnostics/output-spec.h" +#include "diagnostics/logging.h" #include "opts.h" #include "options.h" @@ -78,6 +79,8 @@ handle_OPT_fdiagnostics_add_output_ (const gcc_options &opts, gcc_assert (line_table); const char *const option_name = "-fdiagnostics-add-output="; + DIAGNOSTICS_LOG_SCOPE_PRINTF2 (dc.get_logger (), + "handling: %s%s", option_name, arg); opt_spec_context ctxt (opts, dc, line_table, loc, option_name); auto sink = ctxt.parse_and_make_sink (arg, dc); if (!sink) @@ -97,6 +100,8 @@ handle_OPT_fdiagnostics_set_output_ (const gcc_options &opts, gcc_assert (line_table); const char *const option_name = "-fdiagnostics-set-output="; + DIAGNOSTICS_LOG_SCOPE_PRINTF2 (dc.get_logger (), + "handling: %s%s", option_name, arg); opt_spec_context ctxt (opts, dc, line_table, loc, option_name); auto sink = ctxt.parse_and_make_sink (arg, dc); if (!sink) |