diff mbox

C/C++: fix quoting of "aka" typedef information (PR 62170)

Message ID 1496689294-11629-1-git-send-email-dmalcolm@redhat.com
State New
Headers show

Commit Message

David Malcolm June 5, 2017, 7:01 p.m. UTC
PR 62170 describes a problem with how the quoting in pp_format
interacts with the "aka" information for typedefs in %qT for
the C family of frontends, and also now for %qH and %qI in the
C++ frontend.

Currently for %qT we print e.g.:

  ‘Py_ssize_t* {aka int*}’
   ^^^^^^^^^^^^^^^^^^^^^^ colorized as "quote"

i.e.
  ‘[START_COLOR]Py_ssize_t* {aka int*}[END_COLOR]’

when we should print:

  ‘Py_ssize_t*’ {aka ‘int*’}
   ^^^^^^^^^^^        ^^^^ colorized as "quote"

i.e.
  ‘[START_COLOR]Py_ssize_t*[END_COLOR]’ {aka ‘[START_COLOR]int*[END_COLOR]’}

where the opening and closing quote characters and colorization are
currently added by the 'q' handling within pp_format, adding the closing
quote unconditionally after whatever pp_format_decoder prints for 'T'
within "%qT".

This patch fixes the quoting by updating the %T handling in C and C++
and the %H/%I handling in C++ to insert the quoting appropriately.
It converts the "quote" param of the pp_format_decoder callback from
bool to bool *, allowing for the %T and %H/%I handlers to write
false back to it, to avoid printing the closing quote for the cases
like the above where a final trailing closing quote isn't needed.

It introduces pp_begin_quote/pp_end_quote to simplify this.  These
take a "bool show_color", rather than using "pp_show_color (pp)"
since cxx_pp's pp_show_color isn't currently initialized (since
cxx_initialize_diagnostics happens before diagnostic_color_init).

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.

OK for trunk?

gcc/c/ChangeLog:
	PR c++/62170
	* c-objc-common.c (c_tree_printer): Convert penultimate param from
	bool to bool *.  Within '%T' handling, if showing an "aka", use
	"quoted" param to add appropriate quoting.

gcc/cp/ChangeLog:
	PR c++/62170
	* error.c (type_to_string): Add leading comment.  Add params
	"postprocessed", "quote", and "show_color", using them to fix
	quoting of the "aka" for types involving typedefs.
	(arg_to_string): Update for new params to type_to_string.
	(cxx_format_postprocessor::handle): Likewise.
	(cp_printer): Convert penultimate param from bool to bool *.
	Update call to type_to_string and calls to
	defer_phase_2_of_type_diff.

gcc/fortran/ChangeLog:
	PR c++/62170
	* error.c (gfc_notify_std): Convert "quoted" param from bool to
	bool *.

gcc/ChangeLog:
	PR c++/62170
	* pretty-print.c (pp_format): Move quoting implementation to
	pp_begin_quote and pp_end_quote.  Update pp_format_decoder call
	to pass address of "quote" local.
	(pp_begin_quote): New function.
	(pp_end_quote): New function.
	* pretty-print.h (printer_fn): Convert penultimate param from bool
	to bool *.
	(pp_begin_quote): New decl.
	(pp_end_quote): New decl.
	* tree-diagnostic.c (default_tree_printer): Convert penultimate
	param from bool to bool *.
	* tree-diagnostic.h (default_tree_printer): Likewise.

gcc/testsuite/ChangeLog:
	PR c++/62170
	* g++.dg/cpp1z/direct-enum-init1.C: Update expected error messages
	to reflect fixes to quoting.
	* g++.dg/diagnostic/aka1.C: Likewise.
	* g++.dg/diagnostic/aka2.C: New test case.
	* g++.dg/parse/error55.C: Update expected error messages to
	reflect fixes to quoting.
	* g++.dg/warn/pr12242.C: Likewise.
	* g++.old-deja/g++.mike/enum1.C: Likewise.
	* gcc.dg/diag-aka-1.c: Likewise.
	* gcc.dg/diag-aka-2.c: New test case.
	* gcc.dg/pr13804-1.c: Update expected error messages to reflect
	fixes to quoting.
	* gcc.dg/pr56980.c: Likewise.
	* gcc.dg/pr65050.c: Likewise.
	* gcc.dg/redecl-14.c: Likewise.
	* gcc.dg/utf16-4.c Likewise.
	* gcc.target/i386/sse-vect-types.c (__m128d): Likewise.
	* obj-c++.dg/invalid-type-1.mm: Likewise.
---
 gcc/c/c-objc-common.c                          |  12 +-
 gcc/cp/error.c                                 |  92 ++++++++--
 gcc/fortran/error.c                            |   2 +-
 gcc/pretty-print.c                             |  37 +++-
 gcc/pretty-print.h                             |   5 +-
 gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C | 234 ++++++++++++-------------
 gcc/testsuite/g++.dg/diagnostic/aka1.C         |   2 +-
 gcc/testsuite/g++.dg/diagnostic/aka2.C         |  32 ++++
 gcc/testsuite/g++.dg/parse/error55.C           |   2 +-
 gcc/testsuite/g++.dg/warn/pr12242.C            |  16 +-
 gcc/testsuite/g++.old-deja/g++.mike/enum1.C    |   2 +-
 gcc/testsuite/gcc.dg/diag-aka-1.c              |   4 +-
 gcc/testsuite/gcc.dg/diag-aka-2.c              |  12 ++
 gcc/testsuite/gcc.dg/pr13804-1.c               |   4 +-
 gcc/testsuite/gcc.dg/pr56980.c                 |  12 +-
 gcc/testsuite/gcc.dg/pr65050.c                 |   8 +-
 gcc/testsuite/gcc.dg/redecl-14.c               |   2 +-
 gcc/testsuite/gcc.dg/utf16-4.c                 |   2 +-
 gcc/testsuite/gcc.target/i386/sse-vect-types.c |   2 +-
 gcc/testsuite/obj-c++.dg/invalid-type-1.mm     |   4 +-
 gcc/tree-diagnostic.c                          |   2 +-
 gcc/tree-diagnostic.h                          |   2 +-
 22 files changed, 312 insertions(+), 178 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/aka2.C
 create mode 100644 gcc/testsuite/gcc.dg/diag-aka-2.c

Comments

Marek Polacek June 6, 2017, 10:57 a.m. UTC | #1
On Mon, Jun 05, 2017 at 03:01:34PM -0400, David Malcolm wrote:
> PR 62170 describes a problem with how the quoting in pp_format
> interacts with the "aka" information for typedefs in %qT for
> the C family of frontends, and also now for %qH and %qI in the
> C++ frontend.
> 
> Currently for %qT we print e.g.:
> 
>   ‘Py_ssize_t* {aka int*}’
>    ^^^^^^^^^^^^^^^^^^^^^^ colorized as "quote"
> 
> i.e.
>   ‘[START_COLOR]Py_ssize_t* {aka int*}[END_COLOR]’
> 
> when we should print:
> 
>   ‘Py_ssize_t*’ {aka ‘int*’}
>    ^^^^^^^^^^^        ^^^^ colorized as "quote"
> 
> i.e.
>   ‘[START_COLOR]Py_ssize_t*[END_COLOR]’ {aka ‘[START_COLOR]int*[END_COLOR]’}
> 
> where the opening and closing quote characters and colorization are
> currently added by the 'q' handling within pp_format, adding the closing
> quote unconditionally after whatever pp_format_decoder prints for 'T'
> within "%qT".
> 
> This patch fixes the quoting by updating the %T handling in C and C++
> and the %H/%I handling in C++ to insert the quoting appropriately.
> It converts the "quote" param of the pp_format_decoder callback from
> bool to bool *, allowing for the %T and %H/%I handlers to write
> false back to it, to avoid printing the closing quote for the cases
> like the above where a final trailing closing quote isn't needed.
> 
> It introduces pp_begin_quote/pp_end_quote to simplify this.  These
> take a "bool show_color", rather than using "pp_show_color (pp)"
> since cxx_pp's pp_show_color isn't currently initialized (since
> cxx_initialize_diagnostics happens before diagnostic_color_init).
> 
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.

This sounds good to me.

> OK for trunk?
> 
> gcc/c/ChangeLog:
> 	PR c++/62170
> 	* c-objc-common.c (c_tree_printer): Convert penultimate param from
> 	bool to bool *.  Within '%T' handling, if showing an "aka", use
> 	"quoted" param to add appropriate quoting.

This part is obviously OK.

	Marek
David Malcolm June 20, 2017, 3:50 p.m. UTC | #2
Ping re the C++ part of this:

  https://gcc.gnu.org/ml/gcc-patches/2017-06/msg00242.html

Marek approved the C parts; are the C++ parts OK for trunk?

