pretty-print: reimplement pp_format with a new struct pp_token

The following patch rewrites the internals of pp_format.

A pretty_printer's output_buffer maintains a stack of chunk_info
instances, each one responsible for handling a call to pp_format, where
having a stack allows us to support re-entrant calls to pp_format on the
same pretty_printer.

Previously a chunk_info merely stored buffers of accumulated text
per unformatted run and per formatted argument.

This led to various special-casing for handling:

- urlifiers, needing class quoting_info to handle awkard cases where
  the run of quoted text could be split between stages 1 and 2
  of formatting

- dumpfiles, where the optinfo machinery could lead to objects being
  stashed during formatting for later replay to JSON optimization
  records

- in the C++ frontend, the format codes %H and %I can't be processed
  until we've seen both, leading to awkward code to manipulate the
  text buffers

Further, supporting URLs in messages in SARIF output (PR other/116419)
would add additional manipulations of text buffers, since our internal
pp_begin_url API gives the URL at the beginning of the wrapped text,
whereas SARIF's format for embedded URLs has the URL *after* the wrapped
text.  Also when handling "%@" we wouldn't necessarily know the URL of
an event ID until later, requiring further nasty special-case
manipulation of text buffers.

This patch rewrites pretty-print formatting by introducing a new
intermediate representation during formatting: pp_token and
pp_token_list.  Rather than simply accumulating a buffer of "char" in
the chunk_obstack during formatting, we now also accumulate a
pp_token_list, a doubly-linked list of pp_token, which can be:
- text buffers
- begin/end colorization
- begin/end quote
- begin/end URL
- "custom data" tokens

Working at the level of tokens rather than just text buffers allows the
various awkward special cases above to be replaced with uniform logic.
For example, all "urlification" is now done in phase 3 of formatting,
in one place, by looking for [..., BEGIN_QUOTE, TEXT, END_QUOTE, ...]
and injecting BEGIN_URL and END_URL wrapper tokens when the urlifier
has a URL for TEXT.  Doing so greatly simplifies the urlifier code,
allowing the removal of class quoting_info.

The tokens and token lists are allocated on the chunk_obstack, and so
there's no additional heap activity required, with the memory reclaimed
when the chunk_obstack is freed after phase 3 of formatting.

New kinds of pp_token can be added as needed to support output formats.
For example, the followup patch adds a token for "%@" for events IDs, to
better support SARIF output.

No functional change intended.

gcc/c/ChangeLog:
	* c-objc-common.cc (c_tree_printer): Convert final param from
	const char ** to pp_token_list &.

gcc/cp/ChangeLog:
	* error.cc: Include "make-unique.h".
	(deferred_printed_type::m_buffer_ptr): Replace with...
	(deferred_printed_type::m_printed_text): ...this and...
	(deferred_printed_type::m_token_list): ...this.
	(deferred_printed_type::deferred_printed_type): Update ctors for
	above changes.
	(deferred_printed_type::set_text_for_token_list): New.
	(append_formatted_chunk): Pass chunk_obstack to
	append_formatted_chunk.
	(add_quotes): Delete.
	(cxx_format_postprocessor::handle): Reimplement to call
	deferred_printed_type::set_text_for_token_list, rather than store
	buffer pointers.
	(defer_phase_2_of_type_diff): Replace param "buffer_ptr"
	with "formatted_token_list".  Reimplement by storing
	a pointer to formatted_token_list so that the postprocessor can
	put its text there.
	(cp_printer): Convert param "buffer_ptr" to
	"formatted_token_list".  Update calls to
	defer_phase_2_of_type_diff accordingly.

