GCC Middle and Back End API Reference
pretty-print-format-impl.h
Go to the documentation of this file.
1/* Implementation detail of pp_format.
2 Copyright (C) 2002-2025 Free Software Foundation, Inc.
3 Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#ifndef GCC_PRETTY_PRINT_FORMAT_IMPL_H
22#define GCC_PRETTY_PRINT_FORMAT_IMPL_H
23
24#include "pretty-print.h"
25#include "diagnostic-event-id.h"
26
27/* A struct representing a pending item to be printed within
28 pp_format.
29
30 These can represent:
31 - a run of text within one of the output_buffers's obstacks
32 - begin/end named color
33 - open/close quote
34 - begin/end URL
35 - event IDs
36 - custom data (for the formatter, for the pretty_printer,
37 or the output format)
38
39 These are built into pp_token_list instances.
40
41 Doing so allows for interaction between:
42
43 - pretty_printer formatting codes (such as C++'s %H and %I,
44 which can't be printed until we've seen both)
45
46 - output formats, such as text vs SARIF (so each can handle URLs
47 and event IDs it its own way)
48
49 - optimization records, where we want to stash data into the
50 formatted messages
51
52 - urlifiers: these can be run in phase 3 of formatting
53
54 without needing lots of fragile logic on char pointers.
55
56 To avoid needing lots of heap allocation/deallocation, pp_token
57 instances are allocated in the pretty_printer's chunk_obstack:
58 they must not outlive phase 3 of formatting of the given
59 pp_formatted_chunks level. */
60
62{
63public:
64 enum class kind
65 {
66 text,
67
70
73
75 end_url,
76
78
80
82 };
83
84 pp_token (enum kind k);
85
86 pp_token (const pp_token &) = delete;
87 pp_token (pp_token &&) = delete;
88
89 virtual ~pp_token () = default;
90
91 pp_token &operator= (const pp_token &) = delete;
93
94 void dump (FILE *out) const;
95 void DEBUG_FUNCTION dump () const { dump (stderr); }
96
97 static void *operator new (size_t sz, obstack &s);
98 static void operator delete (void *);
99
101
102 // Intrusive doubly-linked list
105};
106
107/* Subclasses of pp_token for the various kinds of token. */
108
109struct pp_token_text : public pp_token
110{
111 pp_token_text (label_text &&value)
112 : pp_token (kind::text),
113 m_value (std::move (value))
114 {
115 gcc_assert (m_value.get ());
116 }
117
118 label_text m_value;
119};
120
121template <>
122template <>
123inline bool
125{
126 return tok->m_kind == pp_token::kind::text;
127}
128
129template <>
130template <>
131inline bool
133{
134 return tok->m_kind == pp_token::kind::text;
135}
136
138{
139 pp_token_begin_color (label_text &&value)
141 m_value (std::move (value))
142 {
143 gcc_assert (m_value.get ());
144 }
145
146 label_text m_value;
147};
148
149template <>
150template <>
151inline bool
156
157template <>
158template <>
159inline bool
164
166{
169 {
170 }
171};
172
174{
179};
180
182{
185 {
186 }
187};
188
190{
191 pp_token_begin_url (label_text &&value)
193 m_value (std::move (value))
194 {
195 gcc_assert (m_value.get ());
196 }
197
198 label_text m_value;
199};
200
201template <>
202template <>
203inline bool
208
209template <>
210template <>
211inline bool
216
218{
221 {
222 }
223};
224
236
237template <>
238template <>
239inline bool
244
245template <>
246template <>
247inline bool
252
254{
255 class value
256 {
257 public:
258 virtual ~value () {}
259 virtual void dump (FILE *out) const = 0;
260
261 /* Hook for lowering a custom_data token to standard tokens.
262 Return true and write to OUT if possible.
263 Return false for custom_data that is to be handled by
264 the token_printer. */
265 virtual bool as_standard_tokens (pp_token_list &out) = 0;
266 };
267
268 pp_token_custom_data (std::unique_ptr<value> val)
270 m_value (std::move (val))
271 {
272 gcc_assert (m_value.get ());
273 }
274
275 std::unique_ptr<value> m_value;
276};
277
278template <>
279template <>
280inline bool
285
286template <>
287template <>
288inline bool
293
294/* A list of pp_token, with ownership of the tokens, using
295 a particular obstack to allocate its tokens. These are
296 also allocated on the obstack during formatting (or, occasionally,
297 the stack). */
298
300{
301public:
302 // Allocate a new pp_token_list within S.
304 {
305 return new (s) pp_token_list (s);
306 }
307 static void *operator new (size_t sz, obstack &s);
308 static void operator delete (void *);
309
311 pp_token_list (const pp_token_list &) = delete;
313
315
318
319/* Make a pp_token of the given subclass, using the relevant obstack to provide
320 the memory. The pp_token must therefore not outlive the current
321 pp_formatted_chunks level during formatting. */
322 template<typename Subclass, typename... Args>
323 std::unique_ptr<pp_token>
324 make_token (Args&&... args)
325 {
326 return std::unique_ptr<pp_token>
327 (new (m_obstack) Subclass (std::forward<Args> (args)...));
328 }
329
330 template<typename Subclass, typename... Args>
331 void push_back (Args&&... args)
332 {
333 auto tok = make_token<Subclass> (std::forward<Args> (args)...);
334 push_back (std::move (tok));
335 }
336 void push_back_text (label_text &&text);
337 void push_back (std::unique_ptr<pp_token> tok);
338 void push_back_list (pp_token_list &&list);
339
340 std::unique_ptr<pp_token> pop_front ();
341
342 std::unique_ptr<pp_token> remove_token (pp_token *tok);
343
344 void insert_after (std::unique_ptr<pp_token> new_tok,
345 pp_token *relative_tok);
346
347 void replace_custom_tokens ();
349 void apply_urlifier (const urlifier &urlifier);
350
351 void dump (FILE *out) const;
352 void DEBUG_FUNCTION dump () const { dump (stderr); }
353
355
358};
359
360/* The pp_formatted_chunks data structure forms a stack of the results from the
361 first phase of formatting (pp_format) which have not yet been
362 output (pp_output_formatted_text). A stack is necessary because
363 the diagnostic starter may decide to generate its own output by way
364 of the formatter. */
366{
367 friend class pretty_printer;
368 friend class pp_markup::context;
369 friend class output_buffer;
370
371public:
372 pp_token_list * const * get_token_lists () const { return m_args; }
373
374 void append_formatted_chunk (obstack &s, const char *content);
375
376 void dump (FILE *out, int indent) const;
377 void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
378
379 // For use in selftests
380 pp_formatted_chunks *get_prev () const { return m_prev; }
381
382private:
383 /* Pointer to previous level on the stack. */
385
386 /* Array of chunks to output. Each chunk is a doubly-linked list of
387 pp_token.
388
389 The chunks can be printed via pp_formatted_chunks::dump ().
390
391 In the first phase of formatting, even-numbered chunks are
392 to be output verbatim, odd-numbered chunks are format specifiers.
393 For example, given:
394 pp_format (pp,
395 "foo: %i, bar: %s, opt: %qs",
396 42, "baz", "-foption");
397
398 after phase 1 we might have:
399 (gdb) call buffer->cur_chunk_array->dump()
400 0: [TEXT("foo: ")]
401 1: [TEXT("i")]
402 2: [TEXT(", bar: ")]
403 3: [TEXT("s")]
404 4: [TEXT(", opt: ")]
405 5: [TEXT("qs")]
406
407 The second phase replaces all odd-numbered chunks with formatted
408 token lists. In the above example, after phase 2 we might have:
409 (gdb) call pp->m_buffer->cur_chunk_array->dump()
410 0: [TEXT("foo: ")]
411 1: [TEXT("42")]
412 2: [TEXT(", bar: ")]
413 3: [TEXT("baz")]
414 4: [TEXT(", opt: ")]
415 5: [BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
416 For example the %qs has become the three tokens:
417 [BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
418
419 The third phase (in pp_output_formatted_text):
420
421 (1) merges the tokens from all the chunks into one list,
422 giving e.g.
423 (gdb) call tokens.dump()
424 [TEXT("foo: "), TEXT("42"), TEXT(", bar: "), TEXT("baz"),
425 TEXT(", opt: "), BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
426
427 (2) lowers some custom tokens into non-custom tokens
428
429 (3) merges consecutive text tokens, giving e.g.:
430 (gdb) call tokens.dump()
431 [TEXT("foo: 42, bar: baz, option: "),
432 BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
433
434 (4) if provided with a urlifier, tries to apply it to quoted text,
435 giving e.g:
436 (gdb) call tokens.dump()
437 [TEXT("foo: 42, bar: baz, option: "), BEGIN_QUOTE,
438 BEGIN_URL("http://example.com"), TEXT("-foption"), END_URL, END_QUOTE]
439
440 (5) emits all tokens in sequence with appropriate line-wrapping. This
441 can be overridded via the pretty_printer's token_printer, allowing for
442 output formats to e.g. override how URLs are handled, or to handle
443 custom_data that wasn't lowered in (2) above, e.g. for handling JSON
444 output of optimization records. */
446
447 /* The pp_tokens, pp_token_lists, and the accumulated text buffers are
448 allocated within the output_buffer's chunk_obstack. In the above
449 example, the in-memory layout of the chunk_obstack might look like
450 this after phase 1:
451
452 + pp_formatted_chunks instance <--- START of pp_formatted_chunks level
453 |
454 + pp_token_list for chunk 0 (m_first: *)
455 | |
456 + "foo: \0" <-------------\ |
457 | | |
458 + pp_token_text (borrowed: *) <-------/
459 |
460 + pp_token_list for chunk 1
461 |
462 + "i\0" <------------------\
463 | |
464 + pp_token_text (borrowed: *)
465 |
466 + ...etc for chunks 2 to 4...
467 |
468 + pp_token_list for chunk 5
469 |
470 + "qs\0" <-----------------\
471 | |
472 + pp_token_text (borrowed: *)
473 |
474 |
475 V
476 obstack grows this way
477
478 At each stage, allocation of additional text buffers, tokens, and lists
479 grow forwards in the obstack (though the internal pointers in linked
480 lists might point backwards to earlier objects within the same
481 pp_formatted_chunks level). */
482};
483
484#endif /* GCC_PRETTY_PRINT_FORMAT_IMPL_H */
Definition diagnostic-event-id.h:37
Definition pretty-print.h:84
Definition pretty-print-format-impl.h:366
pp_formatted_chunks * get_prev() const
Definition pretty-print-format-impl.h:380
pp_token_list * m_args[PP_NL_ARGMAX *2]
Definition pretty-print-format-impl.h:445
pp_token_list *const * get_token_lists() const
Definition pretty-print-format-impl.h:372
void DEBUG_FUNCTION dump() const
Definition pretty-print-format-impl.h:377
pp_formatted_chunks * m_prev
Definition pretty-print-format-impl.h:384
void append_formatted_chunk(obstack &s, const char *content)
Definition pretty-print.cc:1578
Definition pretty-print-markup.h:30
Definition pretty-print-format-impl.h:256
virtual bool as_standard_tokens(pp_token_list &out)=0
virtual void dump(FILE *out) const =0
virtual ~value()
Definition pretty-print-format-impl.h:258
Definition pretty-print-format-impl.h:300
pp_token_list(const pp_token_list &)=delete
obstack & m_obstack
Definition pretty-print-format-impl.h:354
void replace_custom_tokens()
Definition pretty-print.cc:1439
std::unique_ptr< pp_token > remove_token(pp_token *tok)
Definition pretty-print.cc:1380
void insert_after(std::unique_ptr< pp_token > new_tok, pp_token *relative_tok)
Definition pretty-print.cc:1413
pp_token & operator=(const pp_token_list &)=delete
pp_token * m_first
Definition pretty-print-format-impl.h:356
void DEBUG_FUNCTION dump() const
Definition pretty-print-format-impl.h:352
pp_token * m_end
Definition pretty-print-format-impl.h:357
void push_back_text(label_text &&text)
Definition pretty-print.cc:1323
static pp_token_list * make(obstack &s)
Definition pretty-print-format-impl.h:303
pp_token_list(obstack &s)
Definition pretty-print.cc:1296
~pp_token_list()
Definition pretty-print.cc:1312
void merge_consecutive_text_tokens()
Definition pretty-print.cc:1469
std::unique_ptr< pp_token > pop_front()
Definition pretty-print.cc:1357
void apply_urlifier(const urlifier &urlifier)
Definition pretty-print.cc:1531
void push_back(Args &&... args)
Definition pretty-print-format-impl.h:331
void push_back_list(pp_token_list &&list)
Definition pretty-print.cc:1350
std::unique_ptr< pp_token > make_token(Args &&... args)
Definition pretty-print-format-impl.h:324
Definition pretty-print.h:241
Definition pretty-print-urlifier.h:27
static struct obstack obstack
Definition gcc.cc:360
#define PP_NL_ARGMAX
Definition pretty-print.h:29
static bool test(U *p)
Definition ira-emit.cc:158
Definition pretty-print-format-impl.h:138
label_text m_value
Definition pretty-print-format-impl.h:146
pp_token_begin_color(label_text &&value)
Definition pretty-print-format-impl.h:139
Definition pretty-print-format-impl.h:174
pp_token_begin_quote()
Definition pretty-print-format-impl.h:175
Definition pretty-print-format-impl.h:190
label_text m_value
Definition pretty-print-format-impl.h:198
pp_token_begin_url(label_text &&value)
Definition pretty-print-format-impl.h:191
Definition pretty-print-format-impl.h:254
pp_token_custom_data(std::unique_ptr< value > val)
Definition pretty-print-format-impl.h:268
std::unique_ptr< value > m_value
Definition pretty-print-format-impl.h:275
Definition pretty-print-format-impl.h:166
pp_token_end_color()
Definition pretty-print-format-impl.h:167
Definition pretty-print-format-impl.h:182
pp_token_end_quote()
Definition pretty-print-format-impl.h:183
Definition pretty-print-format-impl.h:218
pp_token_end_url()
Definition pretty-print-format-impl.h:219
Definition pretty-print-format-impl.h:226
pp_token_event_id(diagnostic_event_id_t event_id)
Definition pretty-print-format-impl.h:227
diagnostic_event_id_t m_event_id
Definition pretty-print-format-impl.h:234
Definition pretty-print-format-impl.h:110
label_text m_value
Definition pretty-print-format-impl.h:118
pp_token_text(label_text &&value)
Definition pretty-print-format-impl.h:111
Definition pretty-print-format-impl.h:62
enum kind m_kind
Definition pretty-print-format-impl.h:100
pp_token(const pp_token &)=delete
pp_token(enum kind k)
Definition pretty-print.cc:1177
pp_token * m_prev
Definition pretty-print-format-impl.h:103
kind
Definition pretty-print-format-impl.h:65
void DEBUG_FUNCTION dump() const
Definition pretty-print-format-impl.h:95
pp_token(pp_token &&)=delete
virtual ~pp_token()=default
pp_token & operator=(const pp_token &)=delete
pp_token * m_next
Definition pretty-print-format-impl.h:104
#define gcc_assert(EXPR)
Definition system.h:814
#define DEBUG_FUNCTION
Definition system.h:1236