Or can I self-approve this?  (exactly what the boundaries of
my"diagnostic messages" maintainer remit are aren't clear to me).

Thanks
Dave

On Mon, 2017-06-05 at 15:01 -0400, David Malcolm wrote:
> PR 62170 describes a problem with how the quoting in pp_format
> interacts with the "aka" information for typedefs in %qT for
> the C family of frontends, and also now for %qH and %qI in the
> C++ frontend.
> 
> Currently for %qT we print e.g.:
> 
>   ‘Py_ssize_t* {aka int*}’
>    ^^^^^^^^^^^^^^^^^^^^^^ colorized as "quote"
> 
> i.e.
>   ‘[START_COLOR]Py_ssize_t* {aka int*}[END_COLOR]’
> 
> when we should print:
> 
>   ‘Py_ssize_t*’ {aka ‘int*’}
>    ^^^^^^^^^^^        ^^^^ colorized as "quote"
> 
> i.e.
>   ‘[START_COLOR]Py_ssize_t*[END_COLOR]’ {aka
> ‘[START_COLOR]int*[END_COLOR]’}
> 
> where the opening and closing quote characters and colorization are
> currently added by the 'q' handling within pp_format, adding the
> closing
> quote unconditionally after whatever pp_format_decoder prints for 'T'
> within "%qT".
> 
> This patch fixes the quoting by updating the %T handling in C and C++
> and the %H/%I handling in C++ to insert the quoting appropriately.
> It converts the "quote" param of the pp_format_decoder callback from
> bool to bool *, allowing for the %T and %H/%I handlers to write
> false back to it, to avoid printing the closing quote for the cases
> like the above where a final trailing closing quote isn't needed.
> 
> It introduces pp_begin_quote/pp_end_quote to simplify this.  These
> take a "bool show_color", rather than using "pp_show_color (pp)"
> since cxx_pp's pp_show_color isn't currently initialized (since
> cxx_initialize_diagnostics happens before diagnostic_color_init).
> 
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
> 
> OK for trunk?
> 
> gcc/c/ChangeLog:
> 	PR c++/62170
> 	* c-objc-common.c (c_tree_printer): Convert penultimate param
> from
> 	bool to bool *.  Within '%T' handling, if showing an "aka", use
> 	"quoted" param to add appropriate quoting.
> 
> gcc/cp/ChangeLog:
> 	PR c++/62170
> 	* error.c (type_to_string): Add leading comment.  Add params
> 	"postprocessed", "quote", and "show_color", using them to fix
> 	quoting of the "aka" for types involving typedefs.
> 	(arg_to_string): Update for new params to type_to_string.
> 	(cxx_format_postprocessor::handle): Likewise.
> 	(cp_printer): Convert penultimate param from bool to bool *.
> 	Update call to type_to_string and calls to
> 	defer_phase_2_of_type_diff.
> 
> gcc/fortran/ChangeLog:
> 	PR c++/62170
> 	* error.c (gfc_notify_std): Convert "quoted" param from bool to
> 	bool *.
> 
> gcc/ChangeLog:
> 	PR c++/62170
> 	* pretty-print.c (pp_format): Move quoting implementation to
> 	pp_begin_quote and pp_end_quote.  Update pp_format_decoder call
> 	to pass address of "quote" local.
> 	(pp_begin_quote): New function.
> 	(pp_end_quote): New function.
> 	* pretty-print.h (printer_fn): Convert penultimate param from
> bool
> 	to bool *.
> 	(pp_begin_quote): New decl.
> 	(pp_end_quote): New decl.
> 	* tree-diagnostic.c (default_tree_printer): Convert penultimate
> 	param from bool to bool *.
> 	* tree-diagnostic.h (default_tree_printer): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 	PR c++/62170
> 	* g++.dg/cpp1z/direct-enum-init1.C: Update expected error
> messages
> 	to reflect fixes to quoting.
> 	* g++.dg/diagnostic/aka1.C: Likewise.
> 	* g++.dg/diagnostic/aka2.C: New test case.
> 	* g++.dg/parse/error55.C: Update expected error messages to
> 	reflect fixes to quoting.
> 	* g++.dg/warn/pr12242.C: Likewise.
> 	* g++.old-deja/g++.mike/enum1.C: Likewise.
> 	* gcc.dg/diag-aka-1.c: Likewise.
> 	* gcc.dg/diag-aka-2.c: New test case.
> 	* gcc.dg/pr13804-1.c: Update expected error messages to reflect
> 	fixes to quoting.
> 	* gcc.dg/pr56980.c: Likewise.
> 	* gcc.dg/pr65050.c: Likewise.
> 	* gcc.dg/redecl-14.c: Likewise.
> 	* gcc.dg/utf16-4.c Likewise.
> 	* gcc.target/i386/sse-vect-types.c (__m128d): Likewise.
> 	* obj-c++.dg/invalid-type-1.mm: Likewise.
> ---
>  gcc/c/c-objc-common.c                          |  12 +-
>  gcc/cp/error.c                                 |  92 ++++++++--
>  gcc/fortran/error.c                            |   2 +-
>  gcc/pretty-print.c                             |  37 +++-
>  gcc/pretty-print.h                             |   5 +-
>  gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C | 234 ++++++++++++---
> ----------
>  gcc/testsuite/g++.dg/diagnostic/aka1.C         |   2 +-
>  gcc/testsuite/g++.dg/diagnostic/aka2.C         |  32 ++++
>  gcc/testsuite/g++.dg/parse/error55.C           |   2 +-
>  gcc/testsuite/g++.dg/warn/pr12242.C            |  16 +-
>  gcc/testsuite/g++.old-deja/g++.mike/enum1.C    |   2 +-
>  gcc/testsuite/gcc.dg/diag-aka-1.c              |   4 +-
>  gcc/testsuite/gcc.dg/diag-aka-2.c              |  12 ++
>  gcc/testsuite/gcc.dg/pr13804-1.c               |   4 +-
>  gcc/testsuite/gcc.dg/pr56980.c                 |  12 +-
>  gcc/testsuite/gcc.dg/pr65050.c                 |   8 +-
>  gcc/testsuite/gcc.dg/redecl-14.c               |   2 +-
>  gcc/testsuite/gcc.dg/utf16-4.c                 |   2 +-
>  gcc/testsuite/gcc.target/i386/sse-vect-types.c |   2 +-
>  gcc/testsuite/obj-c++.dg/invalid-type-1.mm     |   4 +-
>  gcc/tree-diagnostic.c                          |   2 +-
>  gcc/tree-diagnostic.h                          |   2 +-
>  22 files changed, 312 insertions(+), 178 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/diagnostic/aka2.C
>  create mode 100644 gcc/testsuite/gcc.dg/diag-aka-2.c
> 
> diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
> index 05212b2..b87cdda 100644
> --- a/gcc/c/c-objc-common.c
> +++ b/gcc/c/c-objc-common.c
> @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "c-objc-common.h"
>  
>  static bool c_tree_printer (pretty_printer *, text_info *, const
> char *,
> -			    int, bool, bool, bool, bool, const char
> **);
> +			    int, bool, bool, bool, bool *, const
> char **);
>  
>  bool
>  c_missing_noreturn_ok_p (tree decl)
> @@ -76,7 +76,7 @@ c_objc_common_init (void)
>  static bool
>  c_tree_printer (pretty_printer *pp, text_info *text, const char
> *spec,
>  		int precision, bool wide, bool set_locus, bool hash,
> -		bool, const char **)
> +		bool *quoted, const char **)
>  {
>    tree t = NULL_TREE;
>    tree name;
> @@ -156,12 +156,20 @@ c_tree_printer (pretty_printer *pp, text_info
> *text, const char *spec,
>  	      return true;
>  
>  	    /* They're not, print the stripped version now.  */
> +	    if (*quoted)
> +	      pp_end_quote (pp, pp_show_color (pp));
>  	    pp_c_whitespace (cpp);
>  	    pp_left_brace (cpp);
>  	    pp_c_ws_string (cpp, _("aka"));
>  	    pp_c_whitespace (cpp);
> +	    if (*quoted)
> +	      pp_begin_quote (pp, pp_show_color (pp));
>  	    cpp->type_id (TYPE_CANONICAL (t));
> +	    if (*quoted)
> +	      pp_end_quote (pp, pp_show_color (pp));
>  	    pp_right_brace (cpp);
> +	    /* No further closing quotes are needed.  */
> +	    *quoted = false;
>  	  }
>  	return true;
>        }
> diff --git a/gcc/cp/error.c b/gcc/cp/error.c
> index ed67d14..95288d1 100644
> --- a/gcc/cp/error.c
> +++ b/gcc/cp/error.c
> @@ -57,7 +57,7 @@ static const char *expr_to_string (tree);
>  static const char *fndecl_to_string (tree, int);
>  static const char *op_to_string	(enum tree_code);
>  static const char *parm_to_string (int);
> -static const char *type_to_string (tree, int);
> +static const char *type_to_string (tree, int, bool, bool *, bool);
>  
>  static void dump_alias_template_specialization (cxx_pretty_printer
> *, tree, int);
>  static void dump_type (cxx_pretty_printer *, tree, int);
> @@ -99,7 +99,7 @@ static void cp_diagnostic_starter
> (diagnostic_context *, diagnostic_info *);
>  static void cp_print_error_function (diagnostic_context *,
> diagnostic_info *);
>  
>  static bool cp_printer (pretty_printer *, text_info *, const char *,
> -			int, bool, bool, bool, bool, const char **);
> +			int, bool, bool, bool, bool *, const char
> **);
>  
>  /* Struct for handling %H or %I, which require delaying printing the
>     type until a postprocessing stage.  */
> @@ -3142,8 +3142,28 @@ op_to_string (enum tree_code p)
>    return id ? IDENTIFIER_POINTER (id) : M_("<unknown>");
>  }
>  
> +/* Return a GC-allocated representation of type TYP, with verbosity
> VERBOSE.
> +
> +   If QUOTE is non-NULL and if *QUOTE is true, then quotes are added
> to the
> +   string in appropriate places, and *QUOTE is written to with false
> +   to suppress pp_format's trailing close quote so that e.g.
> +     foo_typedef {aka underlying_foo} {enum}
> +   can be printed by "%qT" as:
> +     `foo_typedef' {aka `underlying_foo'} {enum}
> +   rather than:
> +     `foo_typedef {aka underlying_foo} {enum}'
> +   When adding such quotes, if POSTPROCESSED is true (for handling
> %H and %I)
> +   then a leading open quote will be added, whereas if POSTPROCESSED
> is false
> +   (for handling %T) then any leading quote has already been added
> by
> +   pp_format, or is not needed due to QUOTE being NULL (for template
> arguments
> +   within %H and %I).
> +
> +   SHOW_COLOR is used to determine the colorization of any quotes
> that
> +   are added.  */
> +
>  static const char *
> -type_to_string (tree typ, int verbose)
> +type_to_string (tree typ, int verbose, bool postprocessed, bool
> *quote,
> +		bool show_color)
>  {
>    int flags = 0;
>    if (verbose)
> @@ -3151,7 +3171,19 @@ type_to_string (tree typ, int verbose)
>    flags |= TFF_TEMPLATE_HEADER;
>  
>    reinit_cxx_pp ();
> +
> +  if (postprocessed && quote && *quote)
> +    pp_begin_quote (cxx_pp, show_color);
> +
> +  struct obstack *ob = pp_buffer (cxx_pp)->obstack;
> +  int type_start, type_len;
> +  type_start = obstack_object_size (ob);
> +
>    dump_type (cxx_pp, typ, flags);
> +
> +  /* Remember the end of the initial dump.  */
> +  type_len = obstack_object_size (ob) - type_start;
> +
>    /* If we're printing a type that involves typedefs, also print the
>       stripped version.  But sometimes the stripped version looks
>       exactly the same, so we don't want it after all.  To avoid
> printing
> @@ -3160,21 +3192,42 @@ type_to_string (tree typ, int verbose)
>        && !uses_template_parms (typ))
>      {
>        int aka_start, aka_len; char *p;
> -      struct obstack *ob = pp_buffer (cxx_pp)->obstack;
> -      /* Remember the end of the initial dump.  */
> -      int len = obstack_object_size (ob);
>        tree aka = strip_typedefs (typ);
> +      if (quote && *quote)
> +	pp_end_quote (cxx_pp, show_color);
>        pp_string (cxx_pp, " {aka");
>        pp_cxx_whitespace (cxx_pp);
> +      if (quote && *quote)
> +	pp_begin_quote (cxx_pp, show_color);
>        /* And remember the start of the aka dump.  */
>        aka_start = obstack_object_size (ob);
>        dump_type (cxx_pp, aka, flags);
>        aka_len = obstack_object_size (ob) - aka_start;
> +      if (quote && *quote)
> +	pp_end_quote (cxx_pp, show_color);
>        pp_right_brace (cxx_pp);
>        p = (char*)obstack_base (ob);
> -      /* If they are identical, cut off the aka with a NUL.  */
> -      if (len == aka_len && memcmp (p, p+aka_start, len) == 0)
> -	p[len] = '\0';
> +      /* If they are identical, cut off the aka by unwinding the
> obstack.  */
> +      if (type_len == aka_len
> +	  && memcmp (p + type_start, p+aka_start, type_len) == 0)
> +	{
> +	  /* We can't add a '\0' here, since we may be adding a
> closing quote
> +	     below, and it would be hidden by the '\0'.
> +	     Instead, manually unwind the current object within the
> obstack
> +	     so that the insertion point is at the end of the type,
> before
> +	     the "' {aka".  */
> +	  ob->next_free = p + type_start + type_len;
> +	}
> +      else
> +	if (quote)
> +	  /* No further closing quotes are needed.  */
> +	  *quote = false;
> +    }
> +
> +  if (quote && *quote)
> +    {
> +      pp_end_quote (cxx_pp, show_color);
> +      *quote = false;
>      }
>  
>    if (typ && TYPE_P (typ) && TREE_CODE (typ) == ENUMERAL_TYPE)
> @@ -3643,7 +3696,7 @@ static const char *
>  arg_to_string (tree arg, bool verbose)
>  {
>    if (TYPE_P (arg))
> -    return type_to_string (arg, verbose);
> +    return type_to_string (arg, verbose, true, NULL, false);
>    else
>      return expr_to_string (arg);
>  }
> @@ -3935,8 +3988,10 @@ cxx_format_postprocessor::handle
> (pretty_printer *pp)
>  	{
>  	  /* If the types were not comparable, they are printed
> normally,
>  	     and no difference tree is printed.  */
> -	  type_a_text = type_to_string (type_a.m_tree,
> type_a.m_verbose);
> -	  type_b_text = type_to_string (type_b.m_tree,
> type_b.m_verbose);
> +	  type_a_text = type_to_string (type_a.m_tree,
> type_a.m_verbose,
> +					true, &type_a.m_quote,
> show_color);
> +	  type_b_text = type_to_string (type_b.m_tree,
> type_b.m_verbose,
> +					true, &type_b.m_quote,
> show_color);
>  	}
>  
>        if (type_a.m_quote)
> @@ -4009,7 +4064,7 @@ defer_phase_2_of_type_diff
> (deferred_printed_type *deferred,
>  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, const char **buffer_ptr)
>  {
>    gcc_assert (pp->m_format_postprocessor);
>    cxx_format_postprocessor *postprocessor
> @@ -4052,7 +4107,12 @@ cp_printer (pretty_printer *pp, text_info
> *text, const char *spec,
>      case 'P': result = parm_to_string (next_int);		bre
> ak;
>      case 'Q': result = assop_to_string (next_tcode);		
> break;
>      case 'S': result = subst_to_string (next_tree);		b
> reak;
> -    case 'T': result = type_to_string (next_tree, verbose);	b
> reak;
> +    case 'T':
> +      {
> +	result = type_to_string (next_tree, verbose, false, quoted,
> +				 pp_show_color (pp));
> +      }
> +      break;
>      case 'V': result = cv_to_string (next_tree, verbose);	bre
> ak;
>      case 'X': result = eh_spec_to_string (next_tree, verbose); 
>  break;
>  
> @@ -4063,14 +4123,14 @@ cp_printer (pretty_printer *pp, text_info
> *text, const char *spec,
>      case 'H':
>        {
>  	defer_phase_2_of_type_diff (&postprocessor->m_type_a,
> next_tree,
> -				    buffer_ptr, verbose, quoted);
> +				    buffer_ptr, verbose, *quoted);
>  	return true;
>        }
>  
>      case 'I':
>        {
>  	defer_phase_2_of_type_diff (&postprocessor->m_type_b,
> next_tree,
> -				    buffer_ptr, verbose, quoted);
> +				    buffer_ptr, verbose, *quoted);
>  	return true;
>        }
>  
> diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
> index 3ad1cf9..2cece49 100644
> --- a/gcc/fortran/error.c
> +++ b/gcc/fortran/error.c
> @@ -918,7 +918,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, const char **buffer_ptr)
>  {
>    switch (*spec)
>      {
> diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c
> index 570dec7..6aee2b5 100644
> --- a/gcc/pretty-print.c
> +++ b/gcc/pretty-print.c
> @@ -545,10 +545,7 @@ pp_format (pretty_printer *pp, text_info *text)
>        gcc_assert (!wide || precision == 0);
>  
>        if (quote)
> -	{
> -	  pp_string (pp, open_quote);
> -	  pp_string (pp, colorize_start (pp_show_color (pp),
> "quote"));
> -	}
> +	pp_begin_quote (pp, pp_show_color (pp));
>  
>        switch (*p)
>  	{
> @@ -675,19 +672,21 @@ pp_format (pretty_printer *pp, text_info *text)
>  	  {
>  	    bool ok;
>  
> +	    /* Call the format decoder.
> +	       Pass the address of "quote" so that format decoders
> can
> +	       potentially disable printing of the closing quote
> +	       (e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C
> family
> +	       of frontends).  */
>  	    gcc_assert (pp_format_decoder (pp));
>  	    ok = pp_format_decoder (pp) (pp, text, p,
> -					 precision, wide, plus,
> hash, quote,
> +					 precision, wide, plus,
> hash, &quote,
>  					 formatters[argno]);
>  	    gcc_assert (ok);
>  	  }
>  	}
>  
>        if (quote)
> -	{
> -	  pp_string (pp, colorize_stop (pp_show_color (pp)));
> -	  pp_string (pp, close_quote);
> -	}
> +	pp_end_quote (pp, pp_show_color (pp));
>  
>        obstack_1grow (&buffer->chunk_obstack, '\0');
>        *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const
> char *);
> @@ -1061,6 +1060,26 @@ pp_separate_with (pretty_printer *pp, char c)
>    pp_space (pp);
>  }
>  
> +/* Add a localized open quote, and if SHOW_COLOR is true, begin
> colorizing
> +   using the "quote" color.  */
> +
> +void
> +pp_begin_quote (pretty_printer *pp, bool show_color)
> +{
> +  pp_string (pp, open_quote);
> +  pp_string (pp, colorize_start (show_color, "quote"));
> +}
> +
> +/* If SHOW_COLOR is true, stop colorizing.
> +   Add a localized close quote.  */
> +
> +void
> +pp_end_quote (pretty_printer *pp, bool show_color)
> +{
> +  pp_string (pp, colorize_stop (show_color));
> +  pp_string (pp, close_quote);
> +}
> +
>  
>  /* The string starting at P has LEN (at least 1) bytes left; if they
>     start with a valid UTF-8 sequence, return the length of that
> diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
> index 40e56a3..ff70b70 100644
> --- a/gcc/pretty-print.h
> +++ b/gcc/pretty-print.h
> @@ -180,7 +180,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 *, const
> char **);
>  
>  /* Client supplied function used to decode formats.  */
>  #define pp_format_decoder(PP) (PP)->format_decoder
> @@ -387,6 +387,9 @@ extern void pp_write_text_to_stream
> (pretty_printer *);
>  extern void pp_write_text_as_dot_label_to_stream (pretty_printer *,
> bool);
>  extern void pp_maybe_space (pretty_printer *);
>  
> +extern void pp_begin_quote (pretty_printer *, bool);
> +extern void pp_end_quote (pretty_printer *, bool);
> +
>  /* Switch into verbatim mode and return the old mode.  */
>  static inline pp_wrapping_mode_t
>  pp_set_verbatim_wrapping_ (pretty_printer *pp)
> diff --git a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
> b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
> index 11269cc..39b6052 100644
> --- a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
> +++ b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
> @@ -17,121 +17,121 @@ void bar (E);
>  void
>  foo ()
>  {
> -  A a1 { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A {enum}'" }
> -  B b1 { 7 };		// { dg-error "invalid conversion from
> 'int' to 'B {enum}'" "" { target c++14_down } }
> +  A a1 { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A' {enum}" }
> +  B b1 { 7 };		// { dg-error "invalid conversion from
> 'int' to 'B' {enum}" "" { target c++14_down } }
>    C c1 { s };
> -  D d1 { D(t) };	// { dg-error "invalid cast from type 'T' to
> type 'D {enum}'" }
> -  D d2 { t };		// { dg-error "cannot convert 'T' to 'D
> {enum}' in initialization" "" { target c++14_down } }
> -			// { dg-error "invalid cast from type 'T' to
> type 'D {enum}'" "" { target c++1z } .-1 }
> -  D d3 { 9 };		// { dg-error "cannot convert 'int' to
> 'D {enum}' in initialization" "" { target c++14_down } }
> -  D d4 { l };		// { dg-error "cannot convert 'long
> int' to 'D {enum}' in initialization" "" { target c++14_down } }
> +  D d1 { D(t) };	// { dg-error "invalid cast from type 'T' to
> type 'D' {enum}" }
> +  D d2 { t };		// { dg-error "cannot convert 'T' to
> 'D' {enum} in initialization" "" { target c++14_down } }
> +			// { dg-error "invalid cast from type 'T' to
> type 'D' {enum}" "" { target c++1z } .-1 }
> +  D d3 { 9 };		// { dg-error "cannot convert 'int' to
> 'D' {enum} in initialization" "" { target c++14_down } }
> +  D d4 { l };		// { dg-error "cannot convert 'long
> int' to 'D' {enum} in initialization" "" { target c++14_down } }
>    D d5 { D(l) };
> -  D d6 { G };		// { dg-error "cannot convert 'A
> {enum}' to 'D {enum}' in initialization" "" { target c++14_down } }
> -  E e1 { 5 };		// { dg-error "cannot convert 'int' to
> 'E {enum}' in initialization" "" { target c++14_down } }
> -  E e2 { -1 };		// { dg-error "cannot convert 'int' to
> 'E {enum}' in initialization" "" { target c++14_down } }
> +  D d6 { G };		// { dg-error "cannot convert 'A'
> {enum} to 'D' {enum} in initialization" "" { target c++14_down } }
> +  E e1 { 5 };		// { dg-error "cannot convert 'int' to
> 'E' {enum} in initialization" "" { target c++14_down } }
> +  E e2 { -1 };		// { dg-error "cannot convert 'int' to
> 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of '-1'
> from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
> -  E e3 { 5.0 };		// { dg-error "cannot convert
> 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
> +  E e3 { 5.0 };		// { dg-error "cannot convert
> 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z }
> .-1 }
> -  E e4 { 5.2 };		// { dg-error "cannot convert
> 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
> +  E e4 { 5.2 };		// { dg-error "cannot convert
> 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target
> c++1z } .-1 }
> -  B b2 = { 7 };		// { dg-error "invalid conversion
> from 'int' to 'B {enum}'" }
> -  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to
> 'C {enum}' in initialization" "" { target c++14_down } }
> +  B b2 = { 7 };		// { dg-error "invalid conversion
> from 'int' to 'B' {enum}" }
> +  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to
> 'C' {enum} in initialization" "" { target c++14_down } }
>  
> -  D *d7 = new D { 9 };	// { dg-error "cannot convert
> \[^\n\r]* to 'D {enum}' in initialization" "" { target c++14_down } }
> -  E *e5 = new E { -4 };	// { dg-error "cannot convert
> \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
> +  D *d7 = new D { 9 };	// { dg-error "cannot convert
> \[^\n\r]* to 'D' {enum} in initialization" "" { target c++14_down } }
> +  E *e5 = new E { -4 };	// { dg-error "cannot convert
> \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of '-4'
> from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
> -  bar ({ 10 });		// { dg-error "cannot convert
> \[^\n\r]* to 'E {enum}' for argument" }
> -  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E
> {enum}' in initialization" "" { target c++14_down } }
> -  V v1 = { { 11 } };	// { dg-error "braces around scalar
> initializer for type 'E {enum}'" }
> -  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to
> 'E {enum}' in initialization" "" { target c++14_down } }
> -  V v3 = { E { 5.0 } };	// { dg-error "cannot convert
> 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
> +  bar ({ 10 });		// { dg-error "cannot convert
> \[^\n\r]* to 'E' {enum} for argument" }
> +  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E'
> {enum} in initialization" "" { target c++14_down } }
> +  V v1 = { { 11 } };	// { dg-error "braces around scalar
> initializer for type 'E' {enum}" }
> +  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to
> 'E' {enum} in initialization" "" { target c++14_down } }
> +  V v3 = { E { 5.0 } };	// { dg-error "cannot convert
> 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z }
> .-1 }
> -  V v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E
> {enum}' in initialization" }
> -  if (B b3 { 5 })	// { dg-error "invalid conversion from
> 'int' to 'B {enum}'" "" { target c++14_down } }
> +  V v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E'
> {enum} in initialization" }
> +  if (B b3 { 5 })	// { dg-error "invalid conversion from
> 'int' to 'B' {enum}" "" { target c++14_down } }
>      ;
> -  if (B b4 { 4.0 })	// { dg-error "cannot convert 'double' to
> 'B {enum}' in initialization" "" { target c++14_down } }
> +  if (B b4 { 4.0 })	// { dg-error "cannot convert 'double' to
> 'B' {enum} in initialization" "" { target c++14_down } }
>      ;			// { dg-error "narrowing conversion of
> '4.0e.0' from 'double' to 'short int' inside" "" { target c++1z } .-1
> }
> -  C c3 { 8L };		// { dg-error "cannot convert 'long
> int' to 'C {enum}' in initialization" "" { target c++14_down } }
> -  B b4 {short (c + 5)};	// { dg-error "invalid conversion
> from 'short int' to 'B {enum}'" "" { target c++14_down } }
> -  B b5 {c + 5};		// { dg-error "invalid conversion
> from 'int' to 'B {enum}'" "" { target c++14_down } }
> +  C c3 { 8L };		// { dg-error "cannot convert 'long
> int' to 'C' {enum} in initialization" "" { target c++14_down } }
> +  B b4 {short (c + 5)};	// { dg-error "invalid conversion
> from 'short int' to 'B' {enum}" "" { target c++14_down } }
> +  B b5 {c + 5};		// { dg-error "invalid conversion
> from 'int' to 'B' {enum}" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> \[^\n\r]* from 'int' to 'short int' inside" "" { target c++1z } .-1 }
> -  C c4 { ll };		// { dg-error "cannot convert 'long
> long int' to 'C {enum}' in initialization" "" { target c++14_down } }
> +  C c4 { ll };		// { dg-error "cannot convert 'long
> long int' to 'C' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of 'll'
> from 'long long int' to 'int' inside" "" { target c++1z } .-1 }
> -  C c5 {short (c + 5)};	// { dg-error "cannot convert 'short
> int' to 'C {enum}' in initialization" "" { target c++14_down } }
> -  C c6 {c + 5};		// { dg-error "cannot convert 'int'
> to 'C {enum}' in initialization" "" { target c++14_down } }
> +  C c5 {short (c + 5)};	// { dg-error "cannot convert 'short
> int' to 'C' {enum} in initialization" "" { target c++14_down } }
> +  C c6 {c + 5};		// { dg-error "cannot convert 'int'
> to 'C' {enum} in initialization" "" { target c++14_down } }
>  }
>  
>  struct U
>  {
> -  U () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]*
> to 'E {enum}' in initialization" "" { target c++14_down } }
> -  U (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to
> 'E {enum}' in initialization" "" { target c++14_down } }
> +  U () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]*
> to 'E' {enum} in initialization" "" { target c++14_down } }
> +  U (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to
> 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z }
> .-1 }
>    U (float) : e({ 6 }) {}// { dg-error "list-initializer for non
> -class type must not be parenthesized" }
> -			// { dg-error "cannot convert \[^\n\r]* to
> 'E {enum}' in initialization" "" { target *-*-* } .-1 }
> +			// { dg-error "cannot convert \[^\n\r]* to
> 'E' {enum} in initialization" "" { target *-*-* } .-1 }
>    E e;
>  };
>  
>  struct W
>  {
> -  A a { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A {enum}'" }
> -  B b { 6 };		// { dg-error "invalid conversion from
> 'int' to 'B {enum}'" "" { target c++14_down } }
> -  C c { 3.0f };		// { dg-error "cannot convert
> \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } }
> +  A a { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A' {enum}" }
> +  B b { 6 };		// { dg-error "invalid conversion from
> 'int' to 'B' {enum}" "" { target c++14_down } }
> +  C c { 3.0f };		// { dg-error "cannot convert
> \[^\n\r]* to 'C' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-1 }
> -  D d = { 7 };		// { dg-error "cannot convert
> \[^\n\r]* to 'D {enum}' in initialization" }
> +  D d = { 7 };		// { dg-error "cannot convert
> \[^\n\r]* to 'D' {enum} in initialization" }
>  };
>  
>  template <int N>
>  void
>  foo2 ()
>  {
> -  A a1 { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A {enum}'" }
> -  B b1 { 7 };		// { dg-error "invalid conversion from
> 'int' to 'B {enum}'" "" { target c++14_down } }
> +  A a1 { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A' {enum}" }
> +  B b1 { 7 };		// { dg-error "invalid conversion from
> 'int' to 'B' {enum}" "" { target c++14_down } }
>    C c1 { s };
> -  D d1 { D(t) };	// { dg-error "invalid cast from type 'T' to
> type 'D {enum}'" }
> -  D d2 { t };		// { dg-error "cannot convert 'T' to 'D
> {enum}' in initialization" "" { target c++14_down } }
> -			// { dg-error "invalid cast from type 'T' to
> type 'D {enum}'" "" { target c++1z } .-1 }
> -  D d3 { 9 };		// { dg-error "cannot convert 'int' to
> 'D {enum}' in initialization" "" { target c++14_down } }
> -  D d4 { l };		// { dg-error "cannot convert 'long
> int' to 'D {enum}' in initialization" "" { target c++14_down } }
> +  D d1 { D(t) };	// { dg-error "invalid cast from type 'T' to
> type 'D' {enum}" }
> +  D d2 { t };		// { dg-error "cannot convert 'T' to
> 'D' {enum} in initialization" "" { target c++14_down } }
> +			// { dg-error "invalid cast from type 'T' to
> type 'D' {enum}" "" { target c++1z } .-1 }
> +  D d3 { 9 };		// { dg-error "cannot convert 'int' to
> 'D' {enum} in initialization" "" { target c++14_down } }
> +  D d4 { l };		// { dg-error "cannot convert 'long
> int' to 'D' {enum} in initialization" "" { target c++14_down } }
>    D d5 { D(l) };
> -  D d6 { G };		// { dg-error "cannot convert 'A
> {enum}' to 'D {enum}' in initialization" "" { target c++14_down } }
> -  E e1 { 5 };		// { dg-error "cannot convert 'int' to
> 'E {enum}' in initialization" "" { target c++14_down } }
> -  E e2 { -1 };		// { dg-error "cannot convert 'int' to
> 'E {enum}' in initialization" "" { target c++14_down } }
> +  D d6 { G };		// { dg-error "cannot convert 'A'
> {enum} to 'D' {enum} in initialization" "" { target c++14_down } }
> +  E e1 { 5 };		// { dg-error "cannot convert 'int' to
> 'E' {enum} in initialization" "" { target c++14_down } }
> +  E e2 { -1 };		// { dg-error "cannot convert 'int' to
> 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of '-1'
> from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
> -  E e3 { 5.0 };		// { dg-error "cannot convert
> 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
> +  E e3 { 5.0 };		// { dg-error "cannot convert
> 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z }
> .-1 }
> -  E e4 { 5.2 };		// { dg-error "cannot convert
> 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
> +  E e4 { 5.2 };		// { dg-error "cannot convert
> 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target
> c++1z } .-1 }
> -  B b2 = { 7 };		// { dg-error "invalid conversion
> from 'int' to 'B {enum}'" }
> -  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to
> 'C {enum}' in initialization" "" { target c++14_down } }
> -  D *d7 = new D { 9 };	// { dg-error "cannot convert
> \[^\n\r]* to 'D {enum}' in initialization" "" { target c++14_down } }
> -  E *e5 = new E { -4 };	// { dg-error "cannot convert
> \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
> +  B b2 = { 7 };		// { dg-error "invalid conversion
> from 'int' to 'B' {enum}" }
> +  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to
> 'C' {enum} in initialization" "" { target c++14_down } }
> +  D *d7 = new D { 9 };	// { dg-error "cannot convert
> \[^\n\r]* to 'D' {enum} in initialization" "" { target c++14_down } }
> +  E *e5 = new E { -4 };	// { dg-error "cannot convert
> \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of '-4'
> from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
> -  bar ({ 10 });		// { dg-error "cannot convert
> \[^\n\r]* to 'E {enum}' for argument" }
> -  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E
> {enum}' in initialization" "" { target c++14_down } }
> -  V v1 = { { 11 } };	// { dg-error "braces around scalar
> initializer for type 'E {enum}'" }
> -  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to
> 'E {enum}' in initialization" "" { target c++14_down } }
> -  V v3 = { E { 5.0 } };	// { dg-error "cannot convert
> 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
> +  bar ({ 10 });		// { dg-error "cannot convert
> \[^\n\r]* to 'E' {enum} for argument" }
> +  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E'
> {enum} in initialization" "" { target c++14_down } }
> +  V v1 = { { 11 } };	// { dg-error "braces around scalar
> initializer for type 'E' {enum}" }
> +  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to
> 'E' {enum} in initialization" "" { target c++14_down } }
> +  V v3 = { E { 5.0 } };	// { dg-error "cannot convert
> 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z }
> .-1 }
> -  V v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E
> {enum}' in initialization" }
> -  if (B b3 { 5 })	// { dg-error "invalid conversion from
> 'int' to 'B {enum}'" "" { target c++14_down } }
> +  V v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E'
> {enum} in initialization" }
> +  if (B b3 { 5 })	// { dg-error "invalid conversion from
> 'int' to 'B' {enum}" "" { target c++14_down } }
>      ;
> -  if (B b4 { 4.0 })	// { dg-error "cannot convert 'double' to
> 'B {enum}' in initialization" "" { target c++14_down } }
> +  if (B b4 { 4.0 })	// { dg-error "cannot convert 'double' to
> 'B' {enum} in initialization" "" { target c++14_down } }
>      ;			// { dg-error "narrowing conversion of
> '4.0e.0' from 'double' to 'short int' inside" "" { target c++1z } .-1
> }
> -  C c3 { 8L };		// { dg-error "cannot convert 'long
> int' to 'C {enum}' in initialization" "" { target c++14_down } }
> -  B b4 {short (c + 5)};	// { dg-error "invalid conversion
> from 'short int' to 'B {enum}'" "" { target c++14_down } }
> -  B b5 {c + 5};		// { dg-error "invalid conversion
> from 'int' to 'B {enum}'" "" { target c++14_down } }
> +  C c3 { 8L };		// { dg-error "cannot convert 'long
> int' to 'C' {enum} in initialization" "" { target c++14_down } }
> +  B b4 {short (c + 5)};	// { dg-error "invalid conversion
> from 'short int' to 'B' {enum}" "" { target c++14_down } }
> +  B b5 {c + 5};		// { dg-error "invalid conversion
> from 'int' to 'B' {enum}" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> \[^\n\r]* from 'int' to 'short int' inside" "" { target c++1z } .-1 }
> -  C c4 { ll };		// { dg-error "cannot convert 'long
> long int' to 'C {enum}' in initialization" "" { target c++14_down } }
> +  C c4 { ll };		// { dg-error "cannot convert 'long
> long int' to 'C' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of 'll'
> from 'long long int' to 'int' inside" "" { target c++1z } .-1 }
> -  C c5 {short (c + 5)};	// { dg-error "cannot convert 'short
> int' to 'C {enum}' in initialization" "" { target c++14_down } }
> -  C c6 {c + 5};		// { dg-error "cannot convert 'int'
> to 'C {enum}' in initialization" "" { target c++14_down } }
> +  C c5 {short (c + 5)};	// { dg-error "cannot convert 'short
> int' to 'C' {enum} in initialization" "" { target c++14_down } }
> +  C c6 {c + 5};		// { dg-error "cannot convert 'int'
> to 'C' {enum} in initialization" "" { target c++14_down } }
>  }
>  
>  template <int N>
>  struct U2
>  {
> -  U2 () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]*
> to 'E {enum}' in initialization" "" { target c++14_down } }
> -  U2 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to
> 'E {enum}' in initialization" "" { target c++14_down } }
> +  U2 () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]*
> to 'E' {enum} in initialization" "" { target c++14_down } }
> +  U2 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to
> 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z }
> .-1 }
>    U2 (float) : e({ 6 }) {}
>    E e;
> @@ -140,11 +140,11 @@ struct U2
>  template <int N>
>  struct W2
>  {
> -  A a { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A {enum}'" "" { target *-*-* } .-2 }
> -  B b { 6 };		// { dg-error "invalid conversion from
> 'int' to 'B {enum}'" "" { target c++14_down } .-3 }
> -  C c { 3.0f };		// { dg-error "cannot convert
> \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .
> -4 }
> +  A a { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A' {enum}" "" { target *-*-* } .-2 }
> +  B b { 6 };		// { dg-error "invalid conversion from
> 'int' to 'B' {enum}" "" { target c++14_down } .-3 }
> +  C c { 3.0f };		// { dg-error "cannot convert
> \[^\n\r]* to 'C' {enum} in initialization" "" { target c++14_down } .
> -4 }
>  			// { dg-error "narrowing conversion of
> '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-5 }
> -  D d = { 7 };		// { dg-error "cannot convert
> \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-6 }
> +  D d = { 7 };		// { dg-error "cannot convert
> \[^\n\r]* to 'D' {enum} in initialization" "" { target *-*-* } .-6 }
>  };
>  
>  template <typename H, typename I, typename J, typename K, typename
> L, typename M>
> @@ -152,54 +152,54 @@ void
>  foo3 ()
>  {
>    void bar3 (L);
> -  H a1 { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A {enum}'" }
> -  I b1 { 7 };		// { dg-error "invalid conversion from
> 'int' to 'B {enum}'" "" { target c++14_down } }
> +  H a1 { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A' {enum}" }
> +  I b1 { 7 };		// { dg-error "invalid conversion from
> 'int' to 'B' {enum}" "" { target c++14_down } }
>    J c1 { s };
> -  K d1 { K(t) };	// { dg-error "invalid cast from type 'T' to
> type 'D {enum}'" }
> -  K d2 { t };		// { dg-error "cannot convert 'T' to 'D
> {enum}' in initialization" "" { target c++14_down } }
> -			// { dg-error "invalid cast from type 'T' to
> type 'D {enum}'" "" { target c++1z } .-1 }
> -  K d3 { 9 };		// { dg-error "cannot convert 'int' to
> 'D {enum}' in initialization" "" { target c++14_down } }
> -  K d4 { l };		// { dg-error "cannot convert 'long
> int' to 'D {enum}' in initialization" "" { target c++14_down } }
> +  K d1 { K(t) };	// { dg-error "invalid cast from type 'T' to
> type 'D' {enum}" }
> +  K d2 { t };		// { dg-error "cannot convert 'T' to
> 'D' {enum} in initialization" "" { target c++14_down } }
> +			// { dg-error "invalid cast from type 'T' to
> type 'D' {enum}" "" { target c++1z } .-1 }
> +  K d3 { 9 };		// { dg-error "cannot convert 'int' to
> 'D' {enum} in initialization" "" { target c++14_down } }
> +  K d4 { l };		// { dg-error "cannot convert 'long
> int' to 'D' {enum} in initialization" "" { target c++14_down } }
>    K d5 { K(l) };
> -  K d6 { G };		// { dg-error "cannot convert 'A
> {enum}' to 'D {enum}' in initialization" "" { target c++14_down } }
> -  L e1 { 5 };		// { dg-error "cannot convert 'int' to
> 'E {enum}' in initialization" "" { target c++14_down } }
> -  L e2 { -1 };		// { dg-error "cannot convert 'int' to
> 'E {enum}' in initialization" "" { target c++14_down } }
> +  K d6 { G };		// { dg-error "cannot convert 'A'
> {enum} to 'D' {enum} in initialization" "" { target c++14_down } }
> +  L e1 { 5 };		// { dg-error "cannot convert 'int' to
> 'E' {enum} in initialization" "" { target c++14_down } }
> +  L e2 { -1 };		// { dg-error "cannot convert 'int' to
> 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of '-1'
> from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
> -  L e3 { 5.0 };		// { dg-error "cannot convert
> 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
> +  L e3 { 5.0 };		// { dg-error "cannot convert
> 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z }
> .-1 }
> -  L e4 { 5.2 };		// { dg-error "cannot convert
> 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
> +  L e4 { 5.2 };		// { dg-error "cannot convert
> 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target
> c++1z } .-1 }
> -  I b2 = { 7 };		// { dg-error "invalid conversion
> from 'int' to 'B {enum}'" }
> -  J c2 = { J { 8 } };	// { dg-error "cannot convert 'int' to
> 'C {enum}' in initialization" "" { target c++14_down } }
> -  K *d7 = new K { 9 };	// { dg-error "cannot convert
> \[^\n\r]* to 'D {enum}' in initialization" "" { target c++14_down } }
> -  L *e5 = new L { -4 };	// { dg-error "cannot convert
> \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
> +  I b2 = { 7 };		// { dg-error "invalid conversion
> from 'int' to 'B' {enum}" }
> +  J c2 = { J { 8 } };	// { dg-error "cannot convert 'int' to
> 'C' {enum} in initialization" "" { target c++14_down } }
> +  K *d7 = new K { 9 };	// { dg-error "cannot convert
> \[^\n\r]* to 'D' {enum} in initialization" "" { target c++14_down } }
> +  L *e5 = new L { -4 };	// { dg-error "cannot convert
> \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of '-4'
> from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
> -  bar3 ({ 10 });	// { dg-error "cannot convert \[^\n\r]* to
> 'E {enum}' for argument" }
> -  bar3 (E { 9 });	// { dg-error "cannot convert 'int' to 'E
> {enum}' in initialization" "" { target c++14_down } }
> -  M v1 = { { 11 } };	// { dg-error "braces around scalar
> initializer for type 'E {enum}'" }
> -  M v2 = { L { 12 } };	// { dg-error "cannot convert 'int' to
> 'E {enum}' in initialization" "" { target c++14_down } }
> -  M v3 = { L { 5.0 } };	// { dg-error "cannot convert
> 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
> +  bar3 ({ 10 });	// { dg-error "cannot convert \[^\n\r]* to
> 'E' {enum} for argument" }
> +  bar3 (E { 9 });	// { dg-error "cannot convert 'int' to 'E'
> {enum} in initialization" "" { target c++14_down } }
> +  M v1 = { { 11 } };	// { dg-error "braces around scalar
> initializer for type 'E' {enum}" }
> +  M v2 = { L { 12 } };	// { dg-error "cannot convert 'int' to
> 'E' {enum} in initialization" "" { target c++14_down } }
> +  M v3 = { L { 5.0 } };	// { dg-error "cannot convert
> 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z }
> .-1 }
> -  M v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E
> {enum}' in initialization" }
> -  if (I b3 { 5 })	// { dg-error "invalid conversion from
> 'int' to 'B {enum}'" "" { target c++14_down } }
> +  M v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E'
> {enum} in initialization" }
> +  if (I b3 { 5 })	// { dg-error "invalid conversion from
> 'int' to 'B' {enum}" "" { target c++14_down } }
>      ;
> -  if (I b4 { 4.0 })	// { dg-error "cannot convert 'double' to
> 'B {enum}' in initialization" "" { target c++14_down } }
> +  if (I b4 { 4.0 })	// { dg-error "cannot convert 'double' to
> 'B' {enum} in initialization" "" { target c++14_down } }
>      ;			// { dg-error "narrowing conversion of
> '4.0e.0' from 'double' to 'short int' inside" "" { target c++1z } .-1
> }
> -  J c3 { 8L };		// { dg-error "cannot convert 'long
> int' to 'C {enum}' in initialization" "" { target c++14_down } }
> -  I b4 {short (c + 5)};	// { dg-error "invalid conversion
> from 'short int' to 'B {enum}'" "" { target c++14_down } }
> -  I b5 {c + 5};		// { dg-error "invalid conversion
> from 'int' to 'B {enum}'" "" { target c++14_down } }
> +  J c3 { 8L };		// { dg-error "cannot convert 'long
> int' to 'C' {enum} in initialization" "" { target c++14_down } }
> +  I b4 {short (c + 5)};	// { dg-error "invalid conversion
> from 'short int' to 'B' {enum}" "" { target c++14_down } }
> +  I b5 {c + 5};		// { dg-error "invalid conversion
> from 'int' to 'B' {enum}" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> \[^\n\r]* from 'int' to 'short int' inside" "" { target c++1z } .-1 }
> -  J c4 { ll };		// { dg-error "cannot convert 'long
> long int' to 'C {enum}' in initialization" "" { target c++14_down } }
> +  J c4 { ll };		// { dg-error "cannot convert 'long
> long int' to 'C' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of 'll'
> from 'long long int' to 'int' inside" "" { target c++1z } .-1 }
> -  J c5 {short (c + 5)};	// { dg-error "cannot convert 'short
> int' to 'C {enum}' in initialization" "" { target c++14_down } }
> -  J c6 {c + 5};		// { dg-error "cannot convert 'int'
> to 'C {enum}' in initialization" "" { target c++14_down } }
> +  J c5 {short (c + 5)};	// { dg-error "cannot convert 'short
> int' to 'C' {enum} in initialization" "" { target c++14_down } }
> +  J c6 {c + 5};		// { dg-error "cannot convert 'int'
> to 'C' {enum} in initialization" "" { target c++14_down } }
>  }
>  
>  template <typename L>
>  struct U3
>  {
> -  U3 () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]*
> to 'E {enum}' in initialization" "" { target c++14_down } }
> -  U3 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to
> 'E {enum}' in initialization" "" { target c++14_down } }
> +  U3 () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]*
> to 'E' {enum} in initialization" "" { target c++14_down } }
> +  U3 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to
> 'E' {enum} in initialization" "" { target c++14_down } }
>  			// { dg-error "narrowing conversion of
> '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z }
> .-1 }
>    U3 (float) : e({ 6 }) {}
>    L e;
> @@ -208,11 +208,11 @@ struct U3
>  template <typename H, typename I, typename J, typename K>
>  struct W3
>  {
> -  H a { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A {enum}'" "" { target *-*-* } .-2 }
> -  I b { 6 };		// { dg-error "invalid conversion from
> 'int' to 'B {enum}'" "" { target c++14_down } .-3 }
> -  J c { 3.0f };		// { dg-error "cannot convert
> \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .
> -4 }
> +  H a { 5 };		// { dg-error "invalid conversion from
> 'int' to 'A' {enum}" "" { target *-*-* } .-2 }
> +  I b { 6 };		// { dg-error "invalid conversion from
> 'int' to 'B' {enum}" "" { target c++14_down } .-3 }
> +  J c { 3.0f };		// { dg-error "cannot convert
> \[^\n\r]* to 'C' {enum} in initialization" "" { target c++14_down } .
> -4 }
>  			// { dg-error "narrowing conversion of
> '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-5 }
> -  K d = { 7 };		// { dg-error "cannot convert
> \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-6 }
> +  K d = { 7 };		// { dg-error "cannot convert
> \[^\n\r]* to 'D' {enum} in initialization" "" { target *-*-* } .-6 }
>  };
>  
>  void
> @@ -221,17 +221,17 @@ test ()
>    foo2<0> ();
>    U2<0> u20;
>    U2<1> u21 (5);
> -  W2<0> w2;		// { dg-error "invalid conversion from
> 'int' to 'A {enum}'" }
> -			// { dg-error "invalid conversion from 'int'
> to 'B {enum}'" "" { target c++14_down } .-1 }
> -			// { dg-error "cannot convert \[^\n\r]* to
> 'C {enum}' in initialization" "" { target c++14_down } .-2 }
> +  W2<0> w2;		// { dg-error "invalid conversion from
> 'int' to 'A' {enum}" }
> +			// { dg-error "invalid conversion from 'int'
> to 'B' {enum}" "" { target c++14_down } .-1 }
> +			// { dg-error "cannot convert \[^\n\r]* to
> 'C' {enum} in initialization" "" { target c++14_down } .-2 }
>  			// { dg-error "narrowing conversion of
> '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-3 }
> -			// { dg-error "cannot convert \[^\n\r]* to
> 'D {enum}' in initialization" "" { target *-*-* } .-4 }
> +			// { dg-error "cannot convert \[^\n\r]* to
> 'D' {enum} in initialization" "" { target *-*-* } .-4 }
>    foo3<A, B, C, D, E, V> ();
>    U3<E> u30;
>    U3<E> u31 (5);
> -  W3<A, B, C, D> w3;	// { dg-error "invalid conversion from
> 'int' to 'A {enum}'" }
> -			// { dg-error "invalid conversion from 'int'
> to 'B {enum}'" "" { target c++14_down } .-1 }
> -			// { dg-error "cannot convert \[^\n\r]* to
> 'C {enum}' in initialization" "" { target c++14_down } .-2 }
> +  W3<A, B, C, D> w3;	// { dg-error "invalid conversion from
> 'int' to 'A' {enum}" }
> +			// { dg-error "invalid conversion from 'int'
> to 'B' {enum}" "" { target c++14_down } .-1 }
> +			// { dg-error "cannot convert \[^\n\r]* to
> 'C' {enum} in initialization" "" { target c++14_down } .-2 }
>  			// { dg-error "narrowing conversion of
> '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-3 }
> -			// { dg-error "cannot convert \[^\n\r]* to
> 'D {enum}' in initialization" "" { target *-*-* } .-4 }
> +			// { dg-error "cannot convert \[^\n\r]* to
> 'D' {enum} in initialization" "" { target *-*-* } .-4 }
>  }
> diff --git a/gcc/testsuite/g++.dg/diagnostic/aka1.C
> b/gcc/testsuite/g++.dg/diagnostic/aka1.C
> index 37f8df9..cb314fb 100644
> --- a/gcc/testsuite/g++.dg/diagnostic/aka1.C
> +++ b/gcc/testsuite/g++.dg/diagnostic/aka1.C
> @@ -12,4 +12,4 @@ void A::f() {
>  typedef A B;
>  
>  // We do want an aka for a real typedef.
> -B b = 0;			// { dg-error "B .aka A." }
> +B b = 0;			// { dg-error "'B' {aka 'A'}" }
> diff --git a/gcc/testsuite/g++.dg/diagnostic/aka2.C
> b/gcc/testsuite/g++.dg/diagnostic/aka2.C
> new file mode 100644
> index 0000000..a43f9e3
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/diagnostic/aka2.C
> @@ -0,0 +1,32 @@
> +/* Verify that the "aka" descriptions for typedefs are correctly
> +   quoted (PR 62170).  */
> +
> +/* Exercise %H and %I.  */
> +
> +typedef struct s1 t1;
> +typedef struct s2 {int i;} t2;
> +
> +int foo(t1 *);
> +
> +void test_1 () {
> +  t2 pos;
> +
> +  foo (&pos); // { dg-error "cannot convert 't2\\*' {aka 's2\\*'} to
> 't1\\*' {aka 's1\\*'} for argument '1' to 'int foo\\(t1\\*\\)'" }
> +}
> +
> +/* Exercise %T.  */
> +
> +typedef struct s3
> +{  
> +  void m3 ();
> +} t3;
> +
> +void test_2 (const s3 *ptr)
> +{
> +  ptr->m3 (); // { dg-error "passing 'const s3' as 'this' argument
> discards qualifiers" }
> +}
> +
> +void test_3 (const t3 *ptr)
> +{
> +  ptr->m3 (); // { dg-error "passing 'const t3' {aka 'const s3'} as
> 'this' argument discards qualifiers" }
> +}
> diff --git a/gcc/testsuite/g++.dg/parse/error55.C
> b/gcc/testsuite/g++.dg/parse/error55.C
> index 24cca50..70af85d 100644
> --- a/gcc/testsuite/g++.dg/parse/error55.C
> +++ b/gcc/testsuite/g++.dg/parse/error55.C
> @@ -3,5 +3,5 @@
>  class A { };
>  typedef A B;
>  void foo (B &a) {
> -  a.x();  // { dg-error "'B {aka class A}' has no member named 'x'"
> }
> +  a.x();  // { dg-error "'B' {aka 'class A'} has no member named
> 'x'" }
>  }
> diff --git a/gcc/testsuite/g++.dg/warn/pr12242.C
> b/gcc/testsuite/g++.dg/warn/pr12242.C
> index e1cd780..2cb344b 100644
> --- a/gcc/testsuite/g++.dg/warn/pr12242.C
> +++ b/gcc/testsuite/g++.dg/warn/pr12242.C
> @@ -10,14 +10,14 @@ void example ()
>    X x;
>    Y y;
>    
> -  x = 10;  // { dg-warning "invalid conversion from .int. to .X
> {enum}." "invalid" }
> -           // { dg-warning "unspecified" "unspecified" { target *-*
> -* } .-1 }
> -  x = 1;   // { dg-warning "invalid conversion from .int. to .X
> {enum}." }
> -  x = C;   // { dg-error "cannot convert .Y {enum}. to .X {enum}. in
> assignment" }  
> -  x = D;   // { dg-error "cannot convert .Y {enum}. to .X {enum}. in
> assignment" }  
> -  y = A;   // { dg-error "cannot convert .X {enum}. to .Y {enum}. in
> assignment" }  
> -  x = y;   // { dg-error "cannot convert .Y {enum}. to .X {enum}. in
> assignment" }  
> -  x = i;   // { dg-warning "invalid conversion from .int. to .X
> {enum}."  }
> +  x = 10;  // { dg-warning "invalid conversion from 'int' to 'X'
> {enum}" "invalid" }
> +           // { dg-warning "unspecified" "unspecified" { target *-*
> -* } '-1 }
> +  x = 1;   // { dg-warning "invalid conversion from 'int' to 'X'
> {enum}" }
> +  x = C;   // { dg-error "cannot convert 'Y' {enum} to 'X' {enum} in
> assignment" }  
> +  x = D;   // { dg-error "cannot convert 'Y' {enum} to 'X' {enum} in
> assignment" }  
> +  y = A;   // { dg-error "cannot convert 'X' {enum} to 'Y' {enum} in
> assignment" }  
> +  x = y;   // { dg-error "cannot convert 'Y' {enum} to 'X' {enum} in
> assignment" }  
> +  x = i;   // { dg-warning "invalid conversion from 'int' to 'X'
> {enum}"  }
>  }
>  
>  void foo () 
> diff --git a/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
> b/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
> index 2f7a6dd..82abb602e 100644
> --- a/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
> +++ b/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
> @@ -8,4 +8,4 @@ struct Type {
>    void setBTK();
>  };
>  
> -void Type::setBTK() { kind = DTK; } // { dg-warning "conversion from
> '\[^\n\r]+' to .unsigned char:1. changes value from" }
> +void Type::setBTK() { kind = DTK; } // { dg-warning "conversion from
> '\[^\n\r]+' {enum} to .unsigned char:1. changes value from" }
> diff --git a/gcc/testsuite/gcc.dg/diag-aka-1.c
> b/gcc/testsuite/gcc.dg/diag-aka-1.c
> index 87bc757..fde4ca7 100644
> --- a/gcc/testsuite/gcc.dg/diag-aka-1.c
> +++ b/gcc/testsuite/gcc.dg/diag-aka-1.c
> @@ -10,7 +10,7 @@ typedef int IA[];
>  typedef IA *IAP;
>  extern IAP arr[];
>  
> -void fn1 (B *); /* { dg-message "expected .B \\* {aka struct A \\*}.
> but argument is of type .struct B \\*." } */
> +void fn1 (B *); /* { dg-message "expected 'B \\*' {aka 'struct A
> \\*'} but argument is of type 'struct B \\*'" } */
>  void fn2 (TFC *);
>  
>  void 
> @@ -24,6 +24,6 @@ bar (B *b, int *i)
>  int
>  foo (void *a)
>  {
> -  T *t = a; /* { dg-warning "request for implicit conversion from
> .void \\*. to .T \\* {aka struct T \\*}. not" } */
> +  T *t = a; /* { dg-warning "request for implicit conversion from
> 'void \\*' to 'T \\*' {aka 'struct T \\*'} not" } */
>    return t->i;
>  }
> diff --git a/gcc/testsuite/gcc.dg/diag-aka-2.c
> b/gcc/testsuite/gcc.dg/diag-aka-2.c
> new file mode 100644
> index 0000000..a4b2242
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/diag-aka-2.c
> @@ -0,0 +1,12 @@
> +/* Verify that the "aka" descriptions for typedefs are correctly
> +   quoted (PR 62170).  */
> +
> +typedef struct s1 t1;
> +
> +int foo(t1 *); /* { dg-message "expected 't1 \\*' {aka 'struct s1
> \\*'} but argument is of type 't2 \\*' {aka 'struct s2 \\*'}" } */
> +
> +int bar() {
> +  typedef struct s2 {int i;} t2;
> +  t2 pos;
> +  return foo(&pos); /* { dg-error "incompatible pointer type" } */
> +}
> diff --git a/gcc/testsuite/gcc.dg/pr13804-1.c
> b/gcc/testsuite/gcc.dg/pr13804-1.c
> index 65b238a..5fc17f4 100644
> --- a/gcc/testsuite/gcc.dg/pr13804-1.c
> +++ b/gcc/testsuite/gcc.dg/pr13804-1.c
> @@ -20,9 +20,9 @@ void
>  f (void)
>  {
>    x0.c; /* { dg-error "'struct s0' has no member named 'c'" } */
> -  x1.c; /* { dg-error "'S0 {aka struct s0}' has no member named 'c'"
> } */
> +  x1.c; /* { dg-error "'S0' {aka 'struct s0'} has no member named
> 'c'" } */
>    x2.c; /* { dg-error "'union u0' has no member named 'c'" } */
> -  x3.c; /* { dg-error "'U0 {aka union u0}' has no member named 'c'"
> } */
> +  x3.c; /* { dg-error "'U0' {aka 'union u0'} has no member named
> 'c'" } */
>    x4->c; /* { dg-error "'struct s0' has no member named 'c'" } */
>    x5->c; /* { dg-error "'union u0' has no member named 'c'" } */
>  }
> diff --git a/gcc/testsuite/gcc.dg/pr56980.c
> b/gcc/testsuite/gcc.dg/pr56980.c
> index 27405ef..5303c61 100644
> --- a/gcc/testsuite/gcc.dg/pr56980.c
> +++ b/gcc/testsuite/gcc.dg/pr56980.c
> @@ -5,12 +5,12 @@ typedef struct A { int i; } B;
>  typedef union U { int i; } V;
>  typedef enum E { G } F;
>  
> -void foo_s (struct A); /* { dg-message "expected .struct A. but
> argument is of type .B \\* {aka struct A \\*}." } */
> -void foo_u (union U); /* { dg-message "expected .union U. but
> argument is of type .V \\* {aka union U \\*}." } */
> -void foo_e (enum E); /* { dg-message "expected .enum E. but argument
> is of type .F \\* {aka enum E \\*}." } */
> -void foo_sp (B *); /* { dg-message "expected .B \\* {aka struct A
> \\*}. but argument is of type .struct B \\*." } */
> -void foo_up (V *); /* { dg-message "expected .V \\* {aka union U
> \\*}. but argument is of type .union V \\*." } */
> -void foo_ep (F *); /* { dg-message "expected .F \\* {aka enum E
> \\*}. but argument is of type .enum F \\*." } */
> +void foo_s (struct A); /* { dg-message "expected .struct A. but
> argument is of type 'B \\*' {aka 'struct A \\*'}" } */
> +void foo_u (union U); /* { dg-message "expected .union U. but
> argument is of type 'V \\*' {aka 'union U \\*'}" } */
> +void foo_e (enum E); /* { dg-message "expected .enum E. but argument
> is of type 'F \\*' {aka 'enum E \\*'}" } */
> +void foo_sp (B *); /* { dg-message "expected 'B \\*' {aka 'struct A
> \\*'} but argument is of type .struct B \\*." } */
> +void foo_up (V *); /* { dg-message "expected 'V \\*' {aka 'union U
> \\*'} but argument is of type .union V \\*." } */
> +void foo_ep (F *); /* { dg-message "expected 'F \\*' {aka 'enum E
> \\*'} but argument is of type .enum F \\*." } */
>  
>  void 
>  bar (B *b, V *v, F *f)
> diff --git a/gcc/testsuite/gcc.dg/pr65050.c
> b/gcc/testsuite/gcc.dg/pr65050.c
> index 0822a99..e29559d 100644
> --- a/gcc/testsuite/gcc.dg/pr65050.c
> +++ b/gcc/testsuite/gcc.dg/pr65050.c
> @@ -2,9 +2,9 @@
>  /* { dg-do compile } */
>  
>  typedef int A[];
> -struct S { int i; A a[5]; } s; /* { dg-error "array type has
> incomplete element type .A {aka int\\\[\\\]}." } */
> +struct S { int i; A a[5]; } s; /* { dg-error "array type has
> incomplete element type 'A' {aka 'int\\\[\\\]'}" } */
>  extern void foo (int p[2][]); /* { dg-error "array type has
> incomplete element type .int\\\[\\\]." } */
> -extern void bar (A p[2]); /* { dg-error "array type has incomplete
> element type .A {aka int\\\[\\\]}." } */
> +extern void bar (A p[2]); /* { dg-error "array type has incomplete
> element type 'A' {aka 'int\\\[\\\]'}" } */
>  
>  void
>  foo (int p[2][]) /* { dg-error "array type has incomplete element
> type .int\\\[\\\]." } */
> @@ -12,7 +12,7 @@ foo (int p[2][]) /* { dg-error "array type has
> incomplete element type .int\\\[\
>  }
>  
>  void
> -bar (A p[2]) /* { dg-error "array type has incomplete element type
> .A {aka int\\\[\\\]}." } */
> +bar (A p[2]) /* { dg-error "array type has incomplete element type
> 'A' {aka 'int\\\[\\\]'}" } */
>  {
>  }
>  
> @@ -20,4 +20,4 @@ struct T;
>  struct T t[5]; /* { dg-error "array type has incomplete element type
> .struct T." } */
>  struct U u[] = { { "abc" } }; /* { dg-error "array type has
> incomplete element type .struct U." } */
>  typedef struct T TT;
> -TT tt[5]; /* { dg-error "array type has incomplete element type .TT
> {aka struct T}." } */
> +TT tt[5]; /* { dg-error "array type has incomplete element type 'TT'
> {aka 'struct T'}" } */
> diff --git a/gcc/testsuite/gcc.dg/redecl-14.c
> b/gcc/testsuite/gcc.dg/redecl-14.c
> index 97003c1..1bf1d96 100644
> --- a/gcc/testsuite/gcc.dg/redecl-14.c
> +++ b/gcc/testsuite/gcc.dg/redecl-14.c
> @@ -18,5 +18,5 @@ f (void)
>    }
>    extern IAP a[];
>    extern IAP a[5];
> -  sizeof (*a[0]); /* { dg-error "invalid application of 'sizeof' to
> incomplete type 'IA {aka int\\\[\\\]}'" } */
> +  sizeof (*a[0]); /* { dg-error "invalid application of 'sizeof' to
> incomplete type 'IA' {aka 'int\\\[\\\]'}" } */
>  }
> diff --git a/gcc/testsuite/gcc.dg/utf16-4.c
> b/gcc/testsuite/gcc.dg/utf16-4.c
> index f9ebd61..f2d4388 100644
> --- a/gcc/testsuite/gcc.dg/utf16-4.c
> +++ b/gcc/testsuite/gcc.dg/utf16-4.c
> @@ -12,7 +12,7 @@ char16_t	c2 = u'\U00064321';	/* { dg
> -warning "constant too long" } */
>  char16_t	c3 = 'a';
>  char16_t	c4 = U'a';
>  char16_t	c5 = U'\u2029';
> -char16_t	c6 = U'\U00064321';	/* { dg-warning
> "conversion from .unsigned int. to .char16_t {aka short unsigned
> int}. changes value from .410401. to .17185." } */
> +char16_t	c6 = U'\U00064321';	/* { dg-warning
> "conversion from .unsigned int. to 'char16_t' {aka 'short unsigned
> int'} changes value from .410401. to .17185." } */
>  char16_t	c7 = L'a';
>  char16_t	c8 = L'\u2029';
>  char16_t 	c9 = L'\U00064321';	/* { dg-warning
> "conversion" "" { target { 4byte_wchar_t } } } */
> diff --git a/gcc/testsuite/gcc.target/i386/sse-vect-types.c
> b/gcc/testsuite/gcc.target/i386/sse-vect-types.c
> index 9cb6f3e..ac4ece4 100644
> --- a/gcc/testsuite/gcc.target/i386/sse-vect-types.c
> +++ b/gcc/testsuite/gcc.target/i386/sse-vect-types.c
> @@ -10,4 +10,4 @@ __m128d foo1(__m128d z, __m128d  a, int N) {
>    }
>    return a;
>  }
> -/* { dg-message "note: expected '\[^'\n\]*' but argument is of type
> '\[^'\n\]*'" "note: expected" { target *-*-* } 0 } */
> +/* { dg-message "note: expected '.*'.* but argument is of type '.*'"
> "note: expected" { target *-*-* } 0 } */
> diff --git a/gcc/testsuite/obj-c++.dg/invalid-type-1.mm
> b/gcc/testsuite/obj-c++.dg/invalid-type-1.mm
> index cb2138f..59c8666 100644
> --- a/gcc/testsuite/obj-c++.dg/invalid-type-1.mm
> +++ b/gcc/testsuite/obj-c++.dg/invalid-type-1.mm
> @@ -18,8 +18,8 @@ id <MyProtocol> object; /* This is fine.  */
>  
>  AClass <MyProtocol> *object1; /* This is fine.  */
>  
> -Integer <MyProtocol> *object2; /* { dg-error ".Integer {aka int}. is
> not a template" } */
> +Integer <MyProtocol> *object2; /* { dg-error "'Integer' {aka 'int'}
> is not a template" } */
>  /* { dg-error ".MyProtocol. was not declared in this scope" "" {
> target *-*-* } .-1 } */
>  
> -Integer <NonExistingProtocol> *object3; /* { dg-error ".Integer {aka
> int}. is not a template" } */
> +Integer <NonExistingProtocol> *object3; /* { dg-error "'Integer'
> {aka 'int'} is not a template" } */
>  /* { dg-error ".NonExistingProtocol. was not declared in this scope"
> "" { target *-*-* } .-1 } */
> diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
> index 52b7e7f..5f3295f 100644
> --- a/gcc/tree-diagnostic.c
> +++ b/gcc/tree-diagnostic.c
> @@ -245,7 +245,7 @@ virt_loc_aware_diagnostic_finalizer
> (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 *, const char **)
>  {
>    tree t;
>  
> diff --git a/gcc/tree-diagnostic.h b/gcc/tree-diagnostic.h
> index 85aa980..e38bb44 100644
> --- a/gcc/tree-diagnostic.h
> +++ b/gcc/tree-diagnostic.h
> @@ -55,6 +55,6 @@ void virt_loc_aware_diagnostic_finalizer
> (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 *, const char
> **);
>  
>  #endif /* ! GCC_TREE_DIAGNOSTIC_H */
Jason Merrill June 20, 2017, 5:58 p.m. UTC | #3
On Tue, Jun 20, 2017 at 11:50 AM, David Malcolm <dmalcolm@redhat.com> wrote:
>> +       ob->next_free = p + type_start + type_len;

I'm uncomfortable with modifying the obstack directly.  Why not use
obstack_free?  I guess for that you'd want to change type_start to a
pointer and get it from obstack_next_free.

Jason
Jason Merrill June 20, 2017, 6:01 p.m. UTC | #4
On Tue, Jun 20, 2017 at 1:58 PM, Jason Merrill <jason@redhat.com> wrote:
> On Tue, Jun 20, 2017 at 11:50 AM, David Malcolm <dmalcolm@redhat.com> wrote:
>>> +       ob->next_free = p + type_start + type_len;
>
> I'm uncomfortable with modifying the obstack directly.  Why not use
> obstack_free?

...because you aren't freeing the object, but shrinking it.  So
obstack_blank is a better choice.

Jason
David Malcolm June 20, 2017, 7:06 p.m. UTC | #5
On Tue, 2017-06-20 at 14:01 -0400, Jason Merrill wrote:
> On Tue, Jun 20, 2017 at 1:58 PM, Jason Merrill <jason@redhat.com>
> wrote:
> > On Tue, Jun 20, 2017 at 11:50 AM, David Malcolm <
> > dmalcolm@redhat.com> wrote:
> > > > +       ob->next_free = p + type_start + type_len;
> > 
> > I'm uncomfortable with modifying the obstack directly.  Why not use
> > obstack_free?
> 
> ...because you aren't freeing the object, but shrinking it.  So
> obstack_blank is a better choice.

Thanks.

As of r229987 ("Copy gnulib obstack files", aka
1ed1385ecb1c11d6915adac74afa2ff7da8be5d1),

libiberty/obstacks.texi says:
> @cindex shrinking objects
> You can use @code{obstack_blank_fast} with a ``negative'' size
> argument to make the current object smaller.  Just don't try to
> shrink it beyond zero length---there's no telling what will happen 
> if you do that.  Earlier versions of obstacks allowed you to use
> @code{obstack_blank} to shrink objects.  This will no longer work.

It's not clear to me what the issue alluded to with negative
obstack_blank is, but I chose to follow the above docs and use
obstack_blank_fast; am testing an updated patch in which the above line
now looks like:

	  obstack_blank_fast (ob, -(type_start + type_len));

Is the patch OK with that change? (assuming bootstrap&regrtesting
pass), or should I re-post?

On a related matter, this patch conflicts with Volker's patch here:

  https://gcc.gnu.org/ml/gcc-patches/2017-04/msg01576.html

in which he removes the trailing "{enum}" info (and hence all of our
changes to the testsuite conflict between the two patches...)

Do you have any thoughts on that other patch? [Ccing Volker]

Thanks
Dave
Jason Merrill June 20, 2017, 7:11 p.m. UTC | #6
On Tue, Jun 20, 2017 at 3:06 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> It's not clear to me what the issue alluded to with negative
> obstack_blank is, but I chose to follow the above docs and use
> obstack_blank_fast; am testing an updated patch in which the above line
> now looks like:
>
>           obstack_blank_fast (ob, -(type_start + type_len));
>
> Is the patch OK with that change? (assuming bootstrap&regrtesting
> pass), or should I re-post?

OK with that change.

> On a related matter, this patch conflicts with Volker's patch here:
>
>   https://gcc.gnu.org/ml/gcc-patches/2017-04/msg01576.html
>
> in which he removes the trailing "{enum}" info (and hence all of our
> changes to the testsuite conflict between the two patches...)
>
> Do you have any thoughts on that other patch? [Ccing Volker]

That patch makes sense to me; I prefer "enum E" to "E {enum}".

Jason
Volker Reichelt June 21, 2017, 7:59 a.m. UTC | #7
On 20 Jun, Jason Merrill wrote:
> On Tue, Jun 20, 2017 at 3:06 PM, David Malcolm <dmalcolm@redhat.com> wrote:
>> It's not clear to me what the issue alluded to with negative
>> obstack_blank is, but I chose to follow the above docs and use
>> obstack_blank_fast; am testing an updated patch in which the above line
>> now looks like:
>>
>>           obstack_blank_fast (ob, -(type_start + type_len));
>>
>> Is the patch OK with that change? (assuming bootstrap&regrtesting
>> pass), or should I re-post?
> 
> OK with that change.
> 
>> On a related matter, this patch conflicts with Volker's patch here:
>>
>>   https://gcc.gnu.org/ml/gcc-patches/2017-04/msg01576.html
>>
>> in which he removes the trailing "{enum}" info (and hence all of our
>> changes to the testsuite conflict between the two patches...)
>>
>> Do you have any thoughts on that other patch? [Ccing Volker]
> 
> That patch makes sense to me; I prefer "enum E" to "E {enum}".
> 
> Jason

Is 'makes sense' equivalent to 'OK for trunk' here? If so, should my
patch go in before David's or should we do it the other way round?

Regards,
Volker
Martin Sebor July 14, 2017, 4:23 p.m. UTC | #8
On 06/21/2017 01:59 AM, Volker Reichelt wrote:
> On 20 Jun, Jason Merrill wrote:
>> On Tue, Jun 20, 2017 at 3:06 PM, David Malcolm <dmalcolm@redhat.com> wrote:
>>> It's not clear to me what the issue alluded to with negative
>>> obstack_blank is, but I chose to follow the above docs and use
>>> obstack_blank_fast; am testing an updated patch in which the above line
>>> now looks like:
>>>
>>>           obstack_blank_fast (ob, -(type_start + type_len));
>>>
>>> Is the patch OK with that change? (assuming bootstrap&regrtesting
>>> pass), or should I re-post?
>>
>> OK with that change.
>>
>>> On a related matter, this patch conflicts with Volker's patch here:
>>>
>>>   https://gcc.gnu.org/ml/gcc-patches/2017-04/msg01576.html
>>>
>>> in which he removes the trailing "{enum}" info (and hence all of our
>>> changes to the testsuite conflict between the two patches...)
>>>
>>> Do you have any thoughts on that other patch? [Ccing Volker]
>>
>> That patch makes sense to me; I prefer "enum E" to "E {enum}".
>>
>> Jason
>
> Is 'makes sense' equivalent to 'OK for trunk' here? If so, should my
> patch go in before David's or should we do it the other way round?

I missed this and have been pinging your patch on your behalf
(below).  In the interest on making progress on this, IMO trivial,
change I recommend taking Jason's comment as approval.

https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00472.html

Martin
diff mbox

Patch

diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
index 05212b2..b87cdda 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -28,7 +28,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "c-objc-common.h"
 
 static bool c_tree_printer (pretty_printer *, text_info *, const char *,
-			    int, bool, bool, bool, bool, const char **);
+			    int, bool, bool, bool, bool *, const char **);
 
 bool
 c_missing_noreturn_ok_p (tree decl)