gcc/ChangeLog:
	* diagnostic.cc (diagnostic_context::report_diagnostic): Don't
	pass m_urlifier to pp_format, as urlification now happens in
	phase 3.
	* dump-context.h (class dump_pretty_printer): Update leading
	comment.
	(dump_pretty_printer::emit_items): Drop decl.
	(dump_pretty_printer::set_optinfo): New.
	(class dump_pretty_printer::stashed_item): Delete class.
	(class dump_pretty_printer::custom_token_printer): New class.
	(dump_pretty_printer::format_decoder_cb): Convert param from
	const char ** to pp_token_list &.
	(dump_pretty_printer::decode_format): Likewise.
	(dump_pretty_printer::stash_item): Likewise.
	(dump_pretty_printer::emit_any_pending_textual_chunks): Drop decl.
	(dump_pretty_printer::m_stashed_items): Delete field.
	(dump_pretty_printer::m_token_printer): New member data.
	* dumpfile.cc (struct wrapped_optinfo_item): New.
	(dump_pretty_printer::dump_pretty_printer): Update for dropping
	of field m_stashed_items and new field m_token_printer.
	(dump_pretty_printer::emit_items): Delete; we now use
	pp_output_formatted_text..
	(dump_pretty_printer::emit_any_pending_textual_chunks): Delete.
	(dump_pretty_printer::stash_item): Convert param from
	const char ** to pp_token_list &.
	(dump_pretty_printer::format_decoder_cb): Likewise.
	(dump_pretty_printer::decode_format): Likewise.
	(dump_pretty_printer::custom_token_printer::print_tokens): New.
	(dump_pretty_printer::custom_token_printer::emit_any_pending_textual_chunks):
	New.
	(dump_context::dump_printf_va): Call set_optinfo on the
	dump_pretty_printer.  Replace call to emit_items with a call to
	pp_output_formatted_text.
	* opt-problem.cc (opt_problem::opt_problem): Replace call to
	emit_items with call to set_optinfo and call to
	pp_output_formatted_text.
	* pretty-print-format-impl.h (struct pp_token): New.
	(struct pp_token_text): New.
	(is_a_helper <pp_token_text *>::test): New.
	(is_a_helper <const pp_token_text *>::test): New.
	(struct pp_token_begin_color): New.
	(is_a_helper <pp_token_begin_color *>::test): New.
	(is_a_helper <const pp_token_begin_color *>::test): New.
	(struct pp_token_end_color): New.
	(struct pp_token_begin_quote): New.
	(struct pp_token_end_quote): New.
	(struct pp_token_begin_url): New.
	(is_a_helper <pp_token_begin_url*>::test): New.
	(is_a_helper <const pp_token_begin_url*>::test): New.
	(struct pp_token_end_url): New.
	(struct pp_token_custom_data): New.
	(is_a_helper <pp_token_custom_data *>::test): New.
	(is_a_helper <const pp_token_custom_data *>::test): New.
	(class pp_token_list): New.
	(chunk_info::get_args): Drop.
	(chunk_info::get_quoting_info): Drop.
	(chunk_info::get_token_lists): New accessor.
	(chunk_info::append_formatted_chunk): Add obstack & param.
	(chunk_info::dump): New decls.
	(chunk_info::m_args): Convert element type from const char * to
	pp_token_list *.  Rewrite/update comment.
	(chunk_info::m_quotes): Drop field.
	* pretty-print-markup.h (class pp_token_list): New forward decl.
	(pp_markup::context::context): Drop urlifier param; add
	formatted_token_list param.
	(pp_markup::context::push_back_any_text): New decl.
	(pp_markup::context::m_urlifier): Drop field.
	(pp_markup::context::m_formatted_token_list): New field.
	* pretty-print-urlifier.h: Update comment.
	* pretty-print.cc: Define INCLUDE_MEMORY.  Include
	"make-unique.h".
	(default_token_printer): New forward decl.
	(obstack_append_string): Delete.
	(urlify_quoted_string): Delete.
	(pp_token::pp_token): New.
	(pp_token::dump): New.
	(allocate_object): New.
	(class quoting_info): Delete.
	(pp_token::operator new): New.
	(pp_token::operator delete): New.
	(pp_token_list::operator new): New.
	(pp_token_list::operator delete): New.
	(pp_token_list::pp_token_list): New.
	(pp_token_list::~pp_token_list): New.
	(pp_token_list::push_back_text): New.
	(pp_token_list::push_back): New.
	(pp_token_list::push_back_list): New.
	(pp_token_list::pop_front): New.
	(pp_token_list::remove_token): New.
	(pp_token_list::insert_after): New.
	(pp_token_list::replace_custom_tokens): New.
	(pp_token_list::merge_consecutive_text_tokens): New.
	(pp_token_list::apply_urlifier): New.
	(pp_token_list::dump): New.
	(chunk_info::append_formatted_chunk): Add obstack & param and use
	it to reimplement in terms of token lists.
	(chunk_info::pop_from_output_buffer): Drop m_quotes.
	(chunk_info::on_begin_quote): Delete.
	(chunk_info::dump): New.
	(chunk_info::on_end_quote): Delete.
	(push_back_any_text): New.
	(pretty_printer::format): Drop "urlifier" param and quoting_info
	logic.  Convert "formatters" and "args" from const ** to
	pp_token_list **.  Reimplement so that rather than just
	accumulating a text buffer in the chunk_obstack for each arg,
	instead also accumulate a pp_token_list and pp_tokens for each
	arg.
	(auto_obstack::operator obstack &): New.
	(quoting_info::handle_phase_3): Delete.
	(pp_output_formatted_text): Reimplement in terms of manipulations
	of pp_token_lists, rather than char buffers.  Call
	default_token_printer, or m_token_printer's print_tokens vfunc.
	(default_token_printer): New.
	(pretty_printer::pretty_printer): Initialize m_token_printer in
	both ctors.
	(pp_markup::context::begin_quote): Reimplement to use token list.
	(pp_markup::context::end_quote): Likewise.
	(pp_markup::context::begin_highlight_color): Likewise.
	(pp_markup::context::end_highlight_color): Likewise.
	(pp_markup::context::push_back_any_text): New.
	(selftest::test_merge_consecutive_text_tokens): New.
	(selftest::test_custom_tokens_1): New.
	(selftest::test_custom_tokens_2): New.
	(selftest::pp_printf_with_urlifier): Drop "urlifier" param from
	call to pp_format.
	(selftest::test_urlification): Add test of the example from
	pretty-print-format-impl.h.
	(selftest::pretty_print_cc_tests): Call the new selftest
	functions.
	* pretty-print.h (class quoting_info): Drop forward decl.
	(class pp_token_list): New forward decl.
	(printer_fn): Convert final param from const char ** to
	pp_token_list &.
	(class token_printer): New.
	(class pretty_printer): Add pp_output_formatted_text as friend.
	(pretty_printer::set_token_printer): New.
	(pretty_printer::format): Drop urlifier param as this now happens
	in phase 3.
	(pretty_printer::m_format_decoder): Update comment.
	(pretty_printer::m_token_printer): New field.
	(pp_format): Drop urlifier param.
	* tree-diagnostic.cc (default_tree_printer): Convert final param
	from const char ** to pp_token_list &.
	* tree-diagnostic.h: Likewise for decl.

gcc/fortran/ChangeLog:
	* error.cc (gfc_format_decoder): Convert final param from
	const char **buffer_ptr to pp_token_list &formatted_token_list,
	and update call to default_tree_printer accordingly.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
David Malcolm 2024-08-29 18:48:27 -04:00
parent 68a0ca6697
commit e31b617699
14 changed files with 1490 additions and 542 deletions

View file

