xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/analyzer/analyzer-logging.cc (revision c64d4171c6f912972428361000d29636c687d68b)
1 /* Hierarchical log messages for the analyzer.
2    Copyright (C) 2014-2020 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
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11 
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License 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 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "toplev.h" /* for print_version */
25 #include "pretty-print.h" /* for print_version */
26 #include "diagnostic.h"
27 #include "tree-diagnostic.h"
28 
29 #include "analyzer/analyzer-logging.h"
30 
31 #if ENABLE_ANALYZER
32 
33 namespace ana {
34 
35 /* Implementation of class logger.  */
36 
37 /* ctor for logger.  */
38 
39 logger::logger (FILE *f_out,
40 		int, /* flags */
41 		int /* verbosity */,
42 		const pretty_printer &reference_pp) :
43   m_refcount (0),
44   m_f_out (f_out),
45   m_indent_level (0),
46   m_log_refcount_changes (false),
47   m_pp (reference_pp.clone ())
48 {
49   pp_show_color (m_pp) = 0;
50   pp_buffer (m_pp)->stream = f_out;
51 
52   /* %qE in logs for SSA_NAMEs should show the ssa names, rather than
53      trying to prettify things by showing the underlying var.  */
54   pp_format_decoder (m_pp) = default_tree_printer;
55 
56   /* Begin the log by writing the GCC version.  */
57   print_version (f_out, "", false);
58 }
59 
60 /* The destructor for logger, invoked via
61    the decref method when the refcount hits zero.
62    Note that we do not close the underlying FILE * (m_f_out).  */
63 
64 logger::~logger ()
65 {
66   /* This should be the last message emitted.  */
67   log ("%s", __PRETTY_FUNCTION__);
68   gcc_assert (m_refcount == 0);
69   delete m_pp;
70 }
71 
72 /* Increment the reference count of the logger.  */
73 
74 void
75 logger::incref (const char *reason)
76 {
77   m_refcount++;
78   if (m_log_refcount_changes)
79     log ("%s: reason: %s refcount now %i ",
80 	 __PRETTY_FUNCTION__, reason, m_refcount);
81 }
82 
83 /* Decrement the reference count of the logger,
84    deleting it if nothing is referring to it.  */
85 
86 void
87 logger::decref (const char *reason)
88 {
89   gcc_assert (m_refcount > 0);
90   --m_refcount;
91   if (m_log_refcount_changes)
92     log ("%s: reason: %s refcount now %i",
93 	 __PRETTY_FUNCTION__, reason, m_refcount);
94   if (m_refcount == 0)
95     delete this;
96 }
97 
98 /* Write a formatted message to the log, by calling the log_va method.  */
99 
100 void
101 logger::log (const char *fmt, ...)
102 {
103   va_list ap;
104   va_start (ap, fmt);
105   log_va (fmt, &ap);
106   va_end (ap);
107 }
108 
109 /* Write an indented line to the log file.
110 
111    We explicitly flush after each line: if something crashes the process,
112    we want the logfile/stream to contain the most up-to-date hint about the
113    last thing that was happening, without it being hidden in an in-process
114    buffer.  */
115 
116 void
117 logger::log_va (const char *fmt, va_list *ap)
118 {
119   start_log_line ();
120   log_va_partial (fmt, ap);
121   end_log_line ();
122 }
123 
124 void
125 logger::start_log_line ()
126 {
127   for (int i = 0; i < m_indent_level; i++)
128     fputc (' ', m_f_out);
129 }
130 
131 void
132 logger::log_partial (const char *fmt, ...)
133 {
134   va_list ap;
135   va_start (ap, fmt);
136   log_va_partial (fmt, &ap);
137   va_end (ap);
138 }
139 
140 void
141 logger::log_va_partial (const char *fmt, va_list *ap)
142 {
143   text_info text;
144   text.format_spec = fmt;
145   text.args_ptr = ap;
146   text.err_no = 0;
147   pp_format (m_pp, &text);
148   pp_output_formatted_text (m_pp);
149 }
150 
151 void
152 logger::end_log_line ()
153 {
154   pp_flush (m_pp);
155   pp_clear_output_area (m_pp);
156   fprintf (m_f_out, "\n");
157   fflush (m_f_out);
158 }
159 
160 /* Record the entry within a particular scope, indenting subsequent
161    log lines accordingly.  */
162 
163 void
164 logger::enter_scope (const char *scope_name)
165 {
166   log ("entering: %s", scope_name);
167   m_indent_level += 1;
168 }
169 
170 void
171 logger::enter_scope (const char *scope_name, const char *fmt, va_list *ap)
172 {
173   start_log_line ();
174   log_partial ("entering: %s: ", scope_name);
175   log_va_partial (fmt, ap);
176   end_log_line ();
177 
178   m_indent_level += 1;
179 }
180 
181 
182 /* Record the exit from a particular scope, restoring the indent level to
183    before the scope was entered.  */
184 
185 void
186 logger::exit_scope (const char *scope_name)
187 {
188   if (m_indent_level)
189     m_indent_level -= 1;
190   else
191     log ("(mismatching indentation)");
192   log ("exiting: %s", scope_name);
193 }
194 
195 /* Implementation of class log_user.  */
196 
197 /* The constructor for log_user.  */
198 
199 log_user::log_user (logger *logger) : m_logger (logger)
200 {
201   if (m_logger)
202     m_logger->incref("log_user ctor");
203 }
204 
205 /* The destructor for log_user.  */
206 
207 log_user::~log_user ()
208 {
209   if (m_logger)
210     m_logger->decref("log_user dtor");
211 }
212 
213 /* Set the logger for a log_user, managing the reference counts
214    of the old and new logger (either of which might be NULL).  */
215 
216 void
217 log_user::set_logger (logger *logger)
218 {
219   if (logger)
220     logger->incref ("log_user::set_logger");
221   if (m_logger)
222     m_logger->decref ("log_user::set_logger");
223   m_logger = logger;
224 }
225 
226 } // namespace ana
227 
228 #endif /* #if ENABLE_ANALYZER */
229