Line data Source code
1 : /* Debugging code for logging what the diagnostics subsystem is doing.
2 : Copyright (C) 2025-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it under
8 : the terms of the GNU General Public License as published by the Free
9 : Software Foundation; either version 3, or (at your option) any later
10 : version.
11 :
12 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #ifndef GCC_DIAGNOSTICS_LOGGING_H
22 : #define GCC_DIAGNOSTICS_LOGGING_H
23 :
24 : #include "diagnostics/output-file.h"
25 : #include "diagnostics/option-id.h"
26 : #include "diagnostics/kinds.h"
27 :
28 : namespace diagnostics {
29 :
30 : namespace logging {
31 :
32 : /* A class for emitting a temporal log of what the diagnostics subsystem
33 : is doing, for debugging.
34 : We can't use pretty_printer here as we could potentially be debugging
35 : pretty-printing itself. */
36 :
37 0 : class logger
38 : {
39 : public:
40 : logger (output_file outfile);
41 :
42 : /* High-level functions that emit a line of text. */
43 : void log_printf (const char *fmt, ...)
44 : __attribute__ ((__format__ (printf, 2, 3)));
45 : void log_bool_return (const char *function_name, bool retval);
46 :
47 : /* Lower-level functions for building up a line of text. */
48 : void emit_indent () const;
49 : void emit_newline () const;
50 :
51 0 : FILE *get_stream () const
52 : {
53 0 : return m_outfile.get_open_file ();
54 : }
55 :
56 0 : int get_indent () const { return m_log_depth * 2; }
57 :
58 0 : void inc_depth () { m_log_depth++; }
59 0 : void dec_depth () { m_log_depth--; }
60 :
61 : private:
62 : output_file m_outfile;
63 : int m_log_depth;
64 : };
65 :
66 : /* RAII class for pushing/popping depth within a logger. */
67 :
68 : class auto_inc_depth
69 : {
70 : public:
71 219724936 : auto_inc_depth (logger *log)
72 219724936 : : m_logger (log)
73 : {
74 219724936 : if (m_logger)
75 0 : m_logger->inc_depth ();
76 : }
77 327799648 : ~auto_inc_depth ()
78 : {
79 327799648 : if (m_logger)
80 0 : m_logger->dec_depth ();
81 : }
82 :
83 : private:
84 : logger *m_logger;
85 : };
86 :
87 : /* Class for debugging function call parameters. */
88 :
89 : class log_function_params
90 : {
91 : public:
92 216794222 : log_function_params (logger *logger_, const char *name)
93 216794222 : : m_logger (logger_),
94 216794222 : m_first_param (true)
95 : {
96 216794222 : if (m_logger)
97 : {
98 0 : m_logger->emit_indent ();
99 0 : fprintf (m_logger->get_stream (), "%s (", name);
100 : }
101 216794222 : }
102 216794222 : ~log_function_params ()
103 : {
104 216794222 : if (m_logger)
105 : {
106 0 : fprintf (m_logger->get_stream (), ")");
107 0 : m_logger->emit_newline ();
108 : }
109 216794222 : }
110 :
111 : log_function_params &
112 203006513 : log_param_string (const char *name, const char *value)
113 : {
114 203006513 : if (m_logger)
115 : {
116 0 : add_any_comma ();
117 0 : fprintf (m_logger->get_stream (), "%s: \"%s\"", name, value);
118 : }
119 203006513 : return *this;
120 : }
121 :
122 : log_function_params &
123 20092717 : log_param_location_t (const char *name, location_t value)
124 : {
125 20092717 : if (m_logger)
126 : {
127 0 : add_any_comma ();
128 0 : fprintf (m_logger->get_stream (),
129 : "%s: " HOST_SIZE_T_PRINT_HEX,
130 : name, (fmt_size_t)value);
131 : }
132 20092717 : return *this;
133 : }
134 :
135 : log_function_params &
136 37193 : log_param_rich_location (const char *name, const rich_location *richloc)
137 : {
138 37193 : if (m_logger)
139 : {
140 0 : add_any_comma ();
141 0 : fprintf (m_logger->get_stream (),
142 : "%s: %p",
143 : name, const_cast<void *> ((const void *)richloc));
144 : }
145 37193 : return *this;
146 : }
147 :
148 : log_function_params &
149 207860446 : log_param_option_id (const char *name, diagnostics::option_id value)
150 : {
151 207860446 : if (m_logger)
152 : {
153 0 : add_any_comma ();
154 0 : fprintf (m_logger->get_stream (), "%s: %i", name, value.m_idx);
155 : }
156 207860446 : return *this;
157 : }
158 :
159 : log_function_params &
160 106596784 : log_param_kind (const char *name, enum diagnostics::kind value)
161 : {
162 106596784 : if (m_logger)
163 : {
164 0 : add_any_comma ();
165 0 : fprintf (m_logger->get_stream (), "%s: %s",
166 : name, get_debug_string_for_kind (value));
167 : }
168 106596784 : return *this;
169 : }
170 :
171 : log_function_params &
172 25422 : log_param_uhwi (const char *name, unsigned HOST_WIDE_INT value)
173 : {
174 25422 : if (m_logger)
175 : {
176 0 : add_any_comma ();
177 0 : fprintf (m_logger->get_stream (),
178 : "%s: " HOST_WIDE_INT_PRINT_DEC,
179 : name, value);
180 : }
181 25422 : return *this;
182 : }
183 :
184 : log_function_params &
185 25422 : log_params_n_gmsgids (unsigned HOST_WIDE_INT n,
186 : const char *singular_gmsgid,
187 : const char *plural_gmsgid)
188 : {
189 25422 : return log_param_uhwi ("n", n)
190 25422 : .log_param_string ("singular_gmsgid", singular_gmsgid)
191 25422 : .log_param_string ("plural_gmsgid", plural_gmsgid);
192 : }
193 :
194 : private:
195 : void
196 0 : add_any_comma ()
197 : {
198 0 : gcc_assert (m_logger);
199 0 : if (m_first_param)
200 0 : m_first_param = false;
201 : else
202 0 : fprintf (m_logger->get_stream (), ", ");
203 0 : }
204 :
205 : logger *m_logger;
206 : bool m_first_param;
207 : };
208 :
209 : } // namespace logging
210 : } // namespace diagnostics
211 :
212 : /* Various macros for logging a formatted line, and indenting
213 : further log messages within a scope. */
214 :
215 : #define DIAGNOSTICS_LOG_SCOPE_PRINTF0(LOGGER, FMT) \
216 : if (LOGGER) \
217 : (LOGGER)->log_printf ((FMT)); \
218 : diagnostics::logging::auto_inc_depth depth_sentinel (LOGGER);
219 :
220 : #define DIAGNOSTICS_LOG_SCOPE_PRINTF1(LOGGER, FMT, ARG0) \
221 : if (LOGGER) \
222 : (LOGGER)->log_printf ((FMT), (ARG0)); \
223 : diagnostics::logging::auto_inc_depth depth_sentinel (LOGGER);
224 :
225 : #define DIAGNOSTICS_LOG_SCOPE_PRINTF2(LOGGER, FMT, ARG0, ARG1) \
226 : if (LOGGER) \
227 : (LOGGER)->log_printf ((FMT), (ARG0), (ARG1)); \
228 : diagnostics::logging::auto_inc_depth depth_sentinel (LOGGER);
229 :
230 : #endif /* ! GCC_DIAGNOSTICS_LOGGING_H */
|