diff mbox

Clean up pretty printers [10/n]

Message ID 87ioyyqatx.fsf@euclid.axiomatics.org
State New
Headers show

Commit Message

Gabriel Dos Reis Aug. 22, 2013, 10:27 a.m. UTC
This patch consolidates initialization routines of various pretty
printers -- at the moment, we have unfortunately very few (basic, C, C++).
It adds a default constructor to pretty_printer (which in turn made
obvious we needed one for output_buffer), c_pretty_printer, and
cxx_pretty_printer.   The rest of the patch is just propagating these
things by removing direct calls to pp_construct,
pp_c_pretty_printer_init, and pp_cxx_pretty_printer_init.  Now, we are
guaranteed that initialization of any pretty printer derived from
pretty_printer will initialize the base subobjects (good!)

Our existing XNEW placebo doesn't do what is expected by a C++
programmer, which is to call the constructor to initialize the object.
So, I use placement-new at select places to ensure the Right Thing is done.
As you know, placement-new doesn't allocate memory; its only effect is
to "call" the right constructor.

We need to revisit our design and policy with regard to XNEW and friends.
But that is a debate for a separate thread.

Finally, we really need to get rid of pretty printers with static
storage duration.  I removed almost all of them in previous patches
except two: one is left in tree-pretty-printer.c , and one in cp/error.c.

Tested on an x86_64-suse-linux.  Applied to trunk.

-- Gaby

2013-08-22  Gabriel Dos Reis  <gdr@integrable-solutions.net>

	* pretty-print.h (output_buffer::output_buffer): Declare.
	(pretty_printer::pretty_printer): Likewise.
	(pp_construct): Remove.
	* pretty-print.c (output_buffer::output_buffer): Define.
	(pretty_printer::pretty_printer): Rename from pp_construct.  Simplify.
	* gimple-pretty-print.c (print_gimple_stmt): Do not call pp_construct.
	(print_gimple_expr): Likewise.
	(print_gimple_seq): Likewise.
	(gimple_dump_bb): Likewise.
	* sched-vis.c (dump_value_slim): Likewise.
	(dump_insn_slim): Likewise.
	(dump_rtl_slim): Likewise.
	(str_pattern_slim): Likewise.
	* tree-mudflap.c (mf_varname_tree): Likewise.
	* graph.c (print_graph_cfg): Likewise.
	(start_graph_dump): Likewise.
	* tree-pretty-print.c (maybe_init_pretty_print): Likewise.  Use
	placement-new.
	* diagnostic.c (diagnostic_initialize): Simplify early diagnostic
	pretty printer initialization.
	* coretypes.h (diagnostic_context): Remove superflous type alias
	declaration.
	(pretty_printer): Likewise.  Declare directly as a class.
	(pretty_print_info): Remove declaration as class.
	* asan.c (asan_emit_stack_protection): Remove call to pp_construct
	and pp_clear_output_area.
	(asan_add_global): Likewise.

c/
	* c-objc-common.c (c_initialize_diagnostics): Simplify C pretty
	printer initialization.

c-family/
	* c-pretty-print.h (pp_c_pretty_printer_init): Remove.
	(c_pretty_printer::c_pretty_printer): Declare.
	* c-pretty-print.c (pretty_printer::c_pretty_printer): Rename from
	c_pretty_printer_init.  Adjust.
	(print_c_tree): Do not call c_pretty_printer_init.
	* c-ada-spec.c (dump_ads): Remove call to pp_construct.

cp/
	* error.c (init_error): Remove calls to pp_construct and
	pp_cxx_pretty_printer_init.  Initialize cxx_pp with placement-new.
	* cxx-pretty-print.h (cxx_pretty_printer::cxx_pretty_printer): Declare.
	(cxx_pretty_printer_init): Remove.
	* cxx-pretty-print.c (cxx_pretty_printer::cxx_pretty_printer):
	Rename from cxx_pretty_printer_init.  Adjust.
	* cp-objcp-common.c (cxx_initialize_diagnostics): Simplify
	initialization of C++ diagnostics pretty printer.