@@ -76,7 +76,7 @@  c_objc_common_init (void)
 static bool
 c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
 		int precision, bool wide, bool set_locus, bool hash,
-		bool, const char **)
+		bool *quoted, const char **)
 {
   tree t = NULL_TREE;
   tree name;
@@ -156,12 +156,20 @@  c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
 	      return true;
 
 	    /* They're not, print the stripped version now.  */
+	    if (*quoted)
+	      pp_end_quote (pp, pp_show_color (pp));
 	    pp_c_whitespace (cpp);
 	    pp_left_brace (cpp);
 	    pp_c_ws_string (cpp, _("aka"));
 	    pp_c_whitespace (cpp);
+	    if (*quoted)
+	      pp_begin_quote (pp, pp_show_color (pp));
 	    cpp->type_id (TYPE_CANONICAL (t));
+	    if (*quoted)
+	      pp_end_quote (pp, pp_show_color (pp));
 	    pp_right_brace (cpp);
+	    /* No further closing quotes are needed.  */
+	    *quoted = false;
 	  }
 	return true;
       }
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index ed67d14..95288d1 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -57,7 +57,7 @@  static const char *expr_to_string (tree);
 static const char *fndecl_to_string (tree, int);
 static const char *op_to_string	(enum tree_code);
 static const char *parm_to_string (int);
