diff options
Diffstat (limited to 'gcc/diagnostics/logging.h')
-rw-r--r-- | gcc/diagnostics/logging.h | 230 |
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 */ |