Comments

Jakub Jelinek Feb. 12, 2014, 4:29 p.m. UTC | #1
On Thu, Aug 22, 2013 at 05:27:54AM -0500, Gabriel Dos Reis wrote:
> 	* error.c (init_error): Remove calls to pp_construct and
> 	pp_cxx_pretty_printer_init.  Initialize cxx_pp with placement-new.
> 	* cxx-pretty-print.h (cxx_pretty_printer::cxx_pretty_printer): Declare.
> 	(cxx_pretty_printer_init): Remove.
> 	* cxx-pretty-print.c (cxx_pretty_printer::cxx_pretty_printer):
> 	Rename from cxx_pretty_printer_init.  Adjust.
> 	* cp-objcp-common.c (cxx_initialize_diagnostics): Simplify
> 	initialization of C++ diagnostics pretty printer.

> --- cp/error.c	(revision 201904)
> +++ cp/error.c	(working copy)
> @@ -33,6 +33,8 @@
>  #include "pointer-set.h"
>  #include "c-family/c-objc.h"
>  
> +#include <new>                    // For placement-new.
> +
>  #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
>  #define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
>  
> @@ -109,8 +111,7 @@
>    diagnostic_finalizer (global_dc) = cp_diagnostic_finalizer;
>    diagnostic_format_decoder (global_dc) = cp_printer;
>  
> -  pp_construct (cxx_pp, NULL, 0);
> -  pp_cxx_pretty_printer_init (cxx_pp);
> +  new (cxx_pp) cxx_pretty_printer ();

Unfortunately this always leaks memory,
static cxx_pretty_printer scratch_pretty_printer;
is constructed first during static initialization, where it e.g. allocates
through XNEW the buffer, and then when init_error is called, it ignores
the old content of scratch_pretty_printer and constructs the same objects
again.  Why is the new (cxx_pp) cxx_pretty_printer (); line needed at all?
Isn't it already constructed with the right ctor?
Or, shouldn't it at least first try to call destructor?

I think there are more spots with placement new, perhaps all have the same
issue?

	Jakub
diff mbox

Patch

Index: asan.c
===================================================================
--- asan.c	(revision 201904)
+++ asan.c	(working copy)
@@ -938,9 +938,7 @@ 
 
   /* First of all, prepare the description string.  */
   pretty_printer asan_pp;
-  pp_construct (&asan_pp, /* prefix */NULL, /* line-width */0);
-  
-  pp_clear_output_area (&asan_pp);
+
   if (DECL_NAME (current_function_decl))
     pp_tree_identifier (&asan_pp, DECL_NAME (current_function_decl));
   else
@@ -1963,9 +1961,7 @@ 
   vec<constructor_elt, va_gc> *vinner = NULL;
 
   pretty_printer asan_pp;
-  pp_construct (&asan_pp, /* prefix */NULL, /* line-width */0);
 
-  pp_clear_output_area (&asan_pp);
   if (DECL_NAME (decl))
     pp_tree_identifier (&asan_pp, DECL_NAME (decl));
   else
Index: c/c-objc-common.c
===================================================================
--- c/c-objc-common.c	(revision 201904)
+++ c/c-objc-common.c	(working copy)
@@ -30,6 +30,8 @@ 
 #include "langhooks.h"
 #include "c-objc-common.h"
 
+#include <new>                          // For placement new.
+
 static bool c_tree_printer (pretty_printer *, text_info *, const char *,
 			    int, bool, bool, bool);
 