-static const char *type_to_string (tree, int);
+static const char *type_to_string (tree, int, bool, bool *, bool);
 
 static void dump_alias_template_specialization (cxx_pretty_printer *, tree, int);
 static void dump_type (cxx_pretty_printer *, tree, int);
@@ -99,7 +99,7 @@  static void cp_diagnostic_starter (diagnostic_context *, diagnostic_info *);
 static void cp_print_error_function (diagnostic_context *, diagnostic_info *);
 
 static bool cp_printer (pretty_printer *, text_info *, const char *,
-			int, bool, bool, bool, bool, const char **);
+			int, bool, bool, bool, bool *, const char **);
 
 /* Struct for handling %H or %I, which require delaying printing the
    type until a postprocessing stage.  */
@@ -3142,8 +3142,28 @@  op_to_string (enum tree_code p)
   return id ? IDENTIFIER_POINTER (id) : M_("<unknown>");
 }
 
+/* Return a GC-allocated representation of type TYP, with verbosity VERBOSE.
+
+   If QUOTE is non-NULL and if *QUOTE is true, then quotes are added to the
+   string in appropriate places, and *QUOTE is written to with false
+   to suppress pp_format's trailing close quote so that e.g.
+     foo_typedef {aka underlying_foo} {enum}
+   can be printed by "%qT" as:
+     `foo_typedef' {aka `underlying_foo'} {enum}
+   rather than:
+     `foo_typedef {aka underlying_foo} {enum}'
+   When adding such quotes, if POSTPROCESSED is true (for handling %H and %I)
+   then a leading open quote will be added, whereas if POSTPROCESSED is false
+   (for handling %T) then any leading quote has already been added by
+   pp_format, or is not needed due to QUOTE being NULL (for template arguments
+   within %H and %I).
+
+   SHOW_COLOR is used to determine the colorization of any quotes that
+   are added.  */
+
 static const char *