@ -34,7 +34,7 @@ along with GCC; see the file COPYING3. If not see
#include "dwarf2.h"
static bool c_tree_printer (pretty_printer *, text_info *, const char *,
int, bool, bool, bool, bool *, const char **);
int, bool, bool, bool, bool *, pp_token_list &);
/* Info for C language features which can be queried through
__has_{feature,extension}. */
@ -318,7 +318,7 @@ pp_markup::element_quoted_type::print_type (pp_markup::context &ctxt)
static bool
c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
int precision, bool wide, bool set_locus, bool hash,
bool *quoted, const char **)
bool *quoted, pp_token_list &)
{
tree t = NULL_TREE;
// FIXME: the next cast should be a dynamic_cast, when it is permitted.

View file

@ -39,6 +39,7 @@ along with GCC; see the file COPYING3. If not see
#include "cp-name-hint.h"
#include "attribs.h"
#include "pretty-print-format-impl.h"
#include "make-unique.h"
#define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
#define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
@ -110,7 +111,7 @@ static void cp_print_error_function (diagnostic_context *,
const diagnostic_info *);
static bool cp_printer (pretty_printer *, text_info *, const char *,
int, bool, bool, bool, bool *, const char **);
int, bool, bool, bool, bool *, pp_token_list &);
/* Color names for highlighting "%qH" vs "%qI" values,
and ranges corresponding to them. */
@ -124,22 +125,50 @@ class deferred_printed_type
{
public:
deferred_printed_type ()
: m_tree (NULL_TREE), m_buffer_ptr (NULL), m_verbose (false), m_quote (false)
: m_tree (NULL_TREE),
m_printed_text (),
m_token_list (nullptr),
m_verbose (false), m_quote (false)
{}
deferred_printed_type (tree type, const char **buffer_ptr, bool verbose,
deferred_printed_type (tree type,
pp_token_list &token_list,
bool verbose,
bool quote)
: m_tree (type), m_buffer_ptr (buffer_ptr), m_verbose (verbose),
: m_tree (type),
m_printed_text (),
m_token_list (&token_list),
m_verbose (verbose),
m_quote (quote)
{
gcc_assert (type);
gcc_assert (buffer_ptr);
}
void set_text_for_token_list (const char *text, bool quote)
{
/* Replace the contents of m_token_list with a text token for TEXT,
possibly wrapped by BEGIN_QUOTE/END_QUOTE (if QUOTE is true).
This allows us to ignore any {BEGIN,END}_QUOTE tokens added
by %qH and %qI, and instead use the quoting from type_to_string,
and its logic for "aka". */
while (m_token_list->m_first)
m_token_list->pop_front ();
if (quote)
m_token_list->push_back<pp_token_begin_quote> ();
// TEXT is gc-allocated, so we can borrow it
m_token_list->push_back_text (label_text::borrow (text));
if (quote)
m_token_list->push_back<pp_token_end_quote> ();
}
/* The tree is not GTY-marked: they are only non-NULL within a
call to pp_format. */
tree m_tree;
const char **m_buffer_ptr;
label_text m_printed_text;
pp_token_list *m_token_list;
bool m_verbose;
bool m_quote;
};
@ -4402,26 +4431,7 @@ append_formatted_chunk (pretty_printer *pp, const char *content)
{
output_buffer *buffer = pp_buffer (pp);
chunk_info *chunk_array = buffer->cur_chunk_array;
chunk_array->append_formatted_chunk (content);
}
/* Create a copy of CONTENT, with quotes added, and,
potentially, with colorization.
No escaped is performed on CONTENT.
The result is in a GC-allocated buffer. */
static const char *
add_quotes (const char *content, bool show_color)
{
pretty_printer tmp_pp;
pp_show_color (&tmp_pp) = show_color;
/* We have to use "%<%s%>" rather than "%qs" here in order to avoid
quoting colorization bytes within the results and using either
pp_quote or pp_begin_quote doesn't work the same. */
pp_printf (&tmp_pp, "%<%s%>", content);
return pp_ggc_formatted_text (&tmp_pp);
chunk_array->append_formatted_chunk (buffer->chunk_obstack, content);
}
#if __GNUC__ >= 10
@ -4429,8 +4439,8 @@ add_quotes (const char *content, bool show_color)
#endif
/* If we had %H and %I, and hence deferred printing them,
print them now, storing the result into the chunk_info
for pp_format. Quote them if 'q' was provided.
print them now, storing the result into custom_token_value
for the custom pp_token. Quote them if 'q' was provided.
Also print the difference in tree form, adding it as
an additional chunk. */
@ -4448,13 +4458,13 @@ cxx_format_postprocessor::handle (pretty_printer *pp)
= show_highlight_colors ? highlight_colors::percent_i : nullptr;
/* Avoid reentrancy issues by working with a copy of
m_type_a and m_type_b, resetting them now. */
deferred_printed_type type_a = m_type_a;
deferred_printed_type type_b = m_type_b;
deferred_printed_type type_a = std::move (m_type_a);
deferred_printed_type type_b = std::move (m_type_b);
m_type_a = deferred_printed_type ();
m_type_b = deferred_printed_type ();
gcc_assert (type_a.m_buffer_ptr);
gcc_assert (type_b.m_buffer_ptr);
gcc_assert (type_a.m_token_list);
gcc_assert (type_b.m_token_list);
bool show_color = pp_show_color (pp);
@ -4495,13 +4505,8 @@ cxx_format_postprocessor::handle (pretty_printer *pp)
percent_i);
}
if (type_a.m_quote)
type_a_text = add_quotes (type_a_text, show_color);
*type_a.m_buffer_ptr = type_a_text;
if (type_b.m_quote)
type_b_text = add_quotes (type_b_text, show_color);
*type_b.m_buffer_ptr = type_b_text;
type_a.set_text_for_token_list (type_a_text, type_a.m_quote);
type_b.set_text_for_token_list (type_b_text, type_b.m_quote);
}
}
@ -4526,9 +4531,12 @@ cxx_format_postprocessor::handle (pretty_printer *pp)
pretty_printer's m_format_postprocessor hook.
This is called in phase 2 of pp_format, when it is accumulating
a series of formatted chunks. We stash the location of the chunk
we're meant to have written to, so that we can write to it in the
m_format_postprocessor hook.
a series of pp_token lists. Since we have to interact with the
fiddly quoting logic for "aka", we store the pp_token_list *
and in the m_format_postprocessor hook we generate text for the type
(possibly with quotes and colors), then replace all tokens in that token list
(such as [BEGIN_QUOTE, END_QUOTE]) with a text token containing the
freshly generated text.
We also need to stash whether a 'q' prefix was provided (the QUOTE
param) so that we can add the quotes when writing out the delayed
@ -4536,12 +4544,13 @@ cxx_format_postprocessor::handle (pretty_printer *pp)
static void
defer_phase_2_of_type_diff (deferred_printed_type *deferred,
tree type, const char **buffer_ptr,
tree type,
pp_token_list &formatted_token_list,
bool verbose, bool quote)
{
gcc_assert (deferred->m_tree == NULL_TREE);
gcc_assert (deferred->m_buffer_ptr == NULL);
*deferred = deferred_printed_type (type, buffer_ptr, verbose, quote);
*deferred = deferred_printed_type (type, formatted_token_list,
verbose, quote);
}
/* Implementation of pp_markup::element_quoted_type::print_type
@ -4578,7 +4587,7 @@ pp_markup::element_quoted_type::print_type (pp_markup::context &ctxt)
static bool
cp_printer (pretty_printer *pp, text_info *text, const char *spec,
int precision, bool wide, bool set_locus, bool verbose,
bool *quoted, const char **buffer_ptr)
bool *quoted, pp_token_list &formatted_token_list)
{
gcc_assert (pp_format_postprocessor (pp));
cxx_format_postprocessor *postprocessor
@ -4618,11 +4627,11 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
case 'F': result = fndecl_to_string (next_tree, verbose); break;
case 'H':
defer_phase_2_of_type_diff (&postprocessor->m_type_a, next_tree,
buffer_ptr, verbose, *quoted);
formatted_token_list, verbose, *quoted);
return true;
case 'I':
defer_phase_2_of_type_diff (&postprocessor->m_type_b, next_tree,
buffer_ptr, verbose, *quoted);
formatted_token_list, verbose, *quoted);
return true;
case 'L': result = language_to_string (next_lang); break;
case 'O': result = op_to_string (false, next_tcode); break;

View file

@ -1407,7 +1407,7 @@ diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
m_output_format->on_begin_group ();
m_diagnostic_groups.m_emission_count++;
pp_format (this->printer, &diagnostic->message, m_urlifier);
pp_format (this->printer, &diagnostic->message);
/* Call vfunc in the output format. This is responsible for
phase 3 of formatting, and for printing the result. */
m_output_format->on_report_diagnostic (*diagnostic, orig_diag_kind);

