public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
@ 2017-06-05 18:29 David Malcolm
  2017-06-06 10:57 ` Marek Polacek
  2017-06-20 15:51 ` [PING] C++ " David Malcolm
  0 siblings, 2 replies; 13+ messages in thread
From: David Malcolm @ 2017-06-05 18:29 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

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);		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);
+}
+
 \f
 /* 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 */
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-05 18:29 [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170) David Malcolm
@ 2017-06-06 10:57 ` Marek Polacek
  2017-06-20 15:51 ` [PING] C++ " David Malcolm
  1 sibling, 0 replies; 13+ messages in thread
From: Marek Polacek @ 2017-06-06 10:57 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PING] C++ Re: [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-05 18:29 [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170) David Malcolm
  2017-06-06 10:57 ` Marek Polacek
@ 2017-06-20 15:51 ` David Malcolm
  2017-06-20 17:59   ` Jason Merrill
  1 sibling, 1 reply; 13+ messages in thread
From: David Malcolm @ 2017-06-20 15:51 UTC (permalink / raw)
  To: gcc-patches

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);
> +}
> +
>  \f
>  /* 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 */

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PING] C++ Re: [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-20 15:51 ` [PING] C++ " David Malcolm
@ 2017-06-20 17:59   ` Jason Merrill
  2017-06-20 18:01     ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2017-06-20 17:59 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches List

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PING] C++ Re: [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-20 17:59   ` Jason Merrill
@ 2017-06-20 18:01     ` Jason Merrill
  2017-06-20 19:06       ` David Malcolm
  0 siblings, 1 reply; 13+ messages in thread
From: Jason Merrill @ 2017-06-20 18:01 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches List

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PING] C++ Re: [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-20 18:01     ` Jason Merrill
@ 2017-06-20 19:06       ` David Malcolm
  2017-06-20 19:12         ` Jason Merrill
  0 siblings, 1 reply; 13+ messages in thread
From: David Malcolm @ 2017-06-20 19:06 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List, Volker Reichelt

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PING] C++ Re: [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-20 19:06       ` David Malcolm
@ 2017-06-20 19:12         ` Jason Merrill
  2017-06-21  7:59           ` Volker Reichelt
  2017-06-21 13:59           ` [PATCH] v3: " David Malcolm
  0 siblings, 2 replies; 13+ messages in thread
From: Jason Merrill @ 2017-06-20 19:12 UTC (permalink / raw)
  To: David Malcolm; +Cc: gcc-patches List, Volker Reichelt

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PING] C++ Re: [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-20 19:12         ` Jason Merrill
@ 2017-06-21  7:59           ` Volker Reichelt
  2017-07-14 16:24             ` Martin Sebor
  2017-06-21 13:59           ` [PATCH] v3: " David Malcolm
  1 sibling, 1 reply; 13+ messages in thread
From: Volker Reichelt @ 2017-06-21  7:59 UTC (permalink / raw)
  To: Jason Merrill; +Cc: David Malcolm, gcc-patches List

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH] v3: C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-20 19:12         ` Jason Merrill
  2017-06-21  7:59           ` Volker Reichelt
@ 2017-06-21 13:59           ` David Malcolm
  2017-07-14 15:47             ` [PING] " David Malcolm
  2017-11-22 20:57             ` [committed] v5: " David Malcolm
  1 sibling, 2 replies; 13+ messages in thread
From: David Malcolm @ 2017-06-21 13:59 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List, Volker Reichelt, David Malcolm

On Tue, 2017-06-20 at 15:11 -0400, 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.

It turns out that the resizing calculation in the above line is
wrong, but I managed not to expose my mistake in the light testing
I did before posting the above.  Oops.

Thankfully the issue showed up in g++.dg/other/error23.C when I
ran the full test suite.

Sorry about that.

I've updated the shrinking calculation to look like this:

	  int delta = type_start + type_len - obstack_object_size (ob);
	  gcc_assert (delta <= 0);
	  obstack_blank_fast (ob, delta);

and with that, it successfully bootstrapped & regression-tested on
x86_64-pc-linux-gnu.

OK for trunk?

Full patch follows, for reference:

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                                 |  94 ++++++++--
 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, 314 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 e53afa7..4400d3f 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.  */
@@ -3139,8 +3139,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)
@@ -3148,7 +3168,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
@@ -3157,21 +3189,44 @@ 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".  */
+	  int delta = type_start + type_len - obstack_object_size (ob);
+	  gcc_assert (delta <= 0);
+	  obstack_blank_fast (ob, delta);
+	}
+      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)
@@ -3640,7 +3695,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);
 }