-type_to_string (tree typ, int verbose)
+type_to_string (tree typ, int verbose, bool postprocessed, bool *quote,
+		bool show_color)
 {
   int flags = 0;
   if (verbose)
@@ -3151,7 +3171,19 @@  type_to_string (tree typ, int verbose)
   flags |= TFF_TEMPLATE_HEADER;
 
   reinit_cxx_pp ();
+
+  if (postprocessed && quote && *quote)
+    pp_begin_quote (cxx_pp, show_color);
+
+  struct obstack *ob = pp_buffer (cxx_pp)->obstack;
+  int type_start, type_len;
+  type_start = obstack_object_size (ob);
+
   dump_type (cxx_pp, typ, flags);
+
+  /* Remember the end of the initial dump.  */
+  type_len = obstack_object_size (ob) - type_start;
+
   /* If we're printing a type that involves typedefs, also print the
      stripped version.  But sometimes the stripped version looks
      exactly the same, so we don't want it after all.  To avoid printing
@@ -3160,21 +3192,42 @@  type_to_string (tree typ, int verbose)
       && !uses_template_parms (typ))
     {
       int aka_start, aka_len; char *p;
-      struct obstack *ob = pp_buffer (cxx_pp)->obstack;
-      /* Remember the end of the initial dump.  */
-      int len = obstack_object_size (ob);
       tree aka = strip_typedefs (typ);
+      if (quote && *quote)
+	pp_end_quote (cxx_pp, show_color);
       pp_string (cxx_pp, " {aka");
       pp_cxx_whitespace (cxx_pp);
+      if (quote && *quote)
+	pp_begin_quote (cxx_pp, show_color);
       /* And remember the start of the aka dump.  */
       aka_start = obstack_object_size (ob);
       dump_type (cxx_pp, aka, flags);
       aka_len = obstack_object_size (ob) - aka_start;
+      if (quote && *quote)
+	pp_end_quote (cxx_pp, show_color);
       pp_right_brace (cxx_pp);
       p = (char*)obstack_base (ob);
-      /* If they are identical, cut off the aka with a NUL.  */
-      if (len == aka_len && memcmp (p, p+aka_start, len) == 0)
-	p[len] = '\0';
+      /* If they are identical, cut off the aka by unwinding the obstack.  */
+      if (type_len == aka_len
+	  && memcmp (p + type_start, p+aka_start, type_len) == 0)
+	{
+	  /* We can't add a '\0' here, since we may be adding a closing quote
+	     below, and it would be hidden by the '\0'.
+	     Instead, manually unwind the current object within the obstack
+	     so that the insertion point is at the end of the type, before
+	     the "' {aka".  */
+	  ob->next_free = p + type_start + type_len;
+	}
+      else
+	if (quote)
+	  /* No further closing quotes are needed.  */
+	  *quote = false;
+    }
+
+  if (quote && *quote)
+    {
+      pp_end_quote (cxx_pp, show_color);
+      *quote = false;
     }
 
   if (typ && TYPE_P (typ) && TREE_CODE (typ) == ENUMERAL_TYPE)
