aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2025-08-29 14:39:37 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2025-08-29 14:39:37 -0400
commit9e98b37f32f8bff72885904fc66ea7ec8fefec58 (patch)
tree3d109ac25532ba394efbf36ed868097fec7910c6
parentba9d4b3ce59432f3e7cef5c650b088a12e7ff877 (diff)
downloadgcc-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>
-rw-r--r--gcc/Makefile.in1
-rw-r--r--gcc/analyzer/pending-diagnostic.cc18
-rw-r--r--gcc/diagnostic-global-context.cc267
-rw-r--r--gcc/diagnostics/context.cc161
-rw-r--r--gcc/diagnostics/context.h31
-rw-r--r--gcc/diagnostics/html-sink.cc6
-rw-r--r--gcc/diagnostics/kinds.h1
-rw-r--r--gcc/diagnostics/logging.cc72
-rw-r--r--gcc/diagnostics/logging.h230
-rw-r--r--gcc/diagnostics/output-file.h2
-rw-r--r--gcc/diagnostics/sarif-sink.cc8
-rw-r--r--gcc/diagnostics/sink.h2
-rw-r--r--gcc/diagnostics/text-sink.cc6
-rw-r--r--gcc/doc/invoke.texi10
-rw-r--r--gcc/opts-diagnostic.cc5
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)