@@ -3932,8 +3987,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)
@@ -4006,7 +4063,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
@@ -4049,7 +4106,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;
 
@@ -4060,14 +4122,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);
+}
+
 \f
 /* 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 e2f115e..4b20387 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 .(long )?unsigned int. to .char16_t {aka short unsigned int}. changes value from .410401. to .17185." } */
+char16_t	c6 = U'\U00064321';	/* { dg-warning "conversion from .(long )?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 */
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PING] [PATCH] v3: C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-21 13:59           ` [PATCH] v3: " David Malcolm
@ 2017-07-14 15:47             ` David Malcolm
  2017-11-22 20:57             ` [committed] v5: " David Malcolm
  1 sibling, 0 replies; 13+ messages in thread
From: David Malcolm @ 2017-07-14 15:47 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List, Volker Reichelt

Jason, is this updated version of the patch OK?

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

Thanks
Dave

On Wed, 2017-06-21 at 10:32 -0400, David Malcolm wrote:
> On Tue, 2017-06-20 at 15:11 -0400, 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.
> 
> It turns out that the resizing calculation in the above line is
> wrong, but I managed not to expose my mistake in the light testing
> I did before posting the above.  Oops.
> 
> Thankfully the issue showed up in g++.dg/other/error23.C when I
> ran the full test suite.
> 
> Sorry about that.
> 
> I've updated the shrinking calculation to look like this:
> 
> 	  int delta = type_start + type_len - obstack_object_size (ob);
> 	  gcc_assert (delta <= 0);
> 	  obstack_blank_fast (ob, delta);
> 
> and with that, it successfully bootstrapped & regression-tested on
> x86_64-pc-linux-gnu.
> 
> OK for trunk?
> 
> Full patch follows, for reference:
> 
> 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                                 |  94 ++++++++--
>  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, 314 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 e53afa7..4400d3f 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.  */
> @@ -3139,8 +3139,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)
> @@ -3148,7 +3168,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
> @@ -3157,21 +3189,44 @@ 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".  */
> +	  int delta = type_start + type_len - obstack_object_size
> (ob);
> +	  gcc_assert (delta <= 0);
> +	  obstack_blank_fast (ob, delta);
> +	}
> +      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)
> @@ -3640,7 +3695,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);
>  }
> @@ -3932,8 +3987,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)
> @@ -4006,7 +4063,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
> @@ -4049,7 +4106,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;
>  
> @@ -4060,14 +4122,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);
> +}
> +
>  \f
>  /* 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 e2f115e..4b20387 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 .(long )?unsigned int. to .char16_t {aka short
> unsigned int}. changes value from .410401. to .17185." } */
> +char16_t	c6 = U'\U00064321';	/* { dg-warning
> "conversion from .(long )?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 */

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PING] C++ Re: [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-21  7:59           ` Volker Reichelt
@ 2017-07-14 16:24             ` Martin Sebor
  2017-07-16 10:02               ` Volker Reichelt
  0 siblings, 1 reply; 13+ messages in thread
