1 | /* Default error handlers for CPP Library. |
---|---|
2 | Copyright (C) 1986-2025 Free Software Foundation, Inc. |
3 | Written by Per Bothner, 1994. |
4 | Based on CCCP program by Paul Rubin, June 1986 |
5 | Adapted to ANSI C, Richard Stallman, Jan 1987 |
6 | |
7 | This program is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License as published by the |
9 | Free Software Foundation; either version 3, or (at your option) any |
10 | later version. |
11 | |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with this program; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. |
20 | |
21 | In other words, you are welcome to use, share and improve this program. |
22 | You are forbidden to forbid anyone else to use, share and improve |
23 | what you give them. Help stamp out software-hoarding! */ |
24 | |
25 | #include "config.h" |
26 | #include "system.h" |
27 | #include "cpplib.h" |
28 | #include "internal.h" |
29 | |
30 | /* Get a location_t for the current location in PFILE, |
31 | generally that of the previously lexed token. */ |
32 | |
33 | location_t |
34 | cpp_diagnostic_get_current_location (cpp_reader *pfile) |
35 | { |
36 | if (CPP_OPTION (pfile, traditional)) |
37 | { |
38 | if (pfile->state.in_directive) |
39 | return pfile->directive_line; |
40 | else |
41 | return pfile->line_table->highest_line; |
42 | } |
43 | /* We don't want to refer to a token before the beginning of the |
44 | current run -- that is invalid. */ |
45 | else if (pfile->cur_token == pfile->cur_run->base) |
46 | { |
47 | return 0; |
48 | } |
49 | else |
50 | { |
51 | return pfile->cur_token[-1].src_loc; |
52 | } |
53 | } |
54 | |
55 | /* Sometimes a diagnostic needs to be generated before libcpp has been able |
56 | to generate a valid location for the current token; in that case, the |
57 | non-zero location returned by this function is the preferred one to use. */ |
58 | |
59 | location_t |
60 | cpp_get_diagnostic_override_loc (const cpp_reader *pfile) |
61 | { |
62 | return pfile->diagnostic_override_loc; |
63 | } |
64 | |
65 | /* Print a diagnostic at the given location. */ |
66 | |
67 | ATTRIBUTE_CPP_PPDIAG (5, 0) |
68 | static bool |
69 | cpp_diagnostic_at (cpp_reader * pfile, enum cpp_diagnostic_level level, |
70 | enum cpp_warning_reason reason, rich_location *richloc, |
71 | const char *msgid, va_list *ap) |
72 | { |
73 | if (!pfile->cb.diagnostic) |
74 | abort (); |
75 | if (pfile->diagnostic_override_loc && level != CPP_DL_NOTE) |
76 | { |
77 | rich_location rc2{pfile->line_table, pfile->diagnostic_override_loc}; |
78 | rc2.set_escape_on_output (richloc->escape_on_output_p ()); |
79 | return pfile->cb.diagnostic (pfile, level, reason, &rc2, _(msgid), ap); |
80 | } |
81 | return pfile->cb.diagnostic (pfile, level, reason, richloc, _(msgid), ap); |
82 | } |
83 | |
84 | /* Print a diagnostic at the location of the previously lexed token. */ |
85 | |
86 | ATTRIBUTE_CPP_PPDIAG (4, 0) |
87 | static bool |
88 | cpp_diagnostic (cpp_reader * pfile, enum cpp_diagnostic_level level, |
89 | enum cpp_warning_reason reason, |
90 | const char *msgid, va_list *ap) |
91 | { |
92 | location_t src_loc = cpp_diagnostic_get_current_location (pfile); |
93 | rich_location richloc (pfile->line_table, src_loc); |
94 | return cpp_diagnostic_at (pfile, level, reason, richloc: &richloc, msgid, ap); |
95 | } |
96 | |
97 | /* Print a warning or error, depending on the value of LEVEL. */ |
98 | |
99 | bool |
100 | cpp_error (cpp_reader * pfile, enum cpp_diagnostic_level level, |
101 | const char *msgid, ...) |
102 | { |
103 | va_list ap; |
104 | bool ret; |
105 | |
106 | va_start (ap, msgid); |
107 | |
108 | ret = cpp_diagnostic (pfile, level, reason: CPP_W_NONE, msgid, ap: &ap); |
109 | |
110 | va_end (ap); |
111 | return ret; |
112 | } |
113 | |
114 | /* Print a warning. The warning reason may be given in REASON. */ |
115 | |
116 | bool |
117 | cpp_warning (cpp_reader * pfile, enum cpp_warning_reason reason, |
118 | const char *msgid, ...) |
119 | { |
120 | va_list ap; |
121 | bool ret; |
122 | |
123 | va_start (ap, msgid); |
124 | |
125 | ret = cpp_diagnostic (pfile, level: CPP_DL_WARNING, reason, msgid, ap: &ap); |
126 | |
127 | va_end (ap); |
128 | return ret; |
129 | } |
130 | |
131 | /* Print a pedantic warning. The warning reason may be given in REASON. */ |
132 | |
133 | bool |
134 | cpp_pedwarning (cpp_reader * pfile, enum cpp_warning_reason reason, |
135 | const char *msgid, ...) |
136 | { |
137 | va_list ap; |
138 | bool ret; |
139 | |
140 | va_start (ap, msgid); |
141 | |
142 | ret = cpp_diagnostic (pfile, level: CPP_DL_PEDWARN, reason, msgid, ap: &ap); |
143 | |
144 | va_end (ap); |
145 | return ret; |
146 | } |
147 | |
148 | /* Print a warning, including system headers. The warning reason may be |
149 | given in REASON. */ |
150 | |
151 | bool |
152 | cpp_warning_syshdr (cpp_reader * pfile, enum cpp_warning_reason reason, |
153 | const char *msgid, ...) |
154 | { |
155 | va_list ap; |
156 | bool ret; |
157 | |
158 | va_start (ap, msgid); |
159 | |
160 | ret = cpp_diagnostic (pfile, level: CPP_DL_WARNING_SYSHDR, reason, msgid, ap: &ap); |
161 | |
162 | va_end (ap); |
163 | return ret; |
164 | } |
165 | |
166 | /* As cpp_warning above, but use RICHLOC as the location of the diagnostic. */ |
167 | |
168 | bool cpp_warning_at (cpp_reader *pfile, enum cpp_warning_reason reason, |
169 | rich_location *richloc, const char *msgid, ...) |
170 | { |
171 | va_list ap; |
172 | bool ret; |
173 | |
174 | va_start (ap, msgid); |
175 | |
176 | ret = cpp_diagnostic_at (pfile, level: CPP_DL_WARNING, reason, richloc, |
177 | msgid, ap: &ap); |
178 | |
179 | va_end (ap); |
180 | return ret; |
181 | |
182 | } |
183 | |
184 | /* As cpp_pedwarning above, but use RICHLOC as the location of the |
185 | diagnostic. */ |
186 | |
187 | bool |
188 | cpp_pedwarning_at (cpp_reader * pfile, enum cpp_warning_reason reason, |
189 | rich_location *richloc, const char *msgid, ...) |
190 | { |
191 | va_list ap; |
192 | bool ret; |
193 | |
194 | va_start (ap, msgid); |
195 | |
196 | ret = cpp_diagnostic_at (pfile, level: CPP_DL_PEDWARN, reason, richloc, |
197 | msgid, ap: &ap); |
198 | |
199 | va_end (ap); |
200 | return ret; |
201 | } |
202 | |
203 | /* Print a diagnostic at a specific location. */ |
204 | |
205 | ATTRIBUTE_CPP_PPDIAG (6, 0) |
206 | static bool |
207 | cpp_diagnostic_with_line (cpp_reader * pfile, enum cpp_diagnostic_level level, |
208 | enum cpp_warning_reason reason, |
209 | location_t src_loc, unsigned int column, |
210 | const char *msgid, va_list *ap) |
211 | { |
212 | bool ret; |
213 | |
214 | if (!pfile->cb.diagnostic) |
215 | abort (); |
216 | /* Don't override note locations, which will likely make the note |
217 | more confusing. */ |
218 | const bool do_loc_override |
219 | = pfile->diagnostic_override_loc && level != CPP_DL_NOTE; |
220 | if (do_loc_override) |
221 | src_loc = pfile->diagnostic_override_loc; |
222 | rich_location richloc (pfile->line_table, src_loc); |
223 | if (column && !do_loc_override) |
224 | richloc.override_column (column); |
225 | ret = pfile->cb.diagnostic (pfile, level, reason, &richloc, _(msgid), ap); |
226 | |
227 | return ret; |
228 | } |
229 | |
230 | /* Print a warning or error, depending on the value of LEVEL. */ |
231 | |
232 | bool |
233 | cpp_error_with_line (cpp_reader *pfile, enum cpp_diagnostic_level level, |
234 | location_t src_loc, unsigned int column, |
235 | const char *msgid, ...) |
236 | { |
237 | va_list ap; |
238 | bool ret; |
239 | |
240 | va_start (ap, msgid); |
241 | |
242 | ret = cpp_diagnostic_with_line (pfile, level, reason: CPP_W_NONE, src_loc, |
243 | column, msgid, ap: &ap); |
244 | |
245 | va_end (ap); |
246 | return ret; |
247 | } |
248 | |
249 | /* Print a warning. The warning reason may be given in REASON. */ |
250 | |
251 | bool |
252 | cpp_warning_with_line (cpp_reader *pfile, enum cpp_warning_reason reason, |
253 | location_t src_loc, unsigned int column, |
254 | const char *msgid, ...) |
255 | { |
256 | va_list ap; |
257 | bool ret; |
258 | |
259 | va_start (ap, msgid); |
260 | |
261 | ret = cpp_diagnostic_with_line (pfile, level: CPP_DL_WARNING, reason, src_loc, |
262 | column, msgid, ap: &ap); |
263 | |
264 | va_end (ap); |
265 | return ret; |
266 | } |
267 | |
268 | /* Print a pedantic warning. The warning reason may be given in REASON. */ |
269 | |
270 | bool |
271 | cpp_pedwarning_with_line (cpp_reader *pfile, enum cpp_warning_reason reason, |
272 | location_t src_loc, unsigned int column, |
273 | const char *msgid, ...) |
274 | { |
275 | va_list ap; |
276 | bool ret; |
277 | |
278 | va_start (ap, msgid); |
279 | |
280 | ret = cpp_diagnostic_with_line (pfile, level: CPP_DL_PEDWARN, reason, src_loc, |
281 | column, msgid, ap: &ap); |
282 | |
283 | va_end (ap); |
284 | return ret; |
285 | } |
286 | |
287 | /* Print a warning, including system headers. The warning reason may be |
288 | given in REASON. */ |
289 | |
290 | bool |
291 | cpp_warning_with_line_syshdr (cpp_reader *pfile, enum cpp_warning_reason reason, |
292 | location_t src_loc, unsigned int column, |
293 | const char *msgid, ...) |
294 | { |
295 | va_list ap; |
296 | bool ret; |
297 | |
298 | va_start (ap, msgid); |
299 | |
300 | ret = cpp_diagnostic_with_line (pfile, level: CPP_DL_WARNING_SYSHDR, reason, src_loc, |
301 | column, msgid, ap: &ap); |
302 | |
303 | va_end (ap); |
304 | return ret; |
305 | } |
306 | |
307 | /* As cpp_error, but use SRC_LOC as the location of the error, without |
308 | a column override. */ |
309 | |
310 | bool |
311 | cpp_error_at (cpp_reader * pfile, enum cpp_diagnostic_level level, |
312 | location_t src_loc, const char *msgid, ...) |
313 | { |
314 | va_list ap; |
315 | bool ret; |
316 | |
317 | va_start (ap, msgid); |
318 | |
319 | rich_location richloc (pfile->line_table, src_loc); |
320 | ret = cpp_diagnostic_at (pfile, level, reason: CPP_W_NONE, richloc: &richloc, |
321 | msgid, ap: &ap); |
322 | |
323 | va_end (ap); |
324 | return ret; |
325 | } |
326 | |
327 | /* As cpp_error, but use RICHLOC as the location of the error, without |
328 | a column override. */ |
329 | |
330 | bool |
331 | cpp_error_at (cpp_reader * pfile, enum cpp_diagnostic_level level, |
332 | rich_location *richloc, const char *msgid, ...) |
333 | { |
334 | va_list ap; |
335 | bool ret; |
336 | |
337 | va_start (ap, msgid); |
338 | |
339 | ret = cpp_diagnostic_at (pfile, level, reason: CPP_W_NONE, richloc, |
340 | msgid, ap: &ap); |
341 | |
342 | va_end (ap); |
343 | return ret; |
344 | } |
345 | |
346 | /* Print a warning or error, depending on the value of LEVEL. Include |
347 | information from errno. */ |
348 | |
349 | bool |
350 | cpp_errno (cpp_reader *pfile, enum cpp_diagnostic_level level, |
351 | const char *msgid) |
352 | { |
353 | return cpp_error (pfile, level, msgid: "%s: %s", _(msgid), xstrerror (errno)); |
354 | } |
355 | |
356 | /* Print a warning or error, depending on the value of LEVEL. Include |
357 | information from errno. Unlike cpp_errno, the argument is a filename |
358 | that is not localized, but "" is replaced with localized "stdout". */ |
359 | |
360 | bool |
361 | cpp_errno_filename (cpp_reader *pfile, enum cpp_diagnostic_level level, |
362 | const char *filename, |
363 | location_t loc) |
364 | { |
365 | if (filename[0] == '\0') |
366 | filename = _("stdout"); |
367 | |
368 | return cpp_error_at (pfile, level, src_loc: loc, msgid: "%s: %s", filename, |
369 | xstrerror (errno)); |
370 | } |
371 | |
372 | cpp_auto_suppress_diagnostics::cpp_auto_suppress_diagnostics (cpp_reader *pfile) |
373 | : m_pfile (pfile), m_cb (pfile->cb.diagnostic) |
374 | { |
375 | m_pfile->cb.diagnostic |
376 | = [] (cpp_reader *, cpp_diagnostic_level, cpp_warning_reason, |
377 | rich_location *, const char *, va_list *) |
378 | { |
379 | return true; |
380 | }; |
381 | } |
382 | |
383 | cpp_auto_suppress_diagnostics::~cpp_auto_suppress_diagnostics () |
384 | { |
385 | m_pfile->cb.diagnostic = m_cb; |
386 | } |
387 |
Definitions
- cpp_diagnostic_get_current_location
- cpp_get_diagnostic_override_loc
- cpp_diagnostic_at
- cpp_diagnostic
- cpp_error
- cpp_warning
- cpp_pedwarning
- cpp_warning_syshdr
- cpp_warning_at
- cpp_pedwarning_at
- cpp_diagnostic_with_line
- cpp_error_with_line
- cpp_warning_with_line
- cpp_pedwarning_with_line
- cpp_warning_with_line_syshdr
- cpp_error_at
- cpp_error_at
- cpp_errno
- cpp_errno_filename
- cpp_auto_suppress_diagnostics
Learn to use CMake with our Intro Training
Find out more