View file

@ -154,48 +154,52 @@ class dump_context
};
/* A subclass of pretty_printer for implementing dump_context::dump_printf_va.
In particular, the formatted chunks are captured as optinfo_item instances,
thus retaining metadata about the entities being dumped (e.g. source
locations), rather than just as plain text. */
In particular, the formatted chunks are captured as optinfo_item instances
as pp_token_custom_data, thus retaining metadata about the entities being
dumped (e.g. source locations), rather than just as plain text.
These custom items are retained through to the end of stage 3 of formatted
printing; the printer uses a custom token_printer subclass to emit them to
the active optinfo (if any). */
class dump_pretty_printer : public pretty_printer
{
public:
dump_pretty_printer (dump_context *context, dump_flags_t dump_kind);
void emit_items (optinfo *dest);
void set_optinfo (optinfo *info) { m_token_printer.m_optinfo = info; }
private:
/* Information on an optinfo_item that was generated during phase 2 of
formatting. */
class stashed_item
struct custom_token_printer : public token_printer
{
public:
stashed_item (const char **buffer_ptr_, optinfo_item *item_)
: buffer_ptr (buffer_ptr_), item (item_) {}
const char **buffer_ptr;
optinfo_item *item;
custom_token_printer (dump_pretty_printer &dump_pp)
: m_dump_pp (dump_pp),
m_optinfo (nullptr)
{}
void print_tokens (pretty_printer *pp,
const pp_token_list &tokens) final override;
void emit_any_pending_textual_chunks ();
dump_pretty_printer &m_dump_pp;
optinfo *m_optinfo;
};
static bool format_decoder_cb (pretty_printer *pp, text_info *text,
const char *spec, int /*precision*/,
bool /*wide*/, bool /*set_locus*/,
bool /*verbose*/, bool */*quoted*/,
const char **buffer_ptr);
pp_token_list &formatted_tok_list);
bool decode_format (text_info *text, const char *spec,
const char **buffer_ptr);
pp_token_list &formatted_tok_list);
void stash_item (const char **buffer_ptr,
void stash_item (pp_token_list &formatted_tok_list,
std::unique_ptr<optinfo_item> item);
void emit_any_pending_textual_chunks (optinfo *dest);
void emit_item (std::unique_ptr<optinfo_item> item, optinfo *dest);
dump_context *m_context;
dump_flags_t m_dump_kind;
auto_vec<stashed_item> m_stashed_items;
custom_token_printer m_token_printer;
};
/* An RAII-style class for use in debug dumpers for temporarily using a

View file

@ -791,90 +791,39 @@ make_item_for_dump_symtab_node (symtab_node *node)
return item;
}
struct wrapped_optinfo_item : public pp_token_custom_data::value
{
wrapped_optinfo_item (std::unique_ptr<optinfo_item> item)
: m_optinfo_item (std::move (item))
{
gcc_assert (m_optinfo_item.get ());
}
void dump (FILE *out) const final override
{
fprintf (out, "OPTINFO(\"%s\")", m_optinfo_item->get_text ());
}
bool as_standard_tokens (pp_token_list &) final override
{
/* Keep as a custom token. */
return false;
}
std::unique_ptr<optinfo_item> m_optinfo_item;
};
/* dump_pretty_printer's ctor. */
dump_pretty_printer::dump_pretty_printer (dump_context *context,
dump_flags_t dump_kind)
: pretty_printer (), m_context (context), m_dump_kind (dump_kind),
m_stashed_items ()
: pretty_printer (),
m_context (context),
m_dump_kind (dump_kind),
m_token_printer (*this)
{
pp_format_decoder (this) = format_decoder_cb;
}
/* Phase 3 of formatting; compare with pp_output_formatted_text.
Emit optinfo_item instances for the various formatted chunks from phases
1 and 2 (i.e. pp_format).
Some chunks may already have had their items built (during decode_format).
These chunks have been stashed into m_stashed_items; we emit them here.
For all other purely textual chunks, they are printed into
buffer->formatted_obstack, and then emitted as a textual optinfo_item.
This consolidates multiple adjacent text chunks into a single text
optinfo_item. */
void
dump_pretty_printer::emit_items (optinfo *dest)
{
output_buffer *buffer = pp_buffer (this);
chunk_info *chunk_array = buffer->cur_chunk_array;
const char * const *args = chunk_array->get_args ();
gcc_assert (buffer->obstack == &buffer->formatted_obstack);
gcc_assert (buffer->line_length == 0);
unsigned stashed_item_idx = 0;
for (unsigned chunk = 0; args[chunk]; chunk++)
{
if (stashed_item_idx < m_stashed_items.length ()
&& args[chunk] == *m_stashed_items[stashed_item_idx].buffer_ptr)
{
emit_any_pending_textual_chunks (dest);
/* This chunk has a stashed item: use it. */
std::unique_ptr <optinfo_item> item
(m_stashed_items[stashed_item_idx++].item);
emit_item (std::move (item), dest);
}
else
/* This chunk is purely textual. Print it (to
buffer->formatted_obstack), so that we can consolidate adjacent
chunks into one textual optinfo_item. */
pp_string (this, args[chunk]);
}
emit_any_pending_textual_chunks (dest);
/* Ensure that we consumed all of stashed_items. */
gcc_assert (stashed_item_idx == m_stashed_items.length ());
chunk_array->pop_from_output_buffer (*buffer);
}
/* Subroutine of dump_pretty_printer::emit_items
for consolidating multiple adjacent pure-text chunks into single
optinfo_items (in phase 3). */
void
dump_pretty_printer::emit_any_pending_textual_chunks (optinfo *dest)
{
output_buffer *const buffer = pp_buffer (this);
gcc_assert (buffer->obstack == &buffer->formatted_obstack);
/* Don't emit an item if the pending text is empty. */
if (output_buffer_last_position_in_text (buffer) == NULL)
return;
char *formatted_text = xstrdup (pp_formatted_text (this));
std::unique_ptr<optinfo_item> item
= make_unique<optinfo_item> (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
formatted_text);
emit_item (std::move (item), dest);
/* Clear the pending text by unwinding formatted_text back to the start
of the buffer (without deallocating). */
obstack_free (&buffer->formatted_obstack,
buffer->formatted_obstack.object_base);
set_token_printer (&m_token_printer);
}
/* Emit ITEM and take ownership of it. If DEST is non-NULL, add ITEM
@ -889,17 +838,18 @@ dump_pretty_printer::emit_item (std::unique_ptr<optinfo_item> item,
dest->add_item (std::move (item));
}
/* Record that ITEM (generated in phase 2 of formatting) is to be used for
the chunk at BUFFER_PTR in phase 3 (by emit_items). */
/* Append a custom pp_token for ITEM (generated in phase 2 of formatting)
into FORMATTTED_TOK_LIST, so that it can be emitted in phase 2. */
void
dump_pretty_printer::stash_item (const char **buffer_ptr,
dump_pretty_printer::stash_item (pp_token_list &formatted_tok_list,
std::unique_ptr<optinfo_item> item)
{
gcc_assert (buffer_ptr);
gcc_assert (item.get ());
m_stashed_items.safe_push (stashed_item (buffer_ptr, item.release ()));
auto custom_data
= ::make_unique<wrapped_optinfo_item> (std::move (item));
formatted_tok_list.push_back<pp_token_custom_data> (std::move (custom_data));
}
/* pp_format_decoder callback for dump_pretty_printer, and thus for
@ -912,10 +862,10 @@ dump_pretty_printer::format_decoder_cb (pretty_printer *pp, text_info *text,
const char *spec, int /*precision*/,
bool /*wide*/, bool /*set_locus*/,
bool /*verbose*/, bool */*quoted*/,
const char **buffer_ptr)
pp_token_list &formatted_tok_list)
{
dump_pretty_printer *opp = static_cast <dump_pretty_printer *> (pp);
return opp->decode_format (text, spec, buffer_ptr);
return opp->decode_format (text, spec, formatted_tok_list);
}
/* Format decoder for dump_pretty_printer, and thus for dump_printf and
@ -942,7 +892,7 @@ dump_pretty_printer::format_decoder_cb (pretty_printer *pp, text_info *text,
bool
dump_pretty_printer::decode_format (text_info *text, const char *spec,
const char **buffer_ptr)
pp_token_list &formatted_tok_list)
{
/* Various format codes that imply making an optinfo_item and stashed it
for later use (to capture metadata, rather than plain text). */
@ -954,7 +904,7 @@ dump_pretty_printer::decode_format (text_info *text, const char *spec,
/* Make an item for the node, and stash it. */
auto item = make_item_for_dump_symtab_node (node);
stash_item (buffer_ptr, std::move (item));
stash_item (formatted_tok_list, std::move (item));
return true;
}
@ -964,7 +914,7 @@ dump_pretty_printer::decode_format (text_info *text, const char *spec,
/* Make an item for the stmt, and stash it. */
auto item = make_item_for_dump_gimple_expr (stmt, 0, TDF_SLIM);
stash_item (buffer_ptr, std::move (item));
stash_item (formatted_tok_list, std::move (item));
return true;
}
@ -974,7 +924,7 @@ dump_pretty_printer::decode_format (text_info *text, const char *spec,
/* Make an item for the stmt, and stash it. */
auto item = make_item_for_dump_gimple_stmt (stmt, 0, TDF_SLIM);
stash_item (buffer_ptr, std::move (item));
stash_item (formatted_tok_list, std::move (item));
return true;
}
@ -984,7 +934,7 @@ dump_pretty_printer::decode_format (text_info *text, const char *spec,
/* Make an item for the tree, and stash it. */
auto item = make_item_for_dump_generic_expr (t, TDF_SLIM);
stash_item (buffer_ptr, std::move (item));
stash_item (formatted_tok_list, std::move (item));
return true;
}
@ -993,6 +943,87 @@ dump_pretty_printer::decode_format (text_info *text, const char *spec,
}
}
void
dump_pretty_printer::custom_token_printer::
print_tokens (pretty_printer *pp,
const pp_token_list &tokens)
{
/* Accumulate text whilst emitting items. */
for (auto iter = tokens.m_first; iter; iter = iter->m_next)
switch (iter->m_kind)
{
default:
gcc_unreachable ();
case pp_token::kind::text:
{
pp_token_text *sub = as_a <pp_token_text *> (iter);
gcc_assert (sub->m_value.get ());
pp_string (pp, sub->m_value.get ());
}
break;
case pp_token::kind::begin_color:
case pp_token::kind::end_color:
/* No-op for dumpfiles. */
break;
case pp_token::kind::begin_quote:
pp_begin_quote (pp, pp_show_color (pp));
break;
case pp_token::kind::end_quote:
pp_end_quote (pp, pp_show_color (pp));
break;
case pp_token::kind::begin_url:
case pp_token::kind::end_url:
/* No-op for dumpfiles. */
break;
case pp_token::kind::custom_data:
{
emit_any_pending_textual_chunks ();
pp_token_custom_data *sub = as_a <pp_token_custom_data *> (iter);
gcc_assert (sub->m_value.get ());
wrapped_optinfo_item *custom_data
= static_cast<wrapped_optinfo_item *> (sub->m_value.get ());
m_dump_pp.emit_item (std::move (custom_data->m_optinfo_item),
m_optinfo);
}
break;
}
emit_any_pending_textual_chunks ();
}
/* Subroutine of dump_pretty_printer::custom_token_printer::print_tokens
for consolidating multiple adjacent pure-text chunks into single
optinfo_items (in phase 3). */
void
dump_pretty_printer::custom_token_printer::
emit_any_pending_textual_chunks ()
{
dump_pretty_printer *pp = &m_dump_pp;
output_buffer *const buffer = pp_buffer (pp);
gcc_assert (buffer->obstack == &buffer->formatted_obstack);
/* Don't emit an item if the pending text is empty. */
if (output_buffer_last_position_in_text (buffer) == nullptr)
return;
char *formatted_text = xstrdup (pp_formatted_text (pp));
std::unique_ptr<optinfo_item> item
= make_unique<optinfo_item> (OPTINFO_ITEM_KIND_TEXT, UNKNOWN_LOCATION,
formatted_text);
pp->emit_item (std::move (item), m_optinfo);
/* Clear the pending text by unwinding formatted_text back to the start
of the buffer (without deallocating). */
obstack_free (&buffer->formatted_obstack,
buffer->formatted_obstack.object_base);
}
/* Output a formatted message using FORMAT on appropriate dump streams. */
void
@ -1007,14 +1038,16 @@ dump_context::dump_printf_va (const dump_metadata_t &metadata,
/* Phases 1 and 2, using pp_format. */
pp_format (&pp, &text);
/* Phase 3. */
/* Phase 3: update the custom token_printer with any active optinfo. */
if (optinfo_enabled_p ())
{
optinfo &info = ensure_pending_optinfo (metadata);
pp.emit_items (&info);
pp.set_optinfo (&info);
}
else
pp.emit_items (NULL);
pp.set_optinfo (nullptr);
pp_output_formatted_text (&pp, nullptr);
}
/* Similar to dump_printf, except source location is also printed, and

View file

@ -1125,7 +1125,7 @@ gfc_notify_std (int std, const char *gmsgid, ...)
static bool
gfc_format_decoder (pretty_printer *pp, text_info *text, const char *spec,
int precision, bool wide, bool set_locus, bool hash,
bool *quoted, const char **buffer_ptr)
bool *quoted, pp_token_list &formatted_token_list)
{
switch (*spec)
{
@ -1170,7 +1170,8 @@ gfc_format_decoder (pretty_printer *pp, text_info *text, const char *spec,
etc. diagnostics can use the FE printer while the FE is still
active. */
return default_tree_printer (pp, text, spec, precision, wide,
set_locus, hash, quoted, buffer_ptr);
set_locus, hash, quoted,
formatted_token_list);
}
}