From: Martin Sebor @ 2017-07-14 16:24 UTC (permalink / raw)
  To: Volker Reichelt, Jason Merrill; +Cc: David Malcolm, gcc-patches List

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

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PING] C++ Re: [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-07-14 16:24             ` Martin Sebor
@ 2017-07-16 10:02               ` Volker Reichelt
  0 siblings, 0 replies; 13+ messages in thread
From: Volker Reichelt @ 2017-07-16 10:02 UTC (permalink / raw)
  To: Martin Sebor, gcc-patches List
  Cc: Jason Merrill, David Malcolm, Gerald Pfeifer

On 14 Jul, Martin Sebor wrote:
> 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

After several pings

https://gcc.gnu.org/ml/gcc-patches/2017-05/msg01248.html
https://gcc.gnu.org/ml/gcc-patches/2017-06/msg00207.html
https://gcc.gnu.org/ml/gcc-patches/2017-06/msg00712.html  (by Gerald)
https://gcc.gnu.org/ml/gcc-patches/2017-06/msg01487.html  (by Martin)
https://gcc.gnu.org/ml/gcc-patches/2017-07/msg00472.html  (by Martin)

(thanks Gerald and Martin!) for

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

I went with Martin's suggestion and took Jason's 'make sense' as an OK
for this trivial patch. Due to changes of an error message and a
testcase the patch had to be updated slightly (attached below)

Bootstrapped and regtested again on x86_64-pc-linux-gnu.
Applied to trunk.

Regards,
Volker


2017-07-16  Volker Reichelt  <v.reichelt@netcologne.de>

	* parser.c (cp_parser_cast_expression): Use %q#T instead of %qT
	in old-style cast diagnostic.
	* typeck.c (maybe_warn_about_useless_cast): Use %q#T instead of %qT
	in useless cast diagnostic.
	* error.c (type_to_string): Remove enum special handling.

Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 250230)
+++ gcc/cp/parser.c	(working copy)
@@ -8890,7 +8890,7 @@
 		  maybe_add_cast_fixit (&rich_loc, open_paren_loc, close_paren_loc,
 					expr, type);
 		  warning_at_rich_loc (&rich_loc, OPT_Wold_style_cast,
-				       "use of old-style cast to %qT", type);
+				       "use of old-style cast to %q#T", type);
 		}
 
 	      /* Only type conversions to integral or enumeration types
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 250230)
+++ gcc/cp/typeck.c	(working copy)
@@ -6681,7 +6681,7 @@
 	       ? xvalue_p (expr) : lvalue_p (expr))
 	   && same_type_p (TREE_TYPE (expr), TREE_TYPE (type)))
 	  || same_type_p (TREE_TYPE (expr), type))
-	warning (OPT_Wuseless_cast, "useless cast to type %qT", type);
+	warning (OPT_Wuseless_cast, "useless cast to type %q#T", type);
     }
 }
 
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(revision 250230)
+++ gcc/cp/error.c	(working copy)
@@ -3172,10 +3172,6 @@
       if (len == aka_len && memcmp (p, p+aka_start, len) == 0)
 	p[len] = '\0';
     }
-
-  if (typ && TYPE_P (typ) && TREE_CODE (typ) == ENUMERAL_TYPE)
-    pp_string (cxx_pp, M_(" {enum}"));
-
   return pp_ggc_formatted_text (cxx_pp);
 }
 
===================================================================

2017-07-16  Volker Reichelt  <v.reichelt@netcologne.de>

	* g++.dg/cpp1z/direct-enum-init1.C: Revert special enum handling.
	* g++.dg/warn/pr12242.C: Likewise.

Index: gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
===================================================================
--- gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C	(revision 250230)
+++ gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C	(working copy)
@@ -17,67 +17,67 @@
 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'" }
+  B b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B'" "" { 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'" }
+  D d2 { t };		// { dg-error "cannot convert 'T' to 'D' in initialization" "" { target c++14_down } }
+			// { dg-error "invalid cast from type 'T' to type 'D'" "" { target c++1z } .-1 }
+  D d3 { 9 };		// { dg-error "cannot convert 'int' to 'D' in initialization" "" { target c++14_down } }
+  D d4 { l };		// { dg-error "cannot convert 'long int' to 'D' 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' to 'D' in initialization" "" { target c++14_down } }
+  E e1 { 5 };		// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  E e2 { -1 };		// { dg-error "cannot convert 'int' to 'E' 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' 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' 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'" }
+  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to 'C' 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' in initialization" "" { target c++14_down } }
+  E *e5 = new E { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E' 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' for argument" }
+  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  V v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E'" }
+  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  V v3 = { E { 5.0 } };	// { dg-error "cannot convert 'double' to 'E' 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' in initialization" }
+  if (B b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B'" "" { 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' 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' in initialization" "" { target c++14_down } }
+  B b4 {short (c + 5)};	// { dg-error "invalid conversion from 'short int' to 'B'" "" { target c++14_down } }
+  B b5 {c + 5};		// { dg-error "invalid conversion from 'int' to 'B'" "" { 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' 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' in initialization" "" { target c++14_down } }
+  C c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C' 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' in initialization" "" { target c++14_down } }
+  U (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' 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' 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'" }
+  B b { 6 };		// { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+  C c { 3.0f };		// { dg-error "cannot convert \[^\n\r]* to 'C' 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' in initialization" }
 };
 
 template <int N>
@@ -84,54 +84,54 @@
 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'" }
+  B b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B'" "" { 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'" }
+  D d2 { t };		// { dg-error "cannot convert 'T' to 'D' in initialization" "" { target c++14_down } }
+			// { dg-error "invalid cast from type 'T' to type 'D'" "" { target c++1z } .-1 }
+  D d3 { 9 };		// { dg-error "cannot convert 'int' to 'D' in initialization" "" { target c++14_down } }
+  D d4 { l };		// { dg-error "cannot convert 'long int' to 'D' 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' to 'D' in initialization" "" { target c++14_down } }
+  E e1 { 5 };		// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  E e2 { -1 };		// { dg-error "cannot convert 'int' to 'E' 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' 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' 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'" }
+  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
+  D *d7 = new D { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
+  E *e5 = new E { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E' 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' for argument" }
+  bar (E { 9 });	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  V v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E'" }
+  V v2 = { E { 12 } };	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  V v3 = { E { 5.0 } };	// { dg-error "cannot convert 'double' to 'E' 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' in initialization" }
+  if (B b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B'" "" { 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' 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' in initialization" "" { target c++14_down } }
+  B b4 {short (c + 5)};	// { dg-error "invalid conversion from 'short int' to 'B'" "" { target c++14_down } }
+  B b5 {c + 5};		// { dg-error "invalid conversion from 'int' to 'B'" "" { 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' 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' in initialization" "" { target c++14_down } }
+  C c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C' 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' in initialization" "" { target c++14_down } }
+  U2 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' 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 @@
 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'" "" { target *-*-* } .-2 }
+  B b { 6 };		// { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-3 }
+  C c { 3.0f };		// { dg-error "cannot convert \[^\n\r]* to 'C' 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' in initialization" "" { target *-*-* } .-6 }
 };
 
 template <typename H, typename I, typename J, typename K, typename L, typename M>
@@ -152,54 +152,54 @@
 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'" }
+  I b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B'" "" { 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'" }
+  K d2 { t };		// { dg-error "cannot convert 'T' to 'D' in initialization" "" { target c++14_down } }
+			// { dg-error "invalid cast from type 'T' to type 'D'" "" { target c++1z } .-1 }
+  K d3 { 9 };		// { dg-error "cannot convert 'int' to 'D' in initialization" "" { target c++14_down } }
+  K d4 { l };		// { dg-error "cannot convert 'long int' to 'D' 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' to 'D' in initialization" "" { target c++14_down } }
+  L e1 { 5 };		// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  L e2 { -1 };		// { dg-error "cannot convert 'int' to 'E' 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' 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' 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'" }
+  J c2 = { J { 8 } };	// { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
+  K *d7 = new K { 9 };	// { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
+  L *e5 = new L { -4 };	// { dg-error "cannot convert \[^\n\r]* to 'E' 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' for argument" }
+  bar3 (E { 9 });	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  M v1 = { { 11 } };	// { dg-error "braces around scalar initializer for type 'E'" }
+  M v2 = { L { 12 } };	// { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  M v3 = { L { 5.0 } };	// { dg-error "cannot convert 'double' to 'E' 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' in initialization" }
+  if (I b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B'" "" { 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' 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' in initialization" "" { target c++14_down } }
+  I b4 {short (c + 5)};	// { dg-error "invalid conversion from 'short int' to 'B'" "" { target c++14_down } }
+  I b5 {c + 5};		// { dg-error "invalid conversion from 'int' to 'B'" "" { 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' 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' in initialization" "" { target c++14_down } }
+  J c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C' 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' in initialization" "" { target c++14_down } }
+  U3 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' 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 @@
 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'" "" { target *-*-* } .-2 }
+  I b { 6 };		// { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-3 }
+  J c { 3.0f };		// { dg-error "cannot convert \[^\n\r]* to 'C' 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' in initialization" "" { target *-*-* } .-6 }
 };
 
 void
@@ -221,17 +221,17 @@
   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'" }
+			// { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-1 }
+			// { dg-error "cannot convert \[^\n\r]* to 'C' 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' 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'" }
+			// { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-1 }
+			// { dg-error "cannot convert \[^\n\r]* to 'C' 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' in initialization" "" { target *-*-* } .-4 }
 }
Index: gcc/testsuite/g++.dg/warn/pr12242.C
===================================================================
--- gcc/testsuite/g++.dg/warn/pr12242.C	(revision 250230)
+++ gcc/testsuite/g++.dg/warn/pr12242.C	(working copy)
@@ -10,14 +10,14 @@
   X x;
   Y y;
   
-  x = 10;  // { dg-warning "invalid conversion from .int. to .X {enum}." "invalid" }
+  x = 10;  // { dg-warning "invalid conversion from .int. to .X." "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 = 1;   // { dg-warning "invalid conversion from .int. to .X." }
+  x = C;   // { dg-error "cannot convert .Y. to .X. in assignment" }  
+  x = D;   // { dg-error "cannot convert .Y. to .X. in assignment" }  
+  y = A;   // { dg-error "cannot convert .X. to .Y. in assignment" }  
+  x = y;   // { dg-error "cannot convert .Y. to .X. in assignment" }  
+  x = i;   // { dg-warning "invalid conversion from .int. to .X."  }
 }
 
 void foo () 
===================================================================

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [committed] v5: C/C++: fix quoting of "aka" typedef information (PR 62170)
  2017-06-21 13:59           ` [PATCH] v3: " David Malcolm
  2017-07-14 15:47             ` [PING] " David Malcolm
@ 2017-11-22 20:57             ` David Malcolm
  1 sibling, 0 replies; 13+ messages in thread
From: David Malcolm @ 2017-11-22 20:57 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches List, Volker Reichelt, David Malcolm

Looks like this got dropped on the floor back in June.

Jason approved an earlier version of this, so I've gone ahead and
updated it, and committed it to trunk.

Here's the version I've committed to trunk (as r255076), having verified
bootstrap&regrtest (on x86_64-pc-linux-gnu).

Changed in v5:
  * testsuite fixups

Changed in v4:
  * update for removal of " {enum}" in r250231

Changed in v3:
  * use correct size for obstack_blank_fast

Changed in v2:
  * cp/error.c: type_to_string: use obstack_blank_fast rather
    than directly manipulating ob->next_free

Blurb from v1:

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: we print:

  '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
added by the 'q' handling within pp_format.

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 the 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).

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/diagnostic/aka1.C: Update expected error messages to
	reflect fixes to quoting.
	* g++.dg/diagnostic/aka2.C: New test case.
	* g++.dg/parse/error55.C: Update expected error messages to
	reflect fixes to quoting.
	* 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.
	* objc.dg/proto-lossage-4.m: Likewise.
---
 gcc/c/c-objc-common.c                          | 12 +++-
 gcc/cp/error.c                                 | 99 +++++++++++++++++++++-----
 gcc/fortran/error.c                            |  2 +-
 gcc/pretty-print.c                             | 37 +++++++---
 gcc/pretty-print.h                             |  5 +-
 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/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/testsuite/objc.dg/proto-lossage-4.m        |  6 +-
 gcc/tree-diagnostic.c                          |  2 +-
 gcc/tree-diagnostic.h                          |  2 +-
 20 files changed, 194 insertions(+), 57 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 8f4d3eb..6d923eb 100644
--- a/gcc/c/c-objc-common.c
+++ b/gcc/c/c-objc-common.c
@@ -29,7 +29,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)
@@ -79,7 +79,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;
@@ -166,12 +166,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 6d1f3da..a47822a 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	(bool, 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.  */
@@ -3144,8 +3144,28 @@ op_to_string (bool assop, 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)
@@ -3153,7 +3173,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
@@ -3162,21 +3194,44 @@ 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".  */
+	  int delta = type_start + type_len - obstack_object_size (ob);
+	  gcc_assert (delta <= 0);
+	  obstack_blank_fast (ob, delta);
+	}
+      else
+	if (quote)
+	  /* No further closing quotes are needed.  */
+	  *quote = false;
+    }
+
+  if (quote && *quote)
+    {
+      pp_end_quote (cxx_pp, show_color);
+      *quote = false;
     }
   return pp_ggc_formatted_text (cxx_pp);
 }