@@ -183,16 +185,11 @@ 
 void
 c_initialize_diagnostics (diagnostic_context *context)
 {
-  pretty_printer *base;
-  c_pretty_printer *pp;
-
   c_common_initialize_diagnostics (context);
 
-  base = context->printer;
-  pp = XNEW (c_pretty_printer);
-  memcpy (pp, base, sizeof (pretty_printer));
-  pp_c_pretty_printer_init (pp);
-  context->printer = (pretty_printer *) pp;
+  pretty_printer *base = context->printer;
+  c_pretty_printer *pp = XNEW (c_pretty_printer);
+  context->printer = new (pp) c_pretty_printer ();
 
   /* It is safe to free this object because it was previously XNEW()'d.  */
   XDELETE (base);
Index: c-family/c-ada-spec.c
===================================================================
--- c-family/c-ada-spec.c	(revision 201904)
+++ c-family/c-ada-spec.c	(working copy)
@@ -3304,7 +3304,6 @@ 
     {
       pretty_printer pp;
 
-      pp_construct (&pp, NULL, 0);
       pp_needs_newline (&pp) = true;
       pp.buffer->stream = f;
 
Index: c-family/c-pretty-print.c
===================================================================
--- c-family/c-pretty-print.c	(revision 201904)
+++ c-family/c-pretty-print.c	(working copy)
@@ -2318,39 +2318,37 @@ 
 
 /* Initialize the PRETTY-PRINTER for handling C codes.  */
 
-void
-pp_c_pretty_printer_init (c_pretty_printer *pp)
+c_pretty_printer::c_pretty_printer ()
+  : pretty_printer ()
 {
-  pp->offset_list               = 0;
+  offset_list               = 0;
+  flags			= 0;
+  declaration               = pp_c_declaration;
+  declaration_specifiers    = pp_c_declaration_specifiers;
+  declarator                = pp_c_declarator;
+  direct_declarator         = pp_c_direct_declarator;
+  type_specifier_seq        = pp_c_specifier_qualifier_list;
+  abstract_declarator       = pp_c_abstract_declarator;
+  direct_abstract_declarator = pp_c_direct_abstract_declarator;
+  ptr_operator              = pp_c_pointer;
+  parameter_list            = pp_c_parameter_type_list;
+  type_id                   = pp_c_type_id;
+  simple_type_specifier     = pp_c_type_specifier;
+  function_specifier        = pp_c_function_specifier;
+  storage_class_specifier   = pp_c_storage_class_specifier;
 
-  pp->flags			= 0;
+  statement                 = pp_c_statement;
 
-  pp->declaration               = pp_c_declaration;
-  pp->declaration_specifiers    = pp_c_declaration_specifiers;
-  pp->declarator                = pp_c_declarator;
-  pp->direct_declarator         = pp_c_direct_declarator;
-  pp->type_specifier_seq        = pp_c_specifier_qualifier_list;
-  pp->abstract_declarator       = pp_c_abstract_declarator;
-  pp->direct_abstract_declarator = pp_c_direct_abstract_declarator;
-  pp->ptr_operator              = pp_c_pointer;
-  pp->parameter_list            = pp_c_parameter_type_list;
-  pp->type_id                   = pp_c_type_id;
-  pp->simple_type_specifier     = pp_c_type_specifier;
-  pp->function_specifier        = pp_c_function_specifier;
-  pp->storage_class_specifier   = pp_c_storage_class_specifier;
-
-  pp->statement                 = pp_c_statement;
-
-  pp->constant                  = pp_c_constant;
-  pp->id_expression             = pp_c_id_expression;
-  pp->primary_expression        = pp_c_primary_expression;
-  pp->postfix_expression        = pp_c_postfix_expression;
-  pp->unary_expression          = pp_c_unary_expression;
-  pp->initializer               = pp_c_initializer;
-  pp->multiplicative_expression = pp_c_multiplicative_expression;
-  pp->conditional_expression    = pp_c_conditional_expression;
-  pp->assignment_expression     = pp_c_assignment_expression;
-  pp->expression                = pp_c_expression;
+  constant                  = pp_c_constant;
+  id_expression             = pp_c_id_expression;
+  primary_expression        = pp_c_primary_expression;
+  postfix_expression        = pp_c_postfix_expression;
+  unary_expression          = pp_c_unary_expression;
+  initializer               = pp_c_initializer;
+  multiplicative_expression = pp_c_multiplicative_expression;
+  conditional_expression    = pp_c_conditional_expression;
+  assignment_expression     = pp_c_assignment_expression;
+  expression                = pp_c_expression;
 }
 
 
@@ -2360,8 +2358,7 @@ 
 print_c_tree (FILE *file, tree t)
 {
   c_pretty_printer pp;
-  pp_construct (&pp, NULL, 0);
-  pp_c_pretty_printer_init (&pp);
+
   pp_needs_newline (&pp) = true;
   pp.buffer->stream = file;
   pp_statement (&pp, t);
Index: c-family/c-pretty-print.h
===================================================================
--- c-family/c-pretty-print.h	(revision 201904)
+++ c-family/c-pretty-print.h	(working copy)
@@ -49,6 +49,8 @@ 
    and cp/cxx-pretty-print.c for an example of derivation.  */
 struct c_pretty_printer : pretty_printer
 {
+  c_pretty_printer ();
+
   /* Points to the first element of an array of offset-list.
      Not used yet.  */
   int *offset_list;
@@ -120,7 +122,6 @@ 
 #define pp_expression(PP, E)            (PP)->expression (PP, E)
 
 
-extern void pp_c_pretty_printer_init (c_pretty_printer *);
 void pp_c_whitespace (c_pretty_printer *);
 void pp_c_left_paren (c_pretty_printer *);
 void pp_c_right_paren (c_pretty_printer *);
Index: coretypes.h
===================================================================
--- coretypes.h	(revision 201904)
+++ coretypes.h	(working copy)
@@ -73,9 +73,7 @@ 
 struct cl_decoded_option;
 struct cl_option_handlers;
 struct diagnostic_context;
-typedef struct diagnostic_context diagnostic_context;
-struct pretty_print_info;
-typedef struct pretty_print_info pretty_printer;
+struct pretty_printer;
 
 /* Address space number for named address space support.  */
 typedef unsigned char addr_space_t;
Index: cp/cp-objcp-common.c
===================================================================
--- cp/cp-objcp-common.c	(revision 201904)
+++ cp/cp-objcp-common.c	(working copy)
@@ -32,6 +32,8 @@ 
 #include "cxx-pretty-print.h"
 #include "cp-objcp-common.h"
 
+#include <new>                       // For placement new.
+
 /* Special routine to get the alias set for C++.  */
 
 alias_set_type
@@ -131,19 +133,14 @@ 
 void
 cxx_initialize_diagnostics (diagnostic_context *context)
 {
-  pretty_printer *base;
-  cxx_pretty_printer *pp;
-
   c_common_initialize_diagnostics (context);
 
-  base = context->printer;
-  pp = XNEW (cxx_pretty_printer);
-  memcpy (pp, base, sizeof (pretty_printer));
-  pp_cxx_pretty_printer_init (pp);
-  context->printer = (pretty_printer *) pp;
+  pretty_printer *base = context->printer;
+  cxx_pretty_printer *pp = XNEW (cxx_pretty_printer);
+  context->printer = new (pp) cxx_pretty_printer ();
 
-  /* It is safe to free this object because it was previously malloc()'d.  */
-  free (base);
+  /* It is safe to free this object because it was previously XNEW()'d.  */
+  XDELETE (base);
 }
 
 /* This compares two types for equivalence ("compatible" in C-based languages).
Index: cp/cxx-pretty-print.c
===================================================================
--- cp/cxx-pretty-print.c	(revision 201904)
+++ cp/cxx-pretty-print.c	(working copy)
@@ -2432,34 +2432,33 @@ 
 
 /* Initialization of a C++ pretty-printer object.  */
 
-void
-pp_cxx_pretty_printer_init (cxx_pretty_printer *pp)
+cxx_pretty_printer::cxx_pretty_printer ()
+  : c_pretty_printer (),
+    enclosing_scope (global_namespace)
 {
-  pp_c_pretty_printer_init (pp);
-  pp_set_line_maximum_length (pp, 0);
+  pp_set_line_maximum_length (this, 0);
 
-  pp->declaration = (pp_fun) pp_cxx_declaration;
-  pp->declaration_specifiers = (pp_fun) pp_cxx_decl_specifier_seq;
-  pp->function_specifier = (pp_fun) pp_cxx_function_specifier;
-  pp->type_specifier_seq = (pp_fun) pp_cxx_type_specifier_seq;
-  pp->declarator = (pp_fun) pp_cxx_declarator;
-  pp->direct_declarator = (pp_fun) pp_cxx_direct_declarator;
-  pp->parameter_list = (pp_fun) pp_cxx_parameter_declaration_clause;
-  pp->type_id = (pp_fun) pp_cxx_type_id;
-  pp->abstract_declarator = (pp_fun) pp_cxx_abstract_declarator;
-  pp->direct_abstract_declarator = (pp_fun) pp_cxx_direct_abstract_declarator;
-  pp->simple_type_specifier = (pp_fun) pp_cxx_simple_type_specifier;
+  declaration = (pp_fun) pp_cxx_declaration;
+  declaration_specifiers = (pp_fun) pp_cxx_decl_specifier_seq;
+  function_specifier = (pp_fun) pp_cxx_function_specifier;
+  type_specifier_seq = (pp_fun) pp_cxx_type_specifier_seq;
+  declarator = (pp_fun) pp_cxx_declarator;
+  direct_declarator = (pp_fun) pp_cxx_direct_declarator;
+  parameter_list = (pp_fun) pp_cxx_parameter_declaration_clause;
+  type_id = (pp_fun) pp_cxx_type_id;
+  abstract_declarator = (pp_fun) pp_cxx_abstract_declarator;
+  direct_abstract_declarator = (pp_fun) pp_cxx_direct_abstract_declarator;
+  simple_type_specifier = (pp_fun) pp_cxx_simple_type_specifier;
 
   /* pp->statement = (pp_fun) pp_cxx_statement;  */
 
-  pp->constant = (pp_fun) pp_cxx_constant;
-  pp->id_expression = (pp_fun) pp_cxx_id_expression;
-  pp->primary_expression = (pp_fun) pp_cxx_primary_expression;
-  pp->postfix_expression = (pp_fun) pp_cxx_postfix_expression;
-  pp->unary_expression = (pp_fun) pp_cxx_unary_expression;
-  pp->multiplicative_expression = (pp_fun) pp_cxx_multiplicative_expression;
-  pp->conditional_expression = (pp_fun) pp_cxx_conditional_expression;
-  pp->assignment_expression = (pp_fun) pp_cxx_assignment_expression;
-  pp->expression = (pp_fun) pp_cxx_expression;
-  pp->enclosing_scope = global_namespace;
+  constant = (pp_fun) pp_cxx_constant;
+  id_expression = (pp_fun) pp_cxx_id_expression;
+  primary_expression = (pp_fun) pp_cxx_primary_expression;
+  postfix_expression = (pp_fun) pp_cxx_postfix_expression;
+  unary_expression = (pp_fun) pp_cxx_unary_expression;
+  multiplicative_expression = (pp_fun) pp_cxx_multiplicative_expression;
+  conditional_expression = (pp_fun) pp_cxx_conditional_expression;
+  assignment_expression = (pp_fun) pp_cxx_assignment_expression;
+  expression = (pp_fun) pp_cxx_expression;
 }
Index: cp/cxx-pretty-print.h
===================================================================
--- cp/cxx-pretty-print.h	(revision 201904)
+++ cp/cxx-pretty-print.h	(working copy)
@@ -31,6 +31,7 @@ 
 
 struct cxx_pretty_printer : c_pretty_printer
 {
+  cxx_pretty_printer ();
   /* This is the enclosing scope of the entity being pretty-printed.  */
   tree enclosing_scope;
 };
@@ -59,7 +60,6 @@ 
 #define pp_cxx_tree_identifier(PP, T) \
   pp_c_tree_identifier (PP, T)
 
-void pp_cxx_pretty_printer_init (cxx_pretty_printer *);
 void pp_cxx_begin_template_argument_list (cxx_pretty_printer *);
 void pp_cxx_end_template_argument_list (cxx_pretty_printer *);
 void pp_cxx_colon_colon (cxx_pretty_printer *);
Index: cp/error.c
===================================================================
--- cp/error.c	(revision 201904)
+++ cp/error.c	(working copy)
@@ -33,6 +33,8 @@ 
 #include "pointer-set.h"
 #include "c-family/c-objc.h"
 
+#include <new>                    // For placement-new.
+
 #define pp_separate_with_comma(PP) pp_cxx_separate_with (PP, ',')
 #define pp_separate_with_semicolon(PP) pp_cxx_separate_with (PP, ';')
 
@@ -109,8 +111,7 @@ 
   diagnostic_finalizer (global_dc) = cp_diagnostic_finalizer;
   diagnostic_format_decoder (global_dc) = cp_printer;
 
-  pp_construct (cxx_pp, NULL, 0);
-  pp_cxx_pretty_printer_init (cxx_pp);
+  new (cxx_pp) cxx_pretty_printer ();
 }
 
 /* Dump a scope, if deemed necessary.  */
Index: diagnostic.c
===================================================================
--- diagnostic.c	(revision 201904)
+++ diagnostic.c	(working copy)
@@ -33,6 +33,8 @@ 
 #include "diagnostic.h"
 #include "diagnostic-color.h"
 
+#include <new>                     // For placement new.
+
 #define pedantic_warning_kind(DC)			\
   ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
 #define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
@@ -120,11 +122,7 @@ 
   /* Allocate a basic pretty-printer.  Clients will replace this a
      much more elaborated pretty-printer if they wish.  */
   context->printer = XNEW (pretty_printer);
-  pp_construct (context->printer, NULL, 0);
-  /* By default, diagnostics are sent to stderr.  */
-  context->printer->buffer->stream = stderr;
-  /* By default, we emit prefixes once per message.  */
-  context->printer->wrapping.rule = DIAGNOSTICS_SHOW_PREFIX_ONCE;
+  new (context->printer) pretty_printer ();
 
   memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
   context->some_warnings_are_errors = false;
Index: gimple-pretty-print.c
===================================================================
--- gimple-pretty-print.c	(revision 201904)
+++ gimple-pretty-print.c	(working copy)
@@ -75,7 +75,6 @@ 
 print_gimple_stmt (FILE *file, gimple g, int spc, int flags)
 {
   pretty_printer buffer;
-  pp_construct (&buffer, NULL, 0);
   pp_needs_newline (&buffer) = true;
   buffer.buffer->stream = file;
   pp_gimple_stmt_1 (&buffer, g, spc, flags);
@@ -107,7 +106,6 @@ 
 {
   flags |= TDF_RHS_ONLY;
   pretty_printer buffer;
-  pp_construct (&buffer, NULL, 0);
   pp_needs_newline (&buffer) = true;
   buffer.buffer->stream = file;
   pp_gimple_stmt_1 (&buffer, g, spc, flags);
@@ -143,7 +141,6 @@ 
 print_gimple_seq (FILE *file, gimple_seq seq, int spc, int flags)
 {
   pretty_printer buffer;
-  pp_construct (&buffer, NULL, 0);
   pp_needs_newline (&buffer) = true;
   buffer.buffer->stream = file;
   dump_gimple_seq (&buffer, seq, spc, flags);
@@ -2270,7 +2267,6 @@ 
   if (bb->index >= NUM_FIXED_BLOCKS)
     {
       pretty_printer buffer;
-      pp_construct (&buffer, NULL, 0);
       pp_needs_newline (&buffer) = true;
       buffer.buffer->stream = file;
       gimple_dump_bb_buff (&buffer, bb, indent, flags);
Index: graph.c
===================================================================
--- graph.c	(revision 201904)
+++ graph.c	(working copy)
@@ -278,7 +278,6 @@ 
   const char *funcname = function_name (fun);
   FILE *fp = open_graph_file (base, "a");
   pretty_printer graph_slim_pp;
-  pp_construct (&graph_slim_pp, /*prefix=*/NULL, /*linewidth=*/0);
   graph_slim_pp.buffer->stream = fp;
   pretty_printer *const pp = &graph_slim_pp;
   pp_printf (pp, "subgraph \"%s\" {\n"
@@ -297,7 +296,6 @@ 
 start_graph_dump (FILE *fp, const char *base)
 {
   pretty_printer graph_slim_pp;
-  pp_construct (&graph_slim_pp, /*prefix=*/NULL, /*linewidth=*/0);
   graph_slim_pp.buffer->stream = fp;
   pretty_printer *const pp = &graph_slim_pp;
   pp_string (pp, "digraph \"");
Index: pretty-print.c
===================================================================
--- pretty-print.c	(revision 201904)
+++ pretty-print.c	(working copy)
@@ -25,10 +25,27 @@ 
 #include "pretty-print.h"
 #include "diagnostic-color.h"
 
+#include <new>                    // For placement-new.
+
 #if HAVE_ICONV
 #include <iconv.h>
 #endif
 
+// Default construct an output buffer.
+
+output_buffer::output_buffer ()
+  : formatted_obstack (),
+    chunk_obstack (),
+    obstack (&formatted_obstack),
+    cur_chunk_array (),
+    stream (stderr),
+    line_length (),
+    digit_buffer ()
+{
+  obstack_init (&formatted_obstack);
+  obstack_init (&chunk_obstack);
+}
+
 /* A pointer to the formatted diagnostic message.  */
 #define pp_formatted_text_data(PP) \
    ((const char *) obstack_base ((PP)->buffer->obstack))
@@ -736,19 +753,24 @@ 
 
 /* Construct a PRETTY-PRINTER with PREFIX and of MAXIMUM_LENGTH
    characters per line.  */
-void
-pp_construct (pretty_printer *pp, const char *prefix, int maximum_length)
+
+pretty_printer::pretty_printer (const char *p, int l)
+  : buffer (new (XCNEW (output_buffer)) output_buffer ()),
+    prefix (),
+    padding (pp_none),
+    maximum_length (),
+    indent_skip (),
+    wrapping (),
+    format_decoder (),
+    emitted_prefix (),
+    need_newline (),
+    translate_identifiers(true),
+    show_color ()
 {
-  memset (pp, 0, sizeof (pretty_printer));
-  pp->buffer = XCNEW (output_buffer);
-  obstack_init (&pp->buffer->chunk_obstack);
-  obstack_init (&pp->buffer->formatted_obstack);
-  pp->buffer->obstack = &pp->buffer->formatted_obstack;
-  pp->buffer->stream = stderr;
-  pp_line_cutoff (pp) = maximum_length;
-  pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
-  pp_set_prefix (pp, prefix);
-  pp_translate_identifiers (pp) = true;
+  pp_line_cutoff (this) = l;
+  /* By default, we emit prefixes once per message.  */
+  pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
+  pp_set_prefix (this, p);
 }
 
 /* Append a string delimited by START and END to the output area of
Index: pretty-print.h
===================================================================
--- pretty-print.h	(revision 201904)
+++ pretty-print.h	(working copy)
@@ -73,6 +73,8 @@ 
    whose fields should not be accessed directly by clients.  */
 struct output_buffer
 {
+  output_buffer ();
+
   /* Obstack where the text is built up.  */
   struct obstack formatted_obstack;
 
@@ -157,8 +159,12 @@ 
 /* The data structure that contains the bare minimum required to do
    proper pretty-printing.  Clients may derived from this structure
    and add additional fields they need.  */
-struct pretty_print_info
+struct pretty_printer
 {
+  // Default construct a pretty printer with specified prefix
+  // and a maximum line length cut off limit.
+  explicit pretty_printer (const char* = NULL, int = 0);
+
   /* Where we print external representation of ENTITY.  */
   output_buffer *buffer;
 
@@ -283,7 +289,6 @@ 
 
 #define pp_buffer(PP) (PP)->buffer
 
-extern void pp_construct (pretty_printer *, const char *, int);
 extern void pp_set_line_maximum_length (pretty_printer *, int);
 extern void pp_set_prefix (pretty_printer *, const char *);
 extern void pp_destroy_prefix (pretty_printer *);
Index: sched-vis.c
===================================================================
--- sched-vis.c	(revision 201904)
+++ sched-vis.c	(working copy)
@@ -766,7 +766,6 @@ 
 dump_value_slim (FILE *f, const_rtx x, int verbose)
 {
   pretty_printer rtl_slim_pp;
-  pp_construct (&rtl_slim_pp, /*prefix=*/NULL, /*linewidth=*/0);
   rtl_slim_pp.buffer->stream = f;
   print_value (&rtl_slim_pp, x, verbose);
   pp_flush (&rtl_slim_pp);
@@ -778,7 +777,6 @@ 
 dump_insn_slim (FILE *f, const_rtx x)
 {
   pretty_printer rtl_slim_pp;
-  pp_construct (&rtl_slim_pp, /*prefix=*/NULL, /*linewidth=*/0);
   rtl_slim_pp.buffer->stream = f;
   print_insn_with_notes (&rtl_slim_pp, x);
   pp_flush (&rtl_slim_pp);
@@ -793,7 +791,6 @@ 
 {
   const_rtx insn, tail;
   pretty_printer rtl_slim_pp;
-  pp_construct (&rtl_slim_pp, /*prefix=*/NULL, /*linewidth=*/0);
   rtl_slim_pp.buffer->stream = f;
 
   tail = last ? NEXT_INSN (last) : NULL_RTX;
@@ -842,7 +839,6 @@ 
 str_pattern_slim (const_rtx x)
 {
   pretty_printer rtl_slim_pp;
-  pp_construct (&rtl_slim_pp, /*prefix=*/NULL, /*linewidth=*/0);
   print_pattern (&rtl_slim_pp, x, 0);
   return ggc_strdup (pp_formatted_text (&rtl_slim_pp));
 }
Index: tree-mudflap.c
===================================================================
--- tree-mudflap.c	(revision 201904)
+++ tree-mudflap.c	(working copy)
@@ -112,8 +112,6 @@ 
   gcc_assert (decl);
 
   pretty_printer buf;
-  pp_construct (&buf, /* prefix */ NULL, /* line-width */ 0);
-  pp_clear_output_area (&buf);
 
   /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]].  */
   {
Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c	(revision 201904)
+++ tree-pretty-print.c	(working copy)
@@ -33,6 +33,8 @@ 
 #include "value-prof.h"
 #include "predict.h"
 
+#include <new>                           // For placement-new.
+
 /* Local functions, macros and variables.  */
 static const char *op_symbol (const_tree);
 static void pretty_print_string (pretty_printer *, const char*);
@@ -3059,7 +3061,7 @@ 
 {
   if (!initialized)
     {
-      pp_construct (&buffer, /* prefix */NULL, /* line-width */0);
+      new (&buffer) pretty_printer ();
       pp_needs_newline (&buffer) = true;
       pp_translate_identifiers (&buffer) = false;
       initialized = 1;