aboutsummaryrefslogtreecommitdiff
path: root/gcc/diagnostics/logging.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/diagnostics/logging.h')
-rw-r--r--gcc/diagnostics/logging.h230
1 files changed, 230 insertions, 0 deletions
diff --git a/gcc/diagnostics/logging.h b/gcc/diagnostics/logging.h
new file mode 100644
index 0000000..34ca95b
--- /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, (fmt_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 */