@@ -3634,7 +3689,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);
 }
@@ -3924,10 +3979,13 @@ cxx_format_postprocessor::handle (pretty_printer *pp)
 	}
       else
 	{
-	  /* 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);
+	  /* If the types were not comparable (or if only one of %H/%I was
+	     provided), they are printed normally, and no difference tree
+	     is printed.  */
+	  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)
@@ -4000,7 +4058,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
@@ -4043,7 +4101,12 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
     case 'P': result = parm_to_string (next_int);		break;
     case 'Q': result = op_to_string (true, 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;
 
@@ -4059,14 +4122,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 e66d898..1fbd2fe 100644
--- a/gcc/pretty-print.c
+++ b/gcc/pretty-print.c
@@ -1209,10 +1209,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)
 	{
@@ -1345,19 +1342,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 *);
@@ -1731,6 +1730,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);
+}
+
 \f
 /* 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 98296b1..9f6e2bb 100644
--- a/gcc/pretty-print.h
+++ b/gcc/pretty-print.h
@@ -179,7 +179,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
@@ -386,6 +386,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/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/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 e2f115e..4b20387 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 .(long )?unsigned int. to .char16_t {aka short unsigned int}. changes value from .410401. to .17185." } */
+char16_t	c6 = U'\U00064321';	/* { dg-warning "conversion from .(long )?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/testsuite/objc.dg/proto-lossage-4.m b/gcc/testsuite/objc.dg/proto-lossage-4.m
index c9c80b7..182e92d 100644
--- a/gcc/testsuite/objc.dg/proto-lossage-4.m
+++ b/gcc/testsuite/objc.dg/proto-lossage-4.m
@@ -28,13 +28,13 @@ long foo(void) {
   receiver += [receiver anotherValue]; /* { dg-warning "invalid receiver type .intptr_t." } */
 
   receiver += [(Obj *)receiver someValue]; /* { dg-warning ".Obj. may not respond to .\\-someValue." } */