@@ -3643,7 +3696,7 @@  static const char *
 arg_to_string (tree arg, bool verbose)
 {
   if (TYPE_P (arg))
-    return type_to_string (arg, verbose);
+    return type_to_string (arg, verbose, true, NULL, false);
   else
     return expr_to_string (arg);
 }
@@ -3935,8 +3988,10 @@  cxx_format_postprocessor::handle (pretty_printer *pp)
 	{
 	  /* If the types were not comparable, they are printed normally,
 	     and no difference tree is printed.  */
-	  type_a_text = type_to_string (type_a.m_tree, type_a.m_verbose);
-	  type_b_text = type_to_string (type_b.m_tree, type_b.m_verbose);
+	  type_a_text = type_to_string (type_a.m_tree, type_a.m_verbose,
+					true, &type_a.m_quote, show_color);
+	  type_b_text = type_to_string (type_b.m_tree, type_b.m_verbose,
+					true, &type_b.m_quote, show_color);
 	}
 
       if (type_a.m_quote)
@@ -4009,7 +4064,7 @@  defer_phase_2_of_type_diff (deferred_printed_type *deferred,
 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, const char **buffer_ptr)
 {
   gcc_assert (pp->m_format_postprocessor);
   cxx_format_postprocessor *postprocessor
@@ -4052,7 +4107,12 @@  cp_printer (pretty_printer *pp, text_info *text, const char *spec,
     case 'P': result = parm_to_string (next_int);		break;
     case 'Q': result = assop_to_string (next_tcode);		break;
     case 'S': result = subst_to_string (next_tree);		break;
-    case 'T': result = type_to_string (next_tree, verbose);	break;
+    case 'T':
+      {
+	result = type_to_string (next_tree, verbose, false, quoted,
+				 pp_show_color (pp));
+      }
+      break;
     case 'V': result = cv_to_string (next_tree, verbose);	break;
     case 'X': result = eh_spec_to_string (next_tree, verbose);  break;
 
@@ -4063,14 +4123,14 @@  cp_printer (pretty_printer *pp, text_info *text, const char *spec,
     case 'H':
       {
 	defer_phase_2_of_type_diff (&postprocessor->m_type_a, next_tree,
-				    buffer_ptr, verbose, quoted);
+				    buffer_ptr, verbose, *quoted);
 	return true;
       }
 
     case 'I':
       {
 	defer_phase_2_of_type_diff (&postprocessor->m_type_b, next_tree,
-				    buffer_ptr, verbose, quoted);
+				    buffer_ptr, verbose, *quoted);
 	return true;
       }
 
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index 3ad1cf9..2cece49 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -918,7 +918,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, const char **buffer_ptr)
 {
   switch (*spec)
     {
diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c
index 570dec7..6aee2b5 100644
--- a/gcc/pretty-print.c
+++ b/gcc/pretty-print.c
@@ -545,10 +545,7 @@  pp_format (pretty_printer *pp, text_info *text)
       gcc_assert (!wide || precision == 0);
 
       if (quote)
-	{
-	  pp_string (pp, open_quote);
-	  pp_string (pp, colorize_start (pp_show_color (pp), "quote"));
-	}
+	pp_begin_quote (pp, pp_show_color (pp));
 
       switch (*p)
 	{
@@ -675,19 +672,21 @@  pp_format (pretty_printer *pp, text_info *text)
 	  {
 	    bool ok;
 
+	    /* Call the format decoder.
+	       Pass the address of "quote" so that format decoders can
+	       potentially disable printing of the closing quote
+	       (e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C family
+	       of frontends).  */
 	    gcc_assert (pp_format_decoder (pp));
 	    ok = pp_format_decoder (pp) (pp, text, p,
-					 precision, wide, plus, hash, quote,
+					 precision, wide, plus, hash, &quote,
 					 formatters[argno]);
 	    gcc_assert (ok);
 	  }
 	}
 
       if (quote)
-	{
-	  pp_string (pp, colorize_stop (pp_show_color (pp)));
-	  pp_string (pp, close_quote);
-	}
+	pp_end_quote (pp, pp_show_color (pp));
 
       obstack_1grow (&buffer->chunk_obstack, '\0');
       *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
@@ -1061,6 +1060,26 @@  pp_separate_with (pretty_printer *pp, char c)
   pp_space (pp);
 }
 
+/* Add a localized open quote, and if SHOW_COLOR is true, begin colorizing
+   using the "quote" color.  */
+
+void
+pp_begin_quote (pretty_printer *pp, bool show_color)
+{
+  pp_string (pp, open_quote);
+  pp_string (pp, colorize_start (show_color, "quote"));
+}
+
+/* If SHOW_COLOR is true, stop colorizing.
+   Add a localized close quote.  */
+
+void
+pp_end_quote (pretty_printer *pp, bool show_color)
+{
+  pp_string (pp, colorize_stop (show_color));
+  pp_string (pp, close_quote);
+}
+
 
 /* The string starting at P has LEN (at least 1) bytes left; if they
    start with a valid UTF-8 sequence, return the length of that
diff --git a/gcc/pretty-print.h b/gcc/pretty-print.h
index 40e56a3..ff70b70 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -180,7 +180,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 *, const char **);
 
 /* Client supplied function used to decode formats.  */
 #define pp_format_decoder(PP) (PP)->format_decoder
@@ -387,6 +387,9 @@  extern void pp_write_text_to_stream (pretty_printer *);
 extern void pp_write_text_as_dot_label_to_stream (pretty_printer *, bool);
 extern void pp_maybe_space (pretty_printer *);
 
+extern void pp_begin_quote (pretty_printer *, bool);
+extern void pp_end_quote (pretty_printer *, bool);
+
 /* Switch into verbatim mode and return the old mode.  */
 static inline pp_wrapping_mode_t
 pp_set_verbatim_wrapping_ (pretty_printer *pp)
diff --git a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
index 11269cc..39b6052 100644
--- a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
@@ -17,121 +17,121 @@  void bar (E);
 void
 foo ()
 {
-  A a1 { 5 };		// { dg-error "invalid conversion from 'int' to 'A {enum}'" }
-  B b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+  A a1 { 5 };		// { dg-error "invalid conversion from 'int' to 'A' {enum}" }
+  B b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
   C c1 { s };
-  D d1 { D(t) };	// { dg-error "invalid cast from type 'T' to type 'D {enum}'" }
-  D d2 { t };		// { dg-error "cannot convert 'T' to 'D {enum}' in initialization" "" { target c++14_down } }
-			// { dg-error "invalid cast from type 'T' to type 'D {enum}'" "" { target c++1z } .-1 }
-  D d3 { 9 };		// { dg-error "cannot convert 'int' to 'D {enum}' in initialization" "" { target c++14_down } }
-  D d4 { l };		// { dg-error "cannot convert 'long int' to 'D {enum}' in initialization" "" { target c++14_down } }
+  D d1 { D(t) };	// { dg-error "invalid cast from type 'T' to type 'D' {enum}" }
+  D d2 { t };		// { dg-error "cannot convert 'T' to 'D' {enum} in initialization" "" { target c++14_down } }
+			// { dg-error "invalid cast from type 'T' to type 'D' {enum}" "" { target c++1z } .-1 }
+  D d3 { 9 };		// { dg-error "cannot convert 'int' to 'D' {enum} in initialization" "" { target c++14_down } }
+  D d4 { l };		// { dg-error "cannot convert 'long int' to 'D' {enum} in initialization" "" { target c++14_down } }
   D d5 { D(l) };
-  D d6 { G };		// { dg-error "cannot convert 'A {enum}' to 'D {enum}' in initialization" "" { target c++14_down } }
-  E e1 { 5 };		// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
-  E e2 { -1 };		// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
+  D d6 { G };		// { dg-error "cannot convert 'A' {enum} to 'D' {enum} in initialization" "" { target c++14_down } }
+  E e1 { 5 };		// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
+  E e2 { -1 };		// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  E e3 { 5.0 };		// { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+  E e3 { 5.0 };		// { dg-error "cannot convert 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  E e4 { 5.2 };		// { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+  E e4 { 5.2 };		// { dg-error "cannot convert 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  B b2 = { 7 };		// { dg-error "invalid conversion from 'int' to 'B {enum}'" }
-  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
+  B b2 = { 7 };		// { dg-error "invalid conversion from 'int' to 'B' {enum}" }
+  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to 'C' {enum} in initialization" "" { target c++14_down } }
 
-  D *d7 = new D { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target c++14_down } }
-  E *e5 = new E { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+  D *d7 = new D { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D' {enum} in initialization" "" { target c++14_down } }
+  E *e5 = new E { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  bar ({ 10 });		// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' for argument" }
-  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
-  V v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E {enum}'" }
-  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
-  V v3 = { E { 5.0 } };	// { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+  bar ({ 10 });		// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} for argument" }
+  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
+  V v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E' {enum}" }
+  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
+  V v3 = { E { 5.0 } };	// { dg-error "cannot convert 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  V v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" }
-  if (B b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+  V v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" }
+  if (B b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
     ;
-  if (B b4 { 4.0 })	// { dg-error "cannot convert 'double' to 'B {enum}' in initialization" "" { target c++14_down } }
+  if (B b4 { 4.0 })	// { dg-error "cannot convert 'double' to 'B' {enum} in initialization" "" { target c++14_down } }
     ;			// { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int' inside" "" { target c++1z } .-1 }
-  C c3 { 8L };		// { dg-error "cannot convert 'long int' to 'C {enum}' in initialization" "" { target c++14_down } }
-  B b4 {short (c + 5)};	// { dg-error "invalid conversion from 'short int' to 'B {enum}'" "" { target c++14_down } }
-  B b5 {c + 5};		// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+  C c3 { 8L };		// { dg-error "cannot convert 'long int' to 'C' {enum} in initialization" "" { target c++14_down } }
+  B b4 {short (c + 5)};	// { dg-error "invalid conversion from 'short int' to 'B' {enum}" "" { target c++14_down } }
+  B b5 {c + 5};		// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int' inside" "" { target c++1z } .-1 }
-  C c4 { ll };		// { dg-error "cannot convert 'long long int' to 'C {enum}' in initialization" "" { target c++14_down } }
+  C c4 { ll };		// { dg-error "cannot convert 'long long int' to 'C' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of 'll' from 'long long int' to 'int' inside" "" { target c++1z } .-1 }
-  C c5 {short (c + 5)};	// { dg-error "cannot convert 'short int' to 'C {enum}' in initialization" "" { target c++14_down } }
-  C c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
+  C c5 {short (c + 5)};	// { dg-error "cannot convert 'short int' to 'C' {enum} in initialization" "" { target c++14_down } }
+  C c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C' {enum} in initialization" "" { target c++14_down } }
 }
 
 struct U
 {
-  U () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
-  U (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+  U () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
+  U (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
   U (float) : e({ 6 }) {}// { dg-error "list-initializer for non-class type must not be parenthesized" }
-			// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target *-*-* } .-1 }
+			// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target *-*-* } .-1 }
   E e;
 };
 
 struct W
 {
-  A a { 5 };		// { dg-error "invalid conversion from 'int' to 'A {enum}'" }
-  B b { 6 };		// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
-  C c { 3.0f };		// { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } }
+  A a { 5 };		// { dg-error "invalid conversion from 'int' to 'A' {enum}" }
+  B b { 6 };		// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
+  C c { 3.0f };		// { dg-error "cannot convert \[^\n\r]* to 'C' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-1 }
-  D d = { 7 };		// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" }
+  D d = { 7 };		// { dg-error "cannot convert \[^\n\r]* to 'D' {enum} in initialization" }
 };
 
 template <int N>
 void
 foo2 ()
 {
-  A a1 { 5 };		// { dg-error "invalid conversion from 'int' to 'A {enum}'" }
-  B b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+  A a1 { 5 };		// { dg-error "invalid conversion from 'int' to 'A' {enum}" }
+  B b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
   C c1 { s };
-  D d1 { D(t) };	// { dg-error "invalid cast from type 'T' to type 'D {enum}'" }
-  D d2 { t };		// { dg-error "cannot convert 'T' to 'D {enum}' in initialization" "" { target c++14_down } }
-			// { dg-error "invalid cast from type 'T' to type 'D {enum}'" "" { target c++1z } .-1 }
-  D d3 { 9 };		// { dg-error "cannot convert 'int' to 'D {enum}' in initialization" "" { target c++14_down } }
-  D d4 { l };		// { dg-error "cannot convert 'long int' to 'D {enum}' in initialization" "" { target c++14_down } }
+  D d1 { D(t) };	// { dg-error "invalid cast from type 'T' to type 'D' {enum}" }
+  D d2 { t };		// { dg-error "cannot convert 'T' to 'D' {enum} in initialization" "" { target c++14_down } }
+			// { dg-error "invalid cast from type 'T' to type 'D' {enum}" "" { target c++1z } .-1 }
+  D d3 { 9 };		// { dg-error "cannot convert 'int' to 'D' {enum} in initialization" "" { target c++14_down } }
+  D d4 { l };		// { dg-error "cannot convert 'long int' to 'D' {enum} in initialization" "" { target c++14_down } }
   D d5 { D(l) };
-  D d6 { G };		// { dg-error "cannot convert 'A {enum}' to 'D {enum}' in initialization" "" { target c++14_down } }
-  E e1 { 5 };		// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
-  E e2 { -1 };		// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
+  D d6 { G };		// { dg-error "cannot convert 'A' {enum} to 'D' {enum} in initialization" "" { target c++14_down } }
+  E e1 { 5 };		// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
+  E e2 { -1 };		// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  E e3 { 5.0 };		// { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+  E e3 { 5.0 };		// { dg-error "cannot convert 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  E e4 { 5.2 };		// { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+  E e4 { 5.2 };		// { dg-error "cannot convert 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  B b2 = { 7 };		// { dg-error "invalid conversion from 'int' to 'B {enum}'" }
-  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
-  D *d7 = new D { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target c++14_down } }
-  E *e5 = new E { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+  B b2 = { 7 };		// { dg-error "invalid conversion from 'int' to 'B' {enum}" }
+  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to 'C' {enum} in initialization" "" { target c++14_down } }
+  D *d7 = new D { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D' {enum} in initialization" "" { target c++14_down } }
+  E *e5 = new E { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  bar ({ 10 });		// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' for argument" }
-  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
-  V v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E {enum}'" }
-  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
-  V v3 = { E { 5.0 } };	// { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+  bar ({ 10 });		// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} for argument" }
+  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
+  V v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E' {enum}" }
+  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
+  V v3 = { E { 5.0 } };	// { dg-error "cannot convert 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  V v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" }
-  if (B b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+  V v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" }
+  if (B b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
     ;
-  if (B b4 { 4.0 })	// { dg-error "cannot convert 'double' to 'B {enum}' in initialization" "" { target c++14_down } }
+  if (B b4 { 4.0 })	// { dg-error "cannot convert 'double' to 'B' {enum} in initialization" "" { target c++14_down } }
     ;			// { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int' inside" "" { target c++1z } .-1 }
-  C c3 { 8L };		// { dg-error "cannot convert 'long int' to 'C {enum}' in initialization" "" { target c++14_down } }
-  B b4 {short (c + 5)};	// { dg-error "invalid conversion from 'short int' to 'B {enum}'" "" { target c++14_down } }
-  B b5 {c + 5};		// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+  C c3 { 8L };		// { dg-error "cannot convert 'long int' to 'C' {enum} in initialization" "" { target c++14_down } }
+  B b4 {short (c + 5)};	// { dg-error "invalid conversion from 'short int' to 'B' {enum}" "" { target c++14_down } }
+  B b5 {c + 5};		// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int' inside" "" { target c++1z } .-1 }
-  C c4 { ll };		// { dg-error "cannot convert 'long long int' to 'C {enum}' in initialization" "" { target c++14_down } }
+  C c4 { ll };		// { dg-error "cannot convert 'long long int' to 'C' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of 'll' from 'long long int' to 'int' inside" "" { target c++1z } .-1 }
-  C c5 {short (c + 5)};	// { dg-error "cannot convert 'short int' to 'C {enum}' in initialization" "" { target c++14_down } }
-  C c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
+  C c5 {short (c + 5)};	// { dg-error "cannot convert 'short int' to 'C' {enum} in initialization" "" { target c++14_down } }
+  C c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C' {enum} in initialization" "" { target c++14_down } }
 }
 
 template <int N>
 struct U2
 {
-  U2 () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
-  U2 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+  U2 () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
+  U2 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
   U2 (float) : e({ 6 }) {}
   E e;
@@ -140,11 +140,11 @@  struct U2
 template <int N>
 struct W2
 {
-  A a { 5 };		// { dg-error "invalid conversion from 'int' to 'A {enum}'" "" { target *-*-* } .-2 }
-  B b { 6 };		// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } .-3 }
-  C c { 3.0f };		// { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .-4 }
+  A a { 5 };		// { dg-error "invalid conversion from 'int' to 'A' {enum}" "" { target *-*-* } .-2 }
+  B b { 6 };		// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } .-3 }
+  C c { 3.0f };		// { dg-error "cannot convert \[^\n\r]* to 'C' {enum} in initialization" "" { target c++14_down } .-4 }
 			// { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-5 }
-  D d = { 7 };		// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-6 }
+  D d = { 7 };		// { dg-error "cannot convert \[^\n\r]* to 'D' {enum} in initialization" "" { target *-*-* } .-6 }
 };
 
 template <typename H, typename I, typename J, typename K, typename L, typename M>
@@ -152,54 +152,54 @@  void
 foo3 ()
 {
   void bar3 (L);
-  H a1 { 5 };		// { dg-error "invalid conversion from 'int' to 'A {enum}'" }
-  I b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+  H a1 { 5 };		// { dg-error "invalid conversion from 'int' to 'A' {enum}" }
+  I b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
   J c1 { s };
-  K d1 { K(t) };	// { dg-error "invalid cast from type 'T' to type 'D {enum}'" }
-  K d2 { t };		// { dg-error "cannot convert 'T' to 'D {enum}' in initialization" "" { target c++14_down } }
-			// { dg-error "invalid cast from type 'T' to type 'D {enum}'" "" { target c++1z } .-1 }
-  K d3 { 9 };		// { dg-error "cannot convert 'int' to 'D {enum}' in initialization" "" { target c++14_down } }
-  K d4 { l };		// { dg-error "cannot convert 'long int' to 'D {enum}' in initialization" "" { target c++14_down } }
+  K d1 { K(t) };	// { dg-error "invalid cast from type 'T' to type 'D' {enum}" }
+  K d2 { t };		// { dg-error "cannot convert 'T' to 'D' {enum} in initialization" "" { target c++14_down } }
+			// { dg-error "invalid cast from type 'T' to type 'D' {enum}" "" { target c++1z } .-1 }
+  K d3 { 9 };		// { dg-error "cannot convert 'int' to 'D' {enum} in initialization" "" { target c++14_down } }
+  K d4 { l };		// { dg-error "cannot convert 'long int' to 'D' {enum} in initialization" "" { target c++14_down } }
   K d5 { K(l) };
-  K d6 { G };		// { dg-error "cannot convert 'A {enum}' to 'D {enum}' in initialization" "" { target c++14_down } }
-  L e1 { 5 };		// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
-  L e2 { -1 };		// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
+  K d6 { G };		// { dg-error "cannot convert 'A' {enum} to 'D' {enum} in initialization" "" { target c++14_down } }
+  L e1 { 5 };		// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
+  L e2 { -1 };		// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  L e3 { 5.0 };		// { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+  L e3 { 5.0 };		// { dg-error "cannot convert 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  L e4 { 5.2 };		// { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+  L e4 { 5.2 };		// { dg-error "cannot convert 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  I b2 = { 7 };		// { dg-error "invalid conversion from 'int' to 'B {enum}'" }
-  J c2 = { J { 8 } };	// { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
-  K *d7 = new K { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target c++14_down } }
-  L *e5 = new L { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+  I b2 = { 7 };		// { dg-error "invalid conversion from 'int' to 'B' {enum}" }
+  J c2 = { J { 8 } };	// { dg-error "cannot convert 'int' to 'C' {enum} in initialization" "" { target c++14_down } }
+  K *d7 = new K { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D' {enum} in initialization" "" { target c++14_down } }
+  L *e5 = new L { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  bar3 ({ 10 });	// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' for argument" }
-  bar3 (E { 9 });	// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
-  M v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E {enum}'" }
-  M v2 = { L { 12 } };	// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" "" { target c++14_down } }
-  M v3 = { L { 5.0 } };	// { dg-error "cannot convert 'double' to 'E {enum}' in initialization" "" { target c++14_down } }
+  bar3 ({ 10 });	// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} for argument" }
+  bar3 (E { 9 });	// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
+  M v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E' {enum}" }
+  M v2 = { L { 12 } };	// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" "" { target c++14_down } }
+  M v3 = { L { 5.0 } };	// { dg-error "cannot convert 'double' to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
-  M v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E {enum}' in initialization" }
-  if (I b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+  M v4 = { 13 };	// { dg-error "cannot convert 'int' to 'E' {enum} in initialization" }
+  if (I b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
     ;
-  if (I b4 { 4.0 })	// { dg-error "cannot convert 'double' to 'B {enum}' in initialization" "" { target c++14_down } }
+  if (I b4 { 4.0 })	// { dg-error "cannot convert 'double' to 'B' {enum} in initialization" "" { target c++14_down } }
     ;			// { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int' inside" "" { target c++1z } .-1 }
-  J c3 { 8L };		// { dg-error "cannot convert 'long int' to 'C {enum}' in initialization" "" { target c++14_down } }
-  I b4 {short (c + 5)};	// { dg-error "invalid conversion from 'short int' to 'B {enum}'" "" { target c++14_down } }
-  I b5 {c + 5};		// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } }
+  J c3 { 8L };		// { dg-error "cannot convert 'long int' to 'C' {enum} in initialization" "" { target c++14_down } }
+  I b4 {short (c + 5)};	// { dg-error "invalid conversion from 'short int' to 'B' {enum}" "" { target c++14_down } }
+  I b5 {c + 5};		// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int' inside" "" { target c++1z } .-1 }
-  J c4 { ll };		// { dg-error "cannot convert 'long long int' to 'C {enum}' in initialization" "" { target c++14_down } }
+  J c4 { ll };		// { dg-error "cannot convert 'long long int' to 'C' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of 'll' from 'long long int' to 'int' inside" "" { target c++1z } .-1 }
-  J c5 {short (c + 5)};	// { dg-error "cannot convert 'short int' to 'C {enum}' in initialization" "" { target c++14_down } }
-  J c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C {enum}' in initialization" "" { target c++14_down } }
+  J c5 {short (c + 5)};	// { dg-error "cannot convert 'short int' to 'C' {enum} in initialization" "" { target c++14_down } }
+  J c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C' {enum} in initialization" "" { target c++14_down } }
 }
 
 template <typename L>
 struct U3
 {
-  U3 () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
-  U3 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E {enum}' in initialization" "" { target c++14_down } }
+  U3 () : e { 5 } {}	// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
+  U3 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' {enum} in initialization" "" { target c++14_down } }
 			// { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
   U3 (float) : e({ 6 }) {}
   L e;
@@ -208,11 +208,11 @@  struct U3
 template <typename H, typename I, typename J, typename K>
 struct W3
 {
-  H a { 5 };		// { dg-error "invalid conversion from 'int' to 'A {enum}'" "" { target *-*-* } .-2 }
-  I b { 6 };		// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } .-3 }
-  J c { 3.0f };		// { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .-4 }
+  H a { 5 };		// { dg-error "invalid conversion from 'int' to 'A' {enum}" "" { target *-*-* } .-2 }
+  I b { 6 };		// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } .-3 }
+  J c { 3.0f };		// { dg-error "cannot convert \[^\n\r]* to 'C' {enum} in initialization" "" { target c++14_down } .-4 }
 			// { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-5 }
-  K d = { 7 };		// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-6 }
+  K d = { 7 };		// { dg-error "cannot convert \[^\n\r]* to 'D' {enum} in initialization" "" { target *-*-* } .-6 }
 };
 
 void
@@ -221,17 +221,17 @@  test ()
   foo2<0> ();
   U2<0> u20;
   U2<1> u21 (5);
-  W2<0> w2;		// { dg-error "invalid conversion from 'int' to 'A {enum}'" }
-			// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } .-1 }
-			// { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .-2 }
+  W2<0> w2;		// { dg-error "invalid conversion from 'int' to 'A' {enum}" }
+			// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } .-1 }
+			// { dg-error "cannot convert \[^\n\r]* to 'C' {enum} in initialization" "" { target c++14_down } .-2 }
 			// { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-3 }
-			// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-4 }
+			// { dg-error "cannot convert \[^\n\r]* to 'D' {enum} in initialization" "" { target *-*-* } .-4 }
   foo3<A, B, C, D, E, V> ();
   U3<E> u30;
   U3<E> u31 (5);
-  W3<A, B, C, D> w3;	// { dg-error "invalid conversion from 'int' to 'A {enum}'" }
-			// { dg-error "invalid conversion from 'int' to 'B {enum}'" "" { target c++14_down } .-1 }
-			// { dg-error "cannot convert \[^\n\r]* to 'C {enum}' in initialization" "" { target c++14_down } .-2 }
+  W3<A, B, C, D> w3;	// { dg-error "invalid conversion from 'int' to 'A' {enum}" }
+			// { dg-error "invalid conversion from 'int' to 'B' {enum}" "" { target c++14_down } .-1 }
+			// { dg-error "cannot convert \[^\n\r]* to 'C' {enum} in initialization" "" { target c++14_down } .-2 }
 			// { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-3 }
-			// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-4 }
+			// { dg-error "cannot convert \[^\n\r]* to 'D' {enum} in initialization" "" { target *-*-* } .-4 }
 }
diff --git a/gcc/testsuite/g++.dg/diagnostic/aka1.C b/gcc/testsuite/g++.dg/diagnostic/aka1.C
index 37f8df9..cb314fb 100644
--- a/gcc/testsuite/g++.dg/diagnostic/aka1.C
+++ b/gcc/testsuite/g++.dg/diagnostic/aka1.C
@@ -12,4 +12,4 @@  void A::f() {
 typedef A B;
 
 // We do want an aka for a real typedef.
-B b = 0;			// { dg-error "B .aka A." }
+B b = 0;			// { dg-error "'B' {aka 'A'}" }
diff --git a/gcc/testsuite/g++.dg/diagnostic/aka2.C b/gcc/testsuite/g++.dg/diagnostic/aka2.C
new file mode 100644
index 0000000..a43f9e3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/aka2.C
@@ -0,0 +1,32 @@ 
+/* Verify that the "aka" descriptions for typedefs are correctly
+   quoted (PR 62170).  */
+
+/* Exercise %H and %I.  */
+
+typedef struct s1 t1;
+typedef struct s2 {int i;} t2;
+
+int foo(t1 *);
+
+void test_1 () {
+  t2 pos;
+
+  foo (&pos); // { dg-error "cannot convert 't2\\*' {aka 's2\\*'} to 't1\\*' {aka 's1\\*'} for argument '1' to 'int foo\\(t1\\*\\)'" }
+}
+
+/* Exercise %T.  */
+
+typedef struct s3
+{  
+  void m3 ();
+} t3;
+
+void test_2 (const s3 *ptr)
+{
+  ptr->m3 (); // { dg-error "passing 'const s3' as 'this' argument discards qualifiers" }
+}
+
+void test_3 (const t3 *ptr)
+{
+  ptr->m3 (); // { dg-error "passing 'const t3' {aka 'const s3'} as 'this' argument discards qualifiers" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/error55.C b/gcc/testsuite/g++.dg/parse/error55.C
index 24cca50..70af85d 100644
--- a/gcc/testsuite/g++.dg/parse/error55.C
+++ b/gcc/testsuite/g++.dg/parse/error55.C
@@ -3,5 +3,5 @@ 
 class A { };
 typedef A B;
 void foo (B &a) {
-  a.x();  // { dg-error "'B {aka class A}' has no member named 'x'" }
+  a.x();  // { dg-error "'B' {aka 'class A'} has no member named 'x'" }
 }
diff --git a/gcc/testsuite/g++.dg/warn/pr12242.C b/gcc/testsuite/g++.dg/warn/pr12242.C
index e1cd780..2cb344b 100644
--- a/gcc/testsuite/g++.dg/warn/pr12242.C
+++ b/gcc/testsuite/g++.dg/warn/pr12242.C
@@ -10,14 +10,14 @@  void example ()
   X x;
   Y y;
   
-  x = 10;  // { dg-warning "invalid conversion from .int. to .X {enum}." "invalid" }
-           // { dg-warning "unspecified" "unspecified" { target *-*-* } .-1 }
-  x = 1;   // { dg-warning "invalid conversion from .int. to .X {enum}." }
-  x = C;   // { dg-error "cannot convert .Y {enum}. to .X {enum}. in assignment" }  
-  x = D;   // { dg-error "cannot convert .Y {enum}. to .X {enum}. in assignment" }  
-  y = A;   // { dg-error "cannot convert .X {enum}. to .Y {enum}. in assignment" }  
-  x = y;   // { dg-error "cannot convert .Y {enum}. to .X {enum}. in assignment" }  
-  x = i;   // { dg-warning "invalid conversion from .int. to .X {enum}."  }
+  x = 10;  // { dg-warning "invalid conversion from 'int' to 'X' {enum}" "invalid" }
+           // { dg-warning "unspecified" "unspecified" { target *-*-* } '-1 }
+  x = 1;   // { dg-warning "invalid conversion from 'int' to 'X' {enum}" }
+  x = C;   // { dg-error "cannot convert 'Y' {enum} to 'X' {enum} in assignment" }  
+  x = D;   // { dg-error "cannot convert 'Y' {enum} to 'X' {enum} in assignment" }  
+  y = A;   // { dg-error "cannot convert 'X' {enum} to 'Y' {enum} in assignment" }  
+  x = y;   // { dg-error "cannot convert 'Y' {enum} to 'X' {enum} in assignment" }  
+  x = i;   // { dg-warning "invalid conversion from 'int' to 'X' {enum}"  }
 }
 
 void foo () 
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/enum1.C b/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
index 2f7a6dd..82abb602e 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
@@ -8,4 +8,4 @@  struct Type {
   void setBTK();
 };
 
-void Type::setBTK() { kind = DTK; } // { dg-warning "conversion from '\[^\n\r]+' to .unsigned char:1. changes value from" }
+void Type::setBTK() { kind = DTK; } // { dg-warning "conversion from '\[^\n\r]+' {enum} to .unsigned char:1. changes value from" }
diff --git a/gcc/testsuite/gcc.dg/diag-aka-1.c b/gcc/testsuite/gcc.dg/diag-aka-1.c
index 87bc757..fde4ca7 100644
--- a/gcc/testsuite/gcc.dg/diag-aka-1.c
+++ b/gcc/testsuite/gcc.dg/diag-aka-1.c
@@ -10,7 +10,7 @@  typedef int IA[];
 typedef IA *IAP;
 extern IAP arr[];
 
-void fn1 (B *); /* { dg-message "expected .B \\* {aka struct A \\*}. but argument is of type .struct B \\*." } */
+void fn1 (B *); /* { dg-message "expected 'B \\*' {aka 'struct A \\*'} but argument is of type 'struct B \\*'" } */
 void fn2 (TFC *);
 
 void 
@@ -24,6 +24,6 @@  bar (B *b, int *i)
 int
 foo (void *a)
 {
-  T *t = a; /* { dg-warning "request for implicit conversion from .void \\*. to .T \\* {aka struct T \\*}. not" } */
+  T *t = a; /* { dg-warning "request for implicit conversion from 'void \\*' to 'T \\*' {aka 'struct T \\*'} not" } */
   return t->i;
 }
diff --git a/gcc/testsuite/gcc.dg/diag-aka-2.c b/gcc/testsuite/gcc.dg/diag-aka-2.c
new file mode 100644
index 0000000..a4b2242
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/diag-aka-2.c
@@ -0,0 +1,12 @@ 
+/* Verify that the "aka" descriptions for typedefs are correctly
+   quoted (PR 62170).  */
+
+typedef struct s1 t1;
+
+int foo(t1 *); /* { dg-message "expected 't1 \\*' {aka 'struct s1 \\*'} but argument is of type 't2 \\*' {aka 'struct s2 \\*'}" } */
+
+int bar() {
+  typedef struct s2 {int i;} t2;
+  t2 pos;
+  return foo(&pos); /* { dg-error "incompatible pointer type" } */
+}
diff --git a/gcc/testsuite/gcc.dg/pr13804-1.c b/gcc/testsuite/gcc.dg/pr13804-1.c
index 65b238a..5fc17f4 100644
--- a/gcc/testsuite/gcc.dg/pr13804-1.c
+++ b/gcc/testsuite/gcc.dg/pr13804-1.c
@@ -20,9 +20,9 @@  void
 f (void)
 {
   x0.c; /* { dg-error "'struct s0' has no member named 'c'" } */
-  x1.c; /* { dg-error "'S0 {aka struct s0}' has no member named 'c'" } */
+  x1.c; /* { dg-error "'S0' {aka 'struct s0'} has no member named 'c'" } */
   x2.c; /* { dg-error "'union u0' has no member named 'c'" } */
-  x3.c; /* { dg-error "'U0 {aka union u0}' has no member named 'c'" } */
+  x3.c; /* { dg-error "'U0' {aka 'union u0'} has no member named 'c'" } */
   x4->c; /* { dg-error "'struct s0' has no member named 'c'" } */
   x5->c; /* { dg-error "'union u0' has no member named 'c'" } */
 }
diff --git a/gcc/testsuite/gcc.dg/pr56980.c b/gcc/testsuite/gcc.dg/pr56980.c
index 27405ef..5303c61 100644
--- a/gcc/testsuite/gcc.dg/pr56980.c
+++ b/gcc/testsuite/gcc.dg/pr56980.c
@@ -5,12 +5,12 @@  typedef struct A { int i; } B;
 typedef union U { int i; } V;
 typedef enum E { G } F;
 
-void foo_s (struct A); /* { dg-message "expected .struct A. but argument is of type .B \\* {aka struct A \\*}." } */
-void foo_u (union U); /* { dg-message "expected .union U. but argument is of type .V \\* {aka union U \\*}." } */
-void foo_e (enum E); /* { dg-message "expected .enum E. but argument is of type .F \\* {aka enum E \\*}." } */
-void foo_sp (B *); /* { dg-message "expected .B \\* {aka struct A \\*}. but argument is of type .struct B \\*." } */
-void foo_up (V *); /* { dg-message "expected .V \\* {aka union U \\*}. but argument is of type .union V \\*." } */
-void foo_ep (F *); /* { dg-message "expected .F \\* {aka enum E \\*}. but argument is of type .enum F \\*." } */
+void foo_s (struct A); /* { dg-message "expected .struct A. but argument is of type 'B \\*' {aka 'struct A \\*'}" } */
+void foo_u (union U); /* { dg-message "expected .union U. but argument is of type 'V \\*' {aka 'union U \\*'}" } */
+void foo_e (enum E); /* { dg-message "expected .enum E. but argument is of type 'F \\*' {aka 'enum E \\*'}" } */
+void foo_sp (B *); /* { dg-message "expected 'B \\*' {aka 'struct A \\*'} but argument is of type .struct B \\*." } */
+void foo_up (V *); /* { dg-message "expected 'V \\*' {aka 'union U \\*'} but argument is of type .union V \\*." } */
+void foo_ep (F *); /* { dg-message "expected 'F \\*' {aka 'enum E \\*'} but argument is of type .enum F \\*." } */
 
 void 
 bar (B *b, V *v, F *f)
diff --git a/gcc/testsuite/gcc.dg/pr65050.c b/gcc/testsuite/gcc.dg/pr65050.c
index 0822a99..e29559d 100644
--- a/gcc/testsuite/gcc.dg/pr65050.c
+++ b/gcc/testsuite/gcc.dg/pr65050.c
@@ -2,9 +2,9 @@ 
 /* { dg-do compile } */
 
 typedef int A[];
-struct S { int i; A a[5]; } s; /* { dg-error "array type has incomplete element type .A {aka int\\\[\\\]}." } */
+struct S { int i; A a[5]; } s; /* { dg-error "array type has incomplete element type 'A' {aka 'int\\\[\\\]'}" } */
 extern void foo (int p[2][]); /* { dg-error "array type has incomplete element type .int\\\[\\\]." } */
-extern void bar (A p[2]); /* { dg-error "array type has incomplete element type .A {aka int\\\[\\\]}." } */
+extern void bar (A p[2]); /* { dg-error "array type has incomplete element type 'A' {aka 'int\\\[\\\]'}" } */
 
 void
 foo (int p[2][]) /* { dg-error "array type has incomplete element type .int\\\[\\\]." } */
@@ -12,7 +12,7 @@  foo (int p[2][]) /* { dg-error "array type has incomplete element type .int\\\[\
 }
 
 void
-bar (A p[2]) /* { dg-error "array type has incomplete element type .A {aka int\\\[\\\]}." } */
+bar (A p[2]) /* { dg-error "array type has incomplete element type 'A' {aka 'int\\\[\\\]'}" } */
 {
 }
 
@@ -20,4 +20,4 @@  struct T;
 struct T t[5]; /* { dg-error "array type has incomplete element type .struct T." } */
 struct U u[] = { { "abc" } }; /* { dg-error "array type has incomplete element type .struct U." } */
 typedef struct T TT;
-TT tt[5]; /* { dg-error "array type has incomplete element type .TT {aka struct T}." } */
+TT tt[5]; /* { dg-error "array type has incomplete element type 'TT' {aka 'struct T'}" } */
diff --git a/gcc/testsuite/gcc.dg/redecl-14.c b/gcc/testsuite/gcc.dg/redecl-14.c
index 97003c1..1bf1d96 100644
--- a/gcc/testsuite/gcc.dg/redecl-14.c
+++ b/gcc/testsuite/gcc.dg/redecl-14.c
@@ -18,5 +18,5 @@  f (void)
   }
   extern IAP a[];
   extern IAP a[5];
-  sizeof (*a[0]); /* { dg-error "invalid application of 'sizeof' to incomplete type 'IA {aka int\\\[\\\]}'" } */
+  sizeof (*a[0]); /* { dg-error "invalid application of 'sizeof' to incomplete type 'IA' {aka 'int\\\[\\\]'}" } */
 }
diff --git a/gcc/testsuite/gcc.dg/utf16-4.c b/gcc/testsuite/gcc.dg/utf16-4.c
index f9ebd61..f2d4388 100644
--- a/gcc/testsuite/gcc.dg/utf16-4.c
+++ b/gcc/testsuite/gcc.dg/utf16-4.c
@@ -12,7 +12,7 @@  char16_t	c2 = u'\U00064321';	/* { dg-warning "constant too long" } */
 char16_t	c3 = 'a';
 char16_t	c4 = U'a';
 char16_t	c5 = U'\u2029';
-char16_t	c6 = U'\U00064321';	/* { dg-warning "conversion from .unsigned int. to .char16_t {aka short unsigned int}. changes value from .410401. to .17185." } */
+char16_t	c6 = U'\U00064321';	/* { dg-warning "conversion from .unsigned int. to 'char16_t' {aka 'short unsigned int'} changes value from .410401. to .17185." } */
 char16_t	c7 = L'a';
 char16_t	c8 = L'\u2029';
 char16_t 	c9 = L'\U00064321';	/* { dg-warning "conversion" "" { target { 4byte_wchar_t } } } */
diff --git a/gcc/testsuite/gcc.target/i386/sse-vect-types.c b/gcc/testsuite/gcc.target/i386/sse-vect-types.c
index 9cb6f3e..ac4ece4 100644
--- a/gcc/testsuite/gcc.target/i386/sse-vect-types.c
+++ b/gcc/testsuite/gcc.target/i386/sse-vect-types.c
@@ -10,4 +10,4 @@  __m128d foo1(__m128d z, __m128d  a, int N) {
   }
   return a;
 }
-/* { dg-message "note: expected '\[^'\n\]*' but argument is of type '\[^'\n\]*'" "note: expected" { target *-*-* } 0 } */
+/* { dg-message "note: expected '.*'.* but argument is of type '.*'" "note: expected" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/obj-c++.dg/invalid-type-1.mm b/gcc/testsuite/obj-c++.dg/invalid-type-1.mm
index cb2138f..59c8666 100644
--- a/gcc/testsuite/obj-c++.dg/invalid-type-1.mm
+++ b/gcc/testsuite/obj-c++.dg/invalid-type-1.mm
@@ -18,8 +18,8 @@  id <MyProtocol> object; /* This is fine.  */
 
 AClass <MyProtocol> *object1; /* This is fine.  */
 
-Integer <MyProtocol> *object2; /* { dg-error ".Integer {aka int}. is not a template" } */
+Integer <MyProtocol> *object2; /* { dg-error "'Integer' {aka 'int'} is not a template" } */
 /* { dg-error ".MyProtocol. was not declared in this scope" "" { target *-*-* } .-1 } */
 
-Integer <NonExistingProtocol> *object3; /* { dg-error ".Integer {aka int}. is not a template" } */
+Integer <NonExistingProtocol> *object3; /* { dg-error "'Integer' {aka 'int'} is not a template" } */
 /* { dg-error ".NonExistingProtocol. was not declared in this scope" "" { target *-*-* } .-1 } */
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 52b7e7f..5f3295f 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -245,7 +245,7 @@  virt_loc_aware_diagnostic_finalizer (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 *, const char **)
 {
   tree t;
 
diff --git a/gcc/tree-diagnostic.h b/gcc/tree-diagnostic.h
index 85aa980..e38bb44 100644
--- a/gcc/tree-diagnostic.h
+++ b/gcc/tree-diagnostic.h
@@ -55,6 +55,6 @@  void virt_loc_aware_diagnostic_finalizer (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 *, const char **);
 
 #endif /* ! GCC_TREE_DIAGNOSTIC_H */