View file

@ -71,7 +71,8 @@ opt_problem::opt_problem (const dump_location_t &loc,
/* Phase 3: dump the items to the "immediate" dump destinations,
and storing them into m_optinfo for later retrieval. */
pp.emit_items (&m_optinfo);
pp.set_optinfo (&m_optinfo);
pp_output_formatted_text (&pp, nullptr);
}
}

View file

@ -23,6 +23,308 @@ along with GCC; see the file COPYING3. If not see
#include "pretty-print.h"
/* A struct representing a pending item to be printed within
pp_format.
These can represent:
- a run of text within one of the output_buffers's obstacks
- begin/end named color
- open/close quote
- begin/end URL
- custom data (for the formatter, for the pretty_printer,
or the output format)
These are built into pp_token_list instances.
Doing so allows for interaction between:
- pretty_printer formatting codes (such as C++'s %H and %I,
which can't be printed until we've seen both)
- output formats, such as text vs SARIF (so each can handle URLs
and event IDs it its own way)
- optimization records, where we want to stash data into the
formatted messages
- urlifiers: these can be run in phase 3 of formatting
without needing lots of fragile logic on char pointers.
To avoid needing lots of heap allocation/deallocation, pp_token
instances are allocated in the pretty_printer's chunk_obstack:
they must not outlive phase 3 of formatting of the given
chunk_info level. */
struct pp_token
{
public:
enum class kind
{
text,
begin_color,
end_color,
begin_quote,
end_quote,
begin_url,
end_url,
custom_data,
NUM_KINDS
};
pp_token (enum kind k);
pp_token (const pp_token &) = delete;
pp_token (pp_token &&) = delete;
virtual ~pp_token () = default;
pp_token &operator= (const pp_token &) = delete;
pp_token &operator= (pp_token &&) = delete;
void dump (FILE *out) const;
void DEBUG_FUNCTION dump () const { dump (stderr); }
static void *operator new (size_t sz, obstack &s);
static void operator delete (void *);
enum kind m_kind;
// Intrusive doubly-linked list
pp_token *m_prev;
pp_token *m_next;
};
/* Subclasses of pp_token for the various kinds of token. */
struct pp_token_text : public pp_token
{
pp_token_text (label_text &&value)
: pp_token (kind::text),
m_value (std::move (value))
{
gcc_assert (m_value.get ());
}
label_text m_value;
};
template <>
template <>
inline bool
is_a_helper <pp_token_text *>::test (pp_token *tok)
{
return tok->m_kind == pp_token::kind::text;
}
template <>
template <>
inline bool
is_a_helper <const pp_token_text *>::test (const pp_token *tok)
{
return tok->m_kind == pp_token::kind::text;
}
struct pp_token_begin_color : public pp_token
{
pp_token_begin_color (label_text &&value)
: pp_token (kind::begin_color),
m_value (std::move (value))
{
gcc_assert (m_value.get ());
}
label_text m_value;
};
template <>
template <>
inline bool
is_a_helper <pp_token_begin_color *>::test (pp_token *tok)
{
return tok->m_kind == pp_token::kind::begin_color;
}
template <>
template <>
inline bool
is_a_helper <const pp_token_begin_color *>::test (const pp_token *tok)
{
return tok->m_kind == pp_token::kind::begin_color;
}
struct pp_token_end_color : public pp_token
{
pp_token_end_color ()
: pp_token (kind::end_color)
{
}
};
struct pp_token_begin_quote : public pp_token
{
pp_token_begin_quote ()
: pp_token (kind::begin_quote)
{
}
};
struct pp_token_end_quote : public pp_token
{
pp_token_end_quote ()
: pp_token (kind::end_quote)
{
}
};
struct pp_token_begin_url : public pp_token
{
pp_token_begin_url (label_text &&value)
: pp_token (kind::begin_url),
m_value (std::move (value))
{
gcc_assert (m_value.get ());
}
label_text m_value;
};
template <>
template <>
inline bool
is_a_helper <pp_token_begin_url*>::test (pp_token *tok)
{
return tok->m_kind == pp_token::kind::begin_url;
}
template <>
template <>
inline bool
is_a_helper <const pp_token_begin_url*>::test (const pp_token *tok)
{
return tok->m_kind == pp_token::kind::begin_url;
}
struct pp_token_end_url : public pp_token
{
pp_token_end_url ()
: pp_token (kind::end_url)
{
}
};
struct pp_token_custom_data : public pp_token
{
class value
{
public:
virtual ~value () {}
virtual void dump (FILE *out) const = 0;
/* Hook for lowering a custom_data token to standard tokens.
Return true and write to OUT if possible.
Return false for custom_data that is to be handled by
the token_printer. */
virtual bool as_standard_tokens (pp_token_list &out) = 0;
};
pp_token_custom_data (std::unique_ptr<value> val)
: pp_token (kind::custom_data),
m_value (std::move (val))
{
gcc_assert (m_value.get ());
}
std::unique_ptr<value> m_value;
};
template <>
template <>
inline bool
is_a_helper <pp_token_custom_data *>::test (pp_token *tok)
{
return tok->m_kind == pp_token::kind::custom_data;
}
template <>
template <>
inline bool
is_a_helper <const pp_token_custom_data *>::test (const pp_token *tok)
{
return tok->m_kind == pp_token::kind::custom_data;
}
/* A list of pp_token, with ownership of the tokens, using
a particular obstack to allocate its tokens. These are
also allocated on the obstack during formatting (or, occasionally,
the stack). */
class pp_token_list
{
public:
// Allocate a new pp_token_list within S.
static pp_token_list *make (obstack &s)
{
return new (s) pp_token_list (s);
}
static void *operator new (size_t sz, obstack &s);
static void operator delete (void *);
pp_token_list (obstack &s);
pp_token_list (const pp_token_list &) = delete;
pp_token_list (pp_token_list &&);
~pp_token_list ();
pp_token &operator= (const pp_token_list &) = delete;
pp_token &operator= (pp_token_list &&) = delete;
/* Make a pp_token of the given subclass, using the relevant obstack to provide
the memory. The pp_token must therefore not outlive the current chunk_info
level during formatting. */
template<typename Subclass, typename... Args>
std::unique_ptr<pp_token>
make_token (Args&&... args)
{
return std::unique_ptr<pp_token>
(new (m_obstack) Subclass (std::forward<Args> (args)...));
}
template<typename Subclass, typename... Args>
void push_back (Args&&... args)
{
auto tok = make_token<Subclass> (std::forward<Args> (args)...);
push_back (std::move (tok));
}
void push_back_text (label_text &&text);
void push_back (std::unique_ptr<pp_token> tok);
void push_back_list (pp_token_list &&list);
std::unique_ptr<pp_token> pop_front ();
std::unique_ptr<pp_token> remove_token (pp_token *tok);
void insert_after (std::unique_ptr<pp_token> new_tok,
pp_token *relative_tok);
void replace_custom_tokens ();
void merge_consecutive_text_tokens ();
void apply_urlifier (const urlifier &urlifier);
void dump (FILE *out) const;
void DEBUG_FUNCTION dump () const { dump (stderr); }
obstack &m_obstack;
pp_token *m_first;
pp_token *m_end;
};
/* The chunk_info data structure forms a stack of the results from the
first phase of formatting (pp_format) which have not yet been
output (pp_output_formatted_text). A stack is necessary because
@ -34,13 +336,15 @@ class chunk_info
friend class pp_markup::context;
public:
const char * const *get_args () const { return m_args; }
quoting_info *get_quoting_info () const { return m_quotes; }
pp_token_list * const * get_token_lists () const { return m_args; }
void append_formatted_chunk (const char *content);
void append_formatted_chunk (obstack &s, const char *content);
void pop_from_output_buffer (output_buffer &buf);
void dump (FILE *out) const;
void DEBUG_FUNCTION dump () const { dump (stderr); }
private:
void on_begin_quote (const output_buffer &buf,
unsigned chunk_idx,
@ -54,17 +358,100 @@ private:
/* Pointer to previous chunk on the stack. */
chunk_info *m_prev;
/* Array of chunks to output. Each chunk is a NUL-terminated string.
/* Array of chunks to output. Each chunk is a doubly-linked list of
pp_token.
The chunks can be printed via chunk_info::dump ().
In the first phase of formatting, even-numbered chunks are
to be output verbatim, odd-numbered chunks are format specifiers.
The second phase replaces all odd-numbered chunks with formatted
text, and the third phase simply emits all the chunks in sequence
with appropriate line-wrapping. */
const char *m_args[PP_NL_ARGMAX * 2];
For example, given:
pp_format (pp,
"foo: %i, bar: %s, opt: %qs",
42, "baz", "-foption");
/* If non-null, information on quoted text runs within the chunks
for use by a urlifier. */
quoting_info *m_quotes;
after phase 1 we might have:
(gdb) call buffer->cur_chunk_array->dump()
0: [TEXT("foo: ")]
1: [TEXT("i")]
2: [TEXT(", bar: ")]
3: [TEXT("s")]
4: [TEXT(", opt: ")]
5: [TEXT("qs")]
The second phase replaces all odd-numbered chunks with formatted
token lists. In the above example, after phase 2 we might have:
(gdb) call pp->m_buffer->cur_chunk_array->dump()
0: [TEXT("foo: ")]
1: [TEXT("42")]
2: [TEXT(", bar: ")]
3: [TEXT("baz")]
4: [TEXT(", opt: ")]
5: [BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
For example the %qs has become the three tokens:
[BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
The third phase (in pp_output_formatted_text):
(1) merges the tokens from all the chunks into one list,
giving e.g.
(gdb) call tokens.dump()
[TEXT("foo: "), TEXT("42"), TEXT(", bar: "), TEXT("baz"),
TEXT(", opt: "), BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
(2) lowers some custom tokens into non-custom tokens
(3) merges consecutive text tokens, giving e.g.:
(gdb) call tokens.dump()
[TEXT("foo: 42, bar: baz, option: "),
BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
(4) if provided with a urlifier, tries to apply it to quoted text,
giving e.g:
(gdb) call tokens.dump()
[TEXT("foo: 42, bar: baz, option: "), BEGIN_QUOTE,
BEGIN_URL("http://example.com"), TEXT("-foption"), END_URL, END_QUOTE]
(5) emits all tokens in sequence with appropriate line-wrapping. This
can be overridded via the pretty_printer's token_printer, allowing for
output formats to e.g. override how URLs are handled, or to handle
custom_data that wasn't lowered in (2) above, e.g. for handling JSON
output of optimization records. */
pp_token_list *m_args[PP_NL_ARGMAX * 2];
/* The pp_tokens, pp_token_lists, and the accumulated text buffers are
allocated within the output_buffer's chunk_obstack. In the above
example, the in-memory layout of the chunk_obstack might look like
this after phase 1:
+ pp_token_list for chunk 0 (m_first: *) <--- START of chunk_info level
| |
+ "foo: \0" <-------------\ |
| | |
+ pp_token_text (borrowed: *) <-------/
|
+ pp_token_list for chunk 1
|
+ "i\0" <------------------\
| |
+ pp_token_text (borrowed: *)
|
+ ...etc for chunks 2 to 4...
|
+ pp_token_list for chunk 5
|
+ "qs\0" <-----------------\
| |
+ pp_token_text (borrowed: *)
|
|
V
obstack grows this way
At each stage, allocation of additional text buffers, tokens, and lists
grow forwards in the obstack (though the internal pointers in linked
lists might point backwards to earlier objects within the same
chunk_info level). */
};
#endif /* GCC_PRETTY_PRINT_FORMAT_IMPL_H */

View file

@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-color.h"
class pp_token_list;
namespace pp_markup {
class context
@ -31,12 +33,12 @@ public:
output_buffer &buf,
unsigned chunk_idx,
bool &quoted,
const urlifier *urlifier)
pp_token_list *formatted_token_list)
: m_pp (pp),
m_buf (buf),
m_chunk_idx (chunk_idx),
m_quoted (quoted),
m_urlifier (urlifier)
m_formatted_token_list (formatted_token_list)
{
}
@ -46,11 +48,13 @@ public:
void begin_highlight_color (const char *color_name);
void end_highlight_color ();
void push_back_any_text ();
pretty_printer &m_pp;
output_buffer &m_buf;
unsigned m_chunk_idx;
bool &m_quoted;
const urlifier *m_urlifier;
pp_token_list *m_formatted_token_list;
};
/* Abstract base class for use in pp_format for handling "%e".

View file

@ -20,7 +20,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_PRETTY_PRINT_URLIFIER_H
#define GCC_PRETTY_PRINT_URLIFIER_H
/* Abstract base class for optional use in pp_format for adding URLs
/* Abstract base class for optional use in pretty-printing for adding URLs
to quoted text strings. */
class urlifier

File diff suppressed because it is too large Load diff

View file

@ -70,8 +70,8 @@ enum diagnostic_prefixing_rule_t
};
class chunk_info;
class quoting_info;
class output_buffer;
class pp_token_list;
class urlifier;
namespace pp_markup {
@ -177,7 +177,7 @@ struct pp_wrapping_mode_t
A client-supplied formatter returns true if everything goes well,
otherwise it returns false. */
typedef bool (*printer_fn) (pretty_printer *, text_info *, const char *,
int, bool, bool, bool, bool *, const char **);
int, bool, bool, bool, bool *, pp_token_list &);
/* Base class for an optional client-supplied object for doing additional
processing between stages 2 and 3 of formatted printing. */
@ -189,6 +189,18 @@ class format_postprocessor
virtual void handle (pretty_printer *) = 0;
};
/* Abstract base class for writing formatted tokens to the pretty_printer's
text buffer, allowing for output formats and dumpfiles to override
how different kinds of tokens are handled. */
class token_printer
{
public:
virtual ~token_printer () {}
virtual void print_tokens (pretty_printer *pp,
const pp_token_list &tokens) = 0;
};
inline bool & pp_needs_newline (pretty_printer *pp);
/* True if PRETTY-PRINTER is in line-wrapping mode. */
@ -236,6 +248,9 @@ public:
friend format_postprocessor *& pp_format_postprocessor (pretty_printer *pp);
friend bool & pp_show_highlight_colors (pretty_printer *pp);
friend void pp_output_formatted_text (pretty_printer *,
const urlifier *);
/* Default construct a pretty printer with specified
maximum line length cut off limit. */
explicit pretty_printer (int = 0);
@ -250,12 +265,16 @@ public:
m_buffer->stream = outfile;
}
void set_token_printer (token_printer* tp)
{
m_token_printer = tp; // borrowed
}
void set_prefix (char *prefix);
void emit_prefix ();
void format (text_info *text,
const urlifier *urlifier);
void format (text_info *text);
void maybe_space ();
@ -314,8 +333,9 @@ private:
If the BUFFER needs additional characters from the format string, it
should advance the TEXT->format_spec as it goes. When FORMAT_DECODER
returns, TEXT->format_spec should point to the last character processed.
The QUOTE and BUFFER_PTR are passed in, to allow for deferring-handling
of format codes (e.g. %H and %I in the C++ frontend). */
The QUOTE and FORMATTED_TOKEN_LIST are passed in, to allow for
deferring-handling of format codes (e.g. %H and %I in
the C++ frontend). */
printer_fn m_format_decoder;
/* If non-NULL, this is called by pp_format once after all format codes
@ -324,6 +344,12 @@ private:
format codes (which interract with each other). */
format_postprocessor *m_format_postprocessor;
/* This is used by pp_output_formatted_text after it has converted all
formatted chunks into a single list of tokens.
Can be nullptr.
Borrowed from the output format or from dump_pretty_printer. */
token_printer *m_token_printer;
/* Nonzero if current PREFIX was emitted at least once. */
bool m_emitted_prefix;
@ -543,10 +569,9 @@ extern void pp_verbatim (pretty_printer *, const char *, ...)
ATTRIBUTE_GCC_PPDIAG(2,3);
extern void pp_flush (pretty_printer *);
extern void pp_really_flush (pretty_printer *);
inline void pp_format (pretty_printer *pp, text_info *text,
const urlifier *urlifier = nullptr)
inline void pp_format (pretty_printer *pp, text_info *text)
{
pp->format (text, urlifier);
pp->format (text);
}
extern void pp_output_formatted_text (pretty_printer *,
const urlifier * = nullptr);

View file

@ -55,7 +55,7 @@ default_tree_diagnostic_starter (diagnostic_context *context,
bool
default_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
int precision, bool wide, bool set_locus, bool hash,
bool *, const char **)
bool *, pp_token_list &)
{
tree t;

View file

@ -53,6 +53,6 @@ void diagnostic_report_current_function (diagnostic_context *,
void tree_diagnostics_defaults (diagnostic_context *context);
bool default_tree_printer (pretty_printer *, text_info *, const char *,
int, bool, bool, bool, bool *, const char **);
int, bool, bool, bool, bool *, pp_token_list &);
#endif /* ! GCC_TREE_DIAGNOSTIC_H */