-/* { dg-warning "assignment to 'intptr_t {aka (long )?int}' from 'id' makes integer from pointer without a cast" "" { target *-*-* } .-1 } */
+/* { dg-warning "assignment to 'intptr_t' {aka '(long )?int'} from 'id' makes integer from pointer without a cast" "" { target *-*-* } .-1 } */
 
   receiver += [(Obj *)receiver anotherValue];
   receiver += [(Obj <Proto> *)receiver someValue];
   receiver += [(Obj <Proto> *)receiver anotherValue];
   receiver += [objrcvr someValue]; /* { dg-warning ".Obj. may not respond to .\\-someValue." } */
-/* { dg-warning "assignment to 'intptr_t {aka (long )?int}' from 'id' makes integer from pointer without a cast" "" { target *-*-* } .-1 } */
+/* { dg-warning "assignment to 'intptr_t' {aka '(long )?int'} from 'id' makes integer from pointer without a cast" "" { target *-*-* } .-1 } */
 
   receiver += [objrcvr anotherValue];
   receiver += [(Obj <Proto> *)objrcvr someValue];
@@ -42,7 +42,7 @@ long foo(void) {
   receiver += [objrcvr2 someValue];
   receiver += [objrcvr2 anotherValue];
   receiver += [(Obj *)objrcvr2 someValue]; /* { dg-warning ".Obj. may not respond to .\\-someValue." } */
-/* { dg-warning "assignment to 'intptr_t {aka (long )?int}' from 'id' makes integer from pointer without a cast" "" { target *-*-* } .-1 } */
+/* { dg-warning "assignment to 'intptr_t' {aka '(long )?int'} from 'id' makes integer from pointer without a cast" "" { target *-*-* } .-1 } */
 
   receiver += [(Obj *)objrcvr2 anotherValue];
 
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 023e896..c80ae54 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -246,7 +246,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 */
-- 
1.8.5.3

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2017-11-22 20:44 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-05 18:29 [PATCH] C/C++: fix quoting of "aka" typedef information (PR 62170) David Malcolm
2017-06-06 10:57 ` Marek Polacek
2017-06-20 15:51 ` [PING] C++ " David Malcolm
2017-06-20 17:59   ` Jason Merrill
2017-06-20 18:01     ` Jason Merrill
2017-06-20 19:06       ` David Malcolm
2017-06-20 19:12         ` Jason Merrill
2017-06-21  7:59           ` Volker Reichelt
2017-07-14 16:24             ` Martin Sebor
2017-07-16 10:02               ` Volker Reichelt
2017-06-21 13:59           ` [PATCH] v3: " David Malcolm
2017-07-14 15:47             ` [PING] " David Malcolm
2017-11-22 20:57             ` [committed] v5: " David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).