public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Improved diagnostics for casts and enums
@ 2017-04-27  8:00 Volker Reichelt
  2017-04-27 12:37 ` Nathan Sidwell
  2017-04-27 16:59 ` [PATCH] Improved diagnostics for casts and enums Martin Sebor
  0 siblings, 2 replies; 15+ messages in thread
From: Volker Reichelt @ 2017-04-27  8:00 UTC (permalink / raw)
  To: gcc-patches

Hi,

the following two patches aim at improving GCC's diagnostics to help
the user to get rid of old-style casts. While old-style pointer casts
are really bad and need to be weeded out quickly, old-style casts between
arithmetic types are IMHO much more tolerable. The patches allow to
easily distinguish between those situations.

The first patch for cp_parser_cast_expression in parser.c just adds
the target type of the cast to the diagnostic (like in
maybe_warn_about_useless_cast in typeck.c).

The second patch for type_to_string in error.c tackles the problem
that the name of a type doesn't tell you if you have a class or just
a simple enum. Similar to adding "{aka 'int'}" to types that
are essentially integers, this patch adds "{enum}" to all
enumeration types (and adjusts two testcases accordingly).

Bootstrapped and regtested on x86_64-pc-linux-gnu.

OK for trunk (as two patches or as one)?

Regards,
Volker


2017-04-27  Volker Reichelt  <v.reichelt@netcologne.de>

	* parser.c (cp_parser_cast_expression): Add target type of cast to
	diagnostic.

Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 247283)
+++ gcc/cp/parser.c	(working copy)
@@ -8763,7 +8763,8 @@
 		  && !in_system_header_at (input_location)
 		  && !VOID_TYPE_P (type)
 		  && current_lang_name != lang_name_c)
-		warning (OPT_Wold_style_cast, "use of old-style cast");
+		warning (OPT_Wold_style_cast,
+			 "use of old-style cast to %qT", type);
 
 	      /* Only type conversions to integral or enumeration types
 		 can be used in constant-expressions.  */
===================================================================

2017-04-27  Volker Reichelt  <v.reichelt@netcologne.de>

	* error.c (type_to_string): Add '{enum}' suffix to enumeration types.

Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(revision 247283)
+++ gcc/cp/error.c	(working copy)
@@ -3134,6 +3134,10 @@
       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-04-27  Volker Reichelt  <v.reichelt@netcologne.de>

	* g++.dg/cpp1z/direct-enum-init1.C: Adjust for more verbose enum
	diagnostics.
	* 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 247283)
+++ 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'" }
-  B b1 { 7 };		// { dg-error "invalid conversion from 'int' to 'B'" "" { 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'" }
-  D d2 { t };		// { dg-error "cannot convert 'T' to 'D' 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'" "" { 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 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' 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 } }
+  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' 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' 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'" }
-  C c2 = { C { 8 } };	// { dg-error "cannot convert 'int' to 'C' 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' 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 } }
+  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' 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 } }
+  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' in initialization" }
-  if (B b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B'" "" { 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' 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' 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 } }
+  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' 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' in initialization" "" { target c++14_down } }
-  C c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C' 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' 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 } }
+  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' 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'" }
-  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 } }
+  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' in initialization" }
+  D d = { 7 };		// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" }
 };
 
 template <int N>
@@ -84,54 +84,54 @@
 void
 foo2 ()
 {
-  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 } }
+  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'" }
-  D d2 { t };		// { dg-error "cannot convert 'T' to 'D' 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'" "" { 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 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' 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 } }
+  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' 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' 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'" }
-  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 } }
+  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' 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 } }
+  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' in initialization" }
-  if (B b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B'" "" { 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' 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' 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 } }
+  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' 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' in initialization" "" { target c++14_down } }
-  C c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C' 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' 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 } }
+  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 @@
 template <int N>
 struct W2
 {
-  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 }
+  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' 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 @@
 foo3 ()
 {
   void bar3 (L);
-  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 } }
+  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'" }
-  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 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' 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 } }
+  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' 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' 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'" }
-  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 } }
+  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' 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 } }
+  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' in initialization" }
-  if (I b3 { 5 })	// { dg-error "invalid conversion from 'int' to 'B'" "" { 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' 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' 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 } }
+  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' 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' in initialization" "" { target c++14_down } }
-  J c6 {c + 5};		// { dg-error "cannot convert 'int' to 'C' 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' 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 } }
+  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 @@
 template <typename H, typename I, typename J, typename K>
 struct W3
 {
-  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 }
+  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' 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 @@
   foo2<0> ();
   U2<0> u20;
   U2<1> u21 (5);
-  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 }
+  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' 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'" }
-			// { 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 }
+  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' in initialization" "" { target *-*-* } .-4 }
+			// { dg-error "cannot convert \[^\n\r]* to 'D {enum}' in initialization" "" { target *-*-* } .-4 }
 }
Index: gcc/testsuite/g++.dg/warn/pr12242.C
===================================================================
--- gcc/testsuite/g++.dg/warn/pr12242.C	(revision 247283)
+++ 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." "invalid" }
+  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." }
-  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."  }
+  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 () 
===================================================================

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

* Re: [PATCH] Improved diagnostics for casts and enums
  2017-04-27  8:00 [PATCH] Improved diagnostics for casts and enums Volker Reichelt
@ 2017-04-27 12:37 ` Nathan Sidwell
  2017-04-27 20:58   ` [PATCH] C++: Add fix-it hints for -Wold-style-cast David Malcolm
  2017-04-27 16:59 ` [PATCH] Improved diagnostics for casts and enums Martin Sebor
  1 sibling, 1 reply; 15+ messages in thread
From: Nathan Sidwell @ 2017-04-27 12:37 UTC (permalink / raw)
  To: Volker Reichelt, gcc-patches

On 04/27/2017 03:29 AM, Volker Reichelt wrote:
> Hi,
> 
> the following two patches aim at improving GCC's diagnostics to help
> the user to get rid of old-style casts. While old-style pointer casts
> are really bad and need to be weeded out quickly, old-style casts between
> arithmetic types are IMHO much more tolerable. The patches allow to
> easily distinguish between those situations.
> 
> The first patch for cp_parser_cast_expression in parser.c just adds
> the target type of the cast to the diagnostic (like in
> maybe_warn_about_useless_cast in typeck.c).
> 
> The second patch for type_to_string in error.c tackles the problem
> that the name of a type doesn't tell you if you have a class or just
> a simple enum. Similar to adding "{aka 'int'}" to types that
> are essentially integers, this patch adds "{enum}" to all
> enumeration types (and adjusts two testcases accordingly).
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu.
> 
> OK for trunk (as two patches or as one)?

ok.  One commit is fine.

nathan

-- 
Nathan Sidwell

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

* Re: [PATCH] Improved diagnostics for casts and enums
  2017-04-27  8:00 [PATCH] Improved diagnostics for casts and enums Volker Reichelt
  2017-04-27 12:37 ` Nathan Sidwell
@ 2017-04-27 16:59 ` Martin Sebor
  2017-04-28  8:42   ` Volker Reichelt
  1 sibling, 1 reply; 15+ messages in thread
From: Martin Sebor @ 2017-04-27 16:59 UTC (permalink / raw)
  To: Volker Reichelt, gcc-patches

On 04/27/2017 01:29 AM, Volker Reichelt wrote:
> Hi,
>
> the following two patches aim at improving GCC's diagnostics to help
> the user to get rid of old-style casts. While old-style pointer casts
> are really bad and need to be weeded out quickly, old-style casts between
> arithmetic types are IMHO much more tolerable. The patches allow to
> easily distinguish between those situations.

FWIW, it can be most helpful to include this sort of detail (and
similar) in diagnostics.  In the case of the C-style cast, besides
mentioning the type of the result, it might be even more helpful
to mention the type of the operand because unlike that of the
result, its type is not apparent from the cast itself.

>
> The first patch for cp_parser_cast_expression in parser.c just adds
> the target type of the cast to the diagnostic (like in
> maybe_warn_about_useless_cast in typeck.c).
>
> The second patch for type_to_string in error.c tackles the problem
> that the name of a type doesn't tell you if you have a class or just
> a simple enum. Similar to adding "{aka 'int'}" to types that
> are essentially integers, this patch adds "{enum}" to all
> enumeration types (and adjusts two testcases accordingly).

In the C front end %qT prints 'enum E' for an argument of
an enumerated type.  Is there some significance to having
the C++ front end print 'E { enum }' or can C++ be made
consistent?

Martin

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

* [PATCH] C++: Add fix-it hints for -Wold-style-cast
  2017-04-27 12:37 ` Nathan Sidwell
@ 2017-04-27 20:58   ` David Malcolm
  2017-04-27 21:05     ` Florian Weimer
  2017-04-27 22:05     ` Marek Polacek
  0 siblings, 2 replies; 15+ messages in thread
From: David Malcolm @ 2017-04-27 20:58 UTC (permalink / raw)
  To: Nathan Sidwell, Volker Reichelt, gcc-patches; +Cc: David Malcolm

Volker's patch for -Wold-style-cast inspired me to add a fix-it hint
for when this warning fires, which converts the C-style cast to
a C++-style cast.

It tries to find a legal C++-style cast, trying them in the order:
const_cast, static_cast, reinterpret_cast.  It doesn't try
dynamic_cast.  It calls into the parser's logic for building such
casts, to see they are indeed valid; it doesn't attempt to do it
for templates.

The fix-it hints print in a rather odd way, as seen in the test case
(which is arguably a bug/RFE for diagnostic-show-locus.c), but the patch
generated with -fdiagnostics-generate-patch shows that they do the
right thing:

   void test_1 (void *ptr)
   {
  -  foo *f = (foo *)ptr;
  +  foo *f = static_cast<foo *> (ptr);
   }

   void test_2 (const foo *ptr)
   {
  -  foo *f = (foo *)ptr;
  +  foo *f = const_cast<foo *> (ptr);
   }

   void test_3 (bar *ptr)
   {
  -  foo *f = (foo *)ptr;
  +  foo *f = reinterpret_cast<foo *> (ptr);
   }

   void test_4 (bar *ptr)
   {
  -  foo *f = (foo *)ptr->field;
  +  foo *f = const_cast<foo *> (ptr->field);
   }

   void test_5 ()
   {
     bar b_inst;
  -  foo *f = (foo *)&b_inst;
  +  foo *f = reinterpret_cast<foo *> (&b_inst);
   }

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
Adds 39 PASS results to g++.sum.

OK for trunk?

gcc/cp/ChangeLog:
	* parser.c (get_cast_suggestion): New function.
	(maybe_add_cast_fixit): New function.
	(cp_parser_cast_expression): Capture the location of the closing
	parenthesis.  Call maybe_add_cast_fixit when emitting warnings
	about old-style casts.

gcc/testsuite/ChangeLog:
	* g++.dg/other/old-style-cast-fixits.C: New test case.
---
 gcc/cp/parser.c                                    | 93 +++++++++++++++++++++-
 gcc/testsuite/g++.dg/other/old-style-cast-fixits.C | 80 +++++++++++++++++++
 2 files changed, 171 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/other/old-style-cast-fixits.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4714bc6..48ab085 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8633,6 +8633,85 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
     }
 }
 
+/* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR, trying them
+   in the order: const_cast, static_cast, reinterpret_cast.
+
+   Don't suggest dynamic_cast.
+
+   Return the first legal cast kind found, or NULL otherwise.  */
+
+static const char *
+get_cast_suggestion (tree dst_type, tree orig_expr)
+{
+  tree trial;
+
+  /* Reuse the parser logic by attempting to build the various kinds of
+     cast, with "complain" disabled.
+     Identify the first such cast that is valid.  */
+
+  /* Don't attempt to run such logic within template processing.  */
+  if (processing_template_decl)
+    return NULL;
+
+  /* First try const_cast.  */
+  trial = build_const_cast (dst_type, orig_expr, 0 /* complain */);
+  if (trial != error_mark_node)
+    return "const_cast";
+
+  /* If that fails, try static_cast.  */
+  trial = build_static_cast (dst_type, orig_expr, 0 /* complain */);
+  if (trial != error_mark_node)
+    return "static_cast";
+
+  /* Finally, try reinterpret_cast.  */
+  trial = build_reinterpret_cast (dst_type, orig_expr, 0 /* complain */);
+  if (trial != error_mark_node)
+    return "reinterpret_cast";
+
+  /* No such cast possible.  */
+  return NULL;
+}
+
+/* If -Wold-style-cast is enabled, add fix-its to RICHLOC,
+   suggesting how to convert a C-style cast of the form:
+
+     (DST_TYPE)ORIG_EXPR
+
+   to a C++-style cast.
+
+   The primary range of RICHLOC is asssumed to be that of the original
+   expression.  OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the locations
+   of the parens in the C-style cast.  */
+
+static void
+maybe_add_cast_fixit (rich_location *rich_loc, location_t open_paren_loc,
+		      location_t close_paren_loc, tree orig_expr,
+		      tree dst_type)
+{
+  /* This function is non-trivial, so bail out now if the warning isn't
+     going to be emitted.  */
+  if (!warn_old_style_cast)
+    return;
+
+  /* Try to find a legal C++ cast, trying them in order:
+     const_cast, static_cast, reinterpret_cast.  */
+  const char *cast_suggestion = get_cast_suggestion (dst_type, orig_expr);
+  if (!cast_suggestion)
+    return;
+
+  /* Replace the open paren with "CAST_SUGGESTION<".  */
+  pretty_printer pp;
+  pp_printf (&pp, "%s<", cast_suggestion);
+  rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text (&pp));
+
+  /* Replace the close paren with "> (".  */
+  rich_loc->add_fixit_replace (close_paren_loc, "> (");
+
+  /* Add a closing paren after the expr (the primary range of RICH_LOC).  */
+  rich_loc->add_fixit_insert_after (")");
+}
+
+
 /* Parse a cast-expression.
 
    cast-expression:
@@ -8668,6 +8747,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
       /* Consume the `('.  */
       cp_token *open_paren = cp_lexer_consume_token (parser->lexer);
       location_t open_paren_loc = open_paren->location;
+      location_t close_paren_loc = UNKNOWN_LOCATION;
 
       /* A very tricky bit is that `(struct S) { 3 }' is a
 	 compound-literal (which we permit in C++ as an extension).
@@ -8730,7 +8810,10 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
 	  /* Look for the type-id.  */
 	  type = cp_parser_type_id (parser);
 	  /* Look for the closing `)'.  */
-	  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+	  cp_token *close_paren
+	    = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+	  if (close_paren)
+	    close_paren_loc = close_paren->location;
 	  parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
 	}
 
@@ -8760,7 +8843,13 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
 		  && !in_system_header_at (input_location)
 		  && !VOID_TYPE_P (type)
 		  && current_lang_name != lang_name_c)
-		warning (OPT_Wold_style_cast, "use of old-style cast");
+		{
+		  gcc_rich_location rich_loc (input_location);
+		  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);
+		}
 
 	      /* Only type conversions to integral or enumeration types
 		 can be used in constant-expressions.  */
diff --git a/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
new file mode 100644
index 0000000..2e8857c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
@@ -0,0 +1,80 @@
+// { dg-options "-Wold-style-cast -fdiagnostics-show-caret" }
+
+struct foo {};
+struct bar { const foo *field; };
+
+void test_1 (void *ptr)
+{
+  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr;
+                   ^~~
+            -
+            static_cast<
+                  -
+                  > ( )
+     { dg-end-multiline-output "" } */
+}
+
+void test_2 (const foo *ptr)
+{
+  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr;
+                   ^~~
+            -
+            const_cast<
+                  -
+                  > ( )
+     { dg-end-multiline-output "" } */
+}
+
+void test_3 (bar *ptr)
+{
+  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr;
+                   ^~~
+            -
+            reinterpret_cast<
+                  -
+                  > ( )
+     { dg-end-multiline-output "" } */
+}
+
+void test_4 (bar *ptr)
+{
+  foo *f = (foo *)ptr->field; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr->field;
+                        ^~~~~
+            -
+            const_cast<
+                  -
+                  > (        )
+     { dg-end-multiline-output "" } */
+}
+
+void test_5 ()
+{
+  bar b_inst;
+  foo *f = (foo *)&b_inst; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)&b_inst;
+                    ^~~~~~
+            -
+            reinterpret_cast<
+                  -
+                  > (     )
+     { dg-end-multiline-output "" } */
+}
+
+template <typename T>
+void test_6 (void *ptr)
+{
+  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr;
+                   ^~~
+     { dg-end-multiline-output "" } */
+}
-- 
1.8.5.3

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

* Re: [PATCH] C++: Add fix-it hints for -Wold-style-cast
  2017-04-27 20:58   ` [PATCH] C++: Add fix-it hints for -Wold-style-cast David Malcolm
@ 2017-04-27 21:05     ` Florian Weimer
  2017-04-27 22:05     ` Marek Polacek
  1 sibling, 0 replies; 15+ messages in thread
From: Florian Weimer @ 2017-04-27 21:05 UTC (permalink / raw)
  To: David Malcolm; +Cc: Nathan Sidwell, Volker Reichelt, gcc-patches

* David Malcolm:

> gcc/testsuite/ChangeLog:
> 	* g++.dg/other/old-style-cast-fixits.C: New test case.

Would it make sense to add a test cases for the non-fixable cases?

That would be:

  void test_1 (const void *ptr)
  {
    foo *f = (foo *)ptr;
  }

And:

  const bar b_inst;
  foo *f = (foo *)&b_inst;

These require const_cast plus static_cast or const_cast plus
reinterpret_cast.

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

* Re: [PATCH] C++: Add fix-it hints for -Wold-style-cast
  2017-04-27 20:58   ` [PATCH] C++: Add fix-it hints for -Wold-style-cast David Malcolm
  2017-04-27 21:05     ` Florian Weimer
@ 2017-04-27 22:05     ` Marek Polacek
  2017-05-03 13:32       ` [PATCH v2] " David Malcolm
  1 sibling, 1 reply; 15+ messages in thread
From: Marek Polacek @ 2017-04-27 22:05 UTC (permalink / raw)
  To: David Malcolm; +Cc: Nathan Sidwell, Volker Reichelt, gcc-patches

On Thu, Apr 27, 2017 at 05:10:24PM -0400, David Malcolm wrote:
> +  /* First try const_cast.  */
> +  trial = build_const_cast (dst_type, orig_expr, 0 /* complain */);
> +  if (trial != error_mark_node)
> +    return "const_cast";
> +
> +  /* If that fails, try static_cast.  */
> +  trial = build_static_cast (dst_type, orig_expr, 0 /* complain */);
> +  if (trial != error_mark_node)
> +    return "static_cast";
> +
> +  /* Finally, try reinterpret_cast.  */
> +  trial = build_reinterpret_cast (dst_type, orig_expr, 0 /* complain */);
> +  if (trial != error_mark_node)
> +    return "reinterpret_cast";

I think you'll want tf_none instead of 0 /* complain */ in these.

	Marek

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

* Re: [PATCH] Improved diagnostics for casts and enums
  2017-04-27 16:59 ` [PATCH] Improved diagnostics for casts and enums Martin Sebor
@ 2017-04-28  8:42   ` Volker Reichelt
  2017-04-30 17:54     ` Volker Reichelt
  0 siblings, 1 reply; 15+ messages in thread
From: Volker Reichelt @ 2017-04-28  8:42 UTC (permalink / raw)
  To: gcc-patches, Martin Sebor; +Cc: Nathan Sidwell, David Malcolm

On 27 Apr, Martin Sebor wrote:
> On 04/27/2017 01:29 AM, Volker Reichelt wrote:
>> Hi,
>>
>> the following two patches aim at improving GCC's diagnostics to help
>> the user to get rid of old-style casts. While old-style pointer casts
>> are really bad and need to be weeded out quickly, old-style casts between
>> arithmetic types are IMHO much more tolerable. The patches allow to
>> easily distinguish between those situations.
> 
> FWIW, it can be most helpful to include this sort of detail (and
> similar) in diagnostics.  In the case of the C-style cast, besides
> mentioning the type of the result, it might be even more helpful
> to mention the type of the operand because unlike that of the
> result, its type is not apparent from the cast itself.

In this particular case the operand is evaluated after the warning
message. So I couldn't include it in the message without fiddling
around with the logic. I was also afraid that the warning message would
become too long.

>> The first patch for cp_parser_cast_expression in parser.c just adds
>> the target type of the cast to the diagnostic (like in
>> maybe_warn_about_useless_cast in typeck.c).
>>
>> The second patch for type_to_string in error.c tackles the problem
>> that the name of a type doesn't tell you if you have a class or just
>> a simple enum. Similar to adding "{aka 'int'}" to types that
>> are essentially integers, this patch adds "{enum}" to all
>> enumeration types (and adjusts two testcases accordingly).
> 
> In the C front end %qT prints 'enum E' for an argument of
> an enumerated type.  Is there some significance to having
> the C++ front end print 'E { enum }' or can C++ be made
> consistent?
>
> Martin

Ah, good point! I was so focused on the '{aka ...}' thing that I didn't
see the obvious: I should have used %q#T instead of just %qT to get
the enum prefix with the type. Unfortunately, I already committed the
patch after Nathan's OK before seeing your message.

I'll prepare another patch this weekend to revert my error.c changes and
use %q#T for the warnings about old-style and useless casts mentioned
above.

Another thought just crossed my mind: Other users might find an
enum/class prefix helpful for different warnings. Right now they
would have to modify the compile to use %q#T instead of %qT.
Would it make sense to add a compiler option that sets the verbose
flag for cp_printer unconditionally? Or am I just unaware of existing
functionality?

Regards,
Volker

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

* Re: [PATCH] Improved diagnostics for casts and enums
  2017-04-28  8:42   ` Volker Reichelt
@ 2017-04-30 17:54     ` Volker Reichelt
  2017-06-20 16:10       ` Martin Sebor
  0 siblings, 1 reply; 15+ messages in thread
From: Volker Reichelt @ 2017-04-30 17:54 UTC (permalink / raw)
  To: gcc-patches; +Cc: Martin Sebor, Nathan Sidwell, David Malcolm

On 28 Apr, Volker Reichelt wrote:
> On 27 Apr, Martin Sebor wrote:
>> On 04/27/2017 01:29 AM, Volker Reichelt wrote:
>>> Hi,
>>>
>>> the following two patches aim at improving GCC's diagnostics to help
>>> the user to get rid of old-style casts. While old-style pointer casts
>>> are really bad and need to be weeded out quickly, old-style casts between
>>> arithmetic types are IMHO much more tolerable. The patches allow to
>>> easily distinguish between those situations.
>> 
>> FWIW, it can be most helpful to include this sort of detail (and
>> similar) in diagnostics.  In the case of the C-style cast, besides
>> mentioning the type of the result, it might be even more helpful
>> to mention the type of the operand because unlike that of the
>> result, its type is not apparent from the cast itself.
> 
> In this particular case the operand is evaluated after the warning
> message. So I couldn't include it in the message without fiddling
> around with the logic. I was also afraid that the warning message would
> become too long.
> 
>>> The first patch for cp_parser_cast_expression in parser.c just adds
>>> the target type of the cast to the diagnostic (like in
>>> maybe_warn_about_useless_cast in typeck.c).
>>>
>>> The second patch for type_to_string in error.c tackles the problem
>>> that the name of a type doesn't tell you if you have a class or just
>>> a simple enum. Similar to adding "{aka 'int'}" to types that
>>> are essentially integers, this patch adds "{enum}" to all
>>> enumeration types (and adjusts two testcases accordingly).
>> 
>> In the C front end %qT prints 'enum E' for an argument of
>> an enumerated type.  Is there some significance to having
>> the C++ front end print 'E { enum }' or can C++ be made
>> consistent?
>>
>> Martin
> 
> Ah, good point! I was so focused on the '{aka ...}' thing that I didn't
> see the obvious: I should have used %q#T instead of just %qT to get
> the enum prefix with the type. Unfortunately, I already committed the
> patch after Nathan's OK before seeing your message.
> 
> I'll prepare another patch this weekend to revert my error.c changes and
> use %q#T for the warnings about old-style and useless casts mentioned
> above.
> 
> Another thought just crossed my mind: Other users might find an
> enum/class prefix helpful for different warnings. Right now they
> would have to modify the compile to use %q#T instead of %qT.
> Would it make sense to add a compiler option that sets the verbose
> flag for cp_printer unconditionally? Or am I just unaware of existing
> functionality?
> 
> Regards,
> Volker

So here's the patch that reverts the special enum handling in 
type_to_string and uses %q#T instead of %qT for two casting-related
diagnostics.

Bootstrapped and regtested on x86_64-pc-linux-gnu.

OK for trunk?

As one can see from the testsuite changes, there are several
casting- and conversion-related messages like "invalid conversion from",
"cannot convert", "invalid cast" that still use the simple %qT
form. I'll give it a try to use %q#T there as well and prepare a
separate patch if this really improves the diagnostics.

Regards,
Volker


2017-04-30  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 247394)
+++ gcc/cp/parser.c	(working copy)
@@ -8764,7 +8764,7 @@
 		  && !VOID_TYPE_P (type)
 		  && current_lang_name != lang_name_c)
 		warning (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
 		 can be used in constant-expressions.  */
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 247394)
+++ gcc/cp/typeck.c	(working copy)
@@ -6631,7 +6631,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 247394)
+++ gcc/cp/error.c	(working copy)
@@ -3134,10 +3134,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-04-30  Volker Reichelt  <v.reichelt@netcologne.de>

	* g++.dg/cpp1z/direct-enum-init1.C: Rever 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 247394)
+++ 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 } }
+  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 {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 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 } }
+  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 {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 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 247394)
+++ 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] 15+ messages in thread

* [PATCH v2] C++: Add fix-it hints for -Wold-style-cast
  2017-04-27 22:05     ` Marek Polacek
@ 2017-05-03 13:32       ` David Malcolm
  2017-05-26 19:54         ` [PING] re " David Malcolm
  2017-06-20 18:39         ` Jason Merrill
  0 siblings, 2 replies; 15+ messages in thread
From: David Malcolm @ 2017-05-03 13:32 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: Marek Polacek, Volker Reichelt, gcc-patches, David Malcolm

On Thu, 2017-04-27 at 23:03 +0200, Marek Polacek wrote:
> On Thu, Apr 27, 2017 at 05:10:24PM -0400, David Malcolm wrote:
> > +  /* First try const_cast.  */
> > +  trial = build_const_cast (dst_type, orig_expr, 0 /* complain
> > */);
> > +  if (trial != error_mark_node)
> > +    return "const_cast";
> > +
> > +  /* If that fails, try static_cast.  */
> > +  trial = build_static_cast (dst_type, orig_expr, 0 /* complain
> > */);
> > +  if (trial != error_mark_node)
> > +    return "static_cast";
> > +
> > +  /* Finally, try reinterpret_cast.  */
> > +  trial = build_reinterpret_cast (dst_type, orig_expr, 0 /*
> > complain */);
> > +  if (trial != error_mark_node)
> > +    return "reinterpret_cast";
> 
> I think you'll want tf_none instead of 0 /* complain */ in these.
> 
> 	Marek

Thanks.

Here's an updated version of the patch.

Changes since v1:
- updated expected fixit-formatting (the new fix-it printer in
  r247548 handles this properly now)
- added new test cases as suggested by Florian
- use "tf_none" rather than "0 /* complain */"

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

OK for trunk?

gcc/cp/ChangeLog:
	* parser.c (get_cast_suggestion): New function.
	(maybe_add_cast_fixit): New function.
	(cp_parser_cast_expression): Capture the location of the closing
	parenthesis.  Call maybe_add_cast_fixit when emitting warnings
	about old-style casts.

gcc/testsuite/ChangeLog:
	* g++.dg/other/old-style-cast-fixits.C: New test case.
---
 gcc/cp/parser.c                                    | 93 ++++++++++++++++++++-
 gcc/testsuite/g++.dg/other/old-style-cast-fixits.C | 95 ++++++++++++++++++++++
 2 files changed, 186 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/other/old-style-cast-fixits.C

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4714bc6..2f83aa9 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8633,6 +8633,85 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
     }
 }
 
+/* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR, trying them
+   in the order: const_cast, static_cast, reinterpret_cast.
+
+   Don't suggest dynamic_cast.
+
+   Return the first legal cast kind found, or NULL otherwise.  */
+
+static const char *
+get_cast_suggestion (tree dst_type, tree orig_expr)
+{
+  tree trial;
+
+  /* Reuse the parser logic by attempting to build the various kinds of
+     cast, with "complain" disabled.
+     Identify the first such cast that is valid.  */
+
+  /* Don't attempt to run such logic within template processing.  */
+  if (processing_template_decl)
+    return NULL;
+
+  /* First try const_cast.  */
+  trial = build_const_cast (dst_type, orig_expr, tf_none);
+  if (trial != error_mark_node)
+    return "const_cast";
+
+  /* If that fails, try static_cast.  */
+  trial = build_static_cast (dst_type, orig_expr, tf_none);
+  if (trial != error_mark_node)
+    return "static_cast";
+
+  /* Finally, try reinterpret_cast.  */
+  trial = build_reinterpret_cast (dst_type, orig_expr, tf_none);
+  if (trial != error_mark_node)
+    return "reinterpret_cast";
+
+  /* No such cast possible.  */
+  return NULL;
+}
+
+/* If -Wold-style-cast is enabled, add fix-its to RICHLOC,
+   suggesting how to convert a C-style cast of the form:
+
+     (DST_TYPE)ORIG_EXPR
+
+   to a C++-style cast.
+
+   The primary range of RICHLOC is asssumed to be that of the original
+   expression.  OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the locations
+   of the parens in the C-style cast.  */
+
+static void
+maybe_add_cast_fixit (rich_location *rich_loc, location_t open_paren_loc,
+		      location_t close_paren_loc, tree orig_expr,
+		      tree dst_type)
+{
+  /* This function is non-trivial, so bail out now if the warning isn't
+     going to be emitted.  */
+  if (!warn_old_style_cast)
+    return;
+
+  /* Try to find a legal C++ cast, trying them in order:
+     const_cast, static_cast, reinterpret_cast.  */
+  const char *cast_suggestion = get_cast_suggestion (dst_type, orig_expr);
+  if (!cast_suggestion)
+    return;
+
+  /* Replace the open paren with "CAST_SUGGESTION<".  */
+  pretty_printer pp;
+  pp_printf (&pp, "%s<", cast_suggestion);
+  rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text (&pp));
+
+  /* Replace the close paren with "> (".  */
+  rich_loc->add_fixit_replace (close_paren_loc, "> (");
+
+  /* Add a closing paren after the expr (the primary range of RICH_LOC).  */
+  rich_loc->add_fixit_insert_after (")");
+}
+
+
 /* Parse a cast-expression.
 
    cast-expression:
@@ -8668,6 +8747,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
       /* Consume the `('.  */
       cp_token *open_paren = cp_lexer_consume_token (parser->lexer);
       location_t open_paren_loc = open_paren->location;
+      location_t close_paren_loc = UNKNOWN_LOCATION;
 
       /* A very tricky bit is that `(struct S) { 3 }' is a
 	 compound-literal (which we permit in C++ as an extension).
@@ -8730,7 +8810,10 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
 	  /* Look for the type-id.  */
 	  type = cp_parser_type_id (parser);
 	  /* Look for the closing `)'.  */
-	  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+	  cp_token *close_paren
+	    = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+	  if (close_paren)
+	    close_paren_loc = close_paren->location;
 	  parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
 	}
 
@@ -8760,7 +8843,13 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
 		  && !in_system_header_at (input_location)
 		  && !VOID_TYPE_P (type)
 		  && current_lang_name != lang_name_c)
-		warning (OPT_Wold_style_cast, "use of old-style cast");
+		{
+		  gcc_rich_location rich_loc (input_location);
+		  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);
+		}
 
 	      /* Only type conversions to integral or enumeration types
 		 can be used in constant-expressions.  */
diff --git a/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
new file mode 100644
index 0000000..a10b623
--- /dev/null
+++ b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
@@ -0,0 +1,95 @@
+// { dg-options "-Wold-style-cast -fdiagnostics-show-caret" }
+
+struct foo {};
+struct bar { const foo *field; };
+
+void test_1 (void *ptr)
+{
+  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr;
+                   ^~~
+            ----------
+            static_cast<foo *> (ptr)
+     { dg-end-multiline-output "" } */
+}
+
+void test_2 (const foo *ptr)
+{
+  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr;
+                   ^~~
+            ----------
+            const_cast<foo *> (ptr)
+     { dg-end-multiline-output "" } */
+}
+
+void test_3 (bar *ptr)
+{
+  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr;
+                   ^~~
+            ----------
+            reinterpret_cast<foo *> (ptr)
+     { dg-end-multiline-output "" } */
+}
+
+void test_4 (bar *ptr)
+{
+  foo *f = (foo *)ptr->field; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr->field;
+                        ^~~~~
+            -----------------
+            const_cast<foo *> (ptr->field)
+     { dg-end-multiline-output "" } */
+}
+
+void test_5 ()
+{
+  bar b_inst;
+  foo *f = (foo *)&b_inst; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)&b_inst;
+                    ^~~~~~
+            --------------
+            reinterpret_cast<foo *> (&b_inst)
+     { dg-end-multiline-output "" } */
+}
+
+/* We don't offer suggestions for templates.  */
+
+template <typename T>
+void test_6 (void *ptr)
+{
+  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr;
+                   ^~~
+     { dg-end-multiline-output "" } */
+}
+
+/* We don't offer suggestions where a single C++-style cast can't be
+   used.  */
+
+void test_7 (const void *ptr)
+{
+  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)ptr;
+                   ^~~
+     { dg-end-multiline-output "" } */
+}
+
+/* Likewise, no single C++-style cast is usable here.  */
+
+void test_8 (const bar &b_inst)
+{
+  foo *f = (foo *)&b_inst;  // { dg-warning "old-style cast" }
+  /* { dg-begin-multiline-output "" }
+   foo *f = (foo *)&b_inst;
+                    ^~~~~~
+     { dg-end-multiline-output "" } */
+}
-- 
1.8.5.3

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

* [PING] re [PATCH v2] C++: Add fix-it hints for -Wold-style-cast
  2017-05-03 13:32       ` [PATCH v2] " David Malcolm
@ 2017-05-26 19:54         ` David Malcolm
  2017-06-05 16:41           ` [PING^2] " David Malcolm
  2017-06-20 18:39         ` Jason Merrill
  1 sibling, 1 reply; 15+ messages in thread
From: David Malcolm @ 2017-05-26 19:54 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: Marek Polacek, Volker Reichelt, gcc-patches

On Wed, 2017-05-03 at 09:51 -0400, David Malcolm wrote:
> On Thu, 2017-04-27 at 23:03 +0200, Marek Polacek wrote:
> > On Thu, Apr 27, 2017 at 05:10:24PM -0400, David Malcolm wrote:
> > > +  /* First try const_cast.  */
> > > +  trial = build_const_cast (dst_type, orig_expr, 0 /* complain
> > > */);
> > > +  if (trial != error_mark_node)
> > > +    return "const_cast";
> > > +
> > > +  /* If that fails, try static_cast.  */
> > > +  trial = build_static_cast (dst_type, orig_expr, 0 /* complain
> > > */);
> > > +  if (trial != error_mark_node)
> > > +    return "static_cast";
> > > +
> > > +  /* Finally, try reinterpret_cast.  */
> > > +  trial = build_reinterpret_cast (dst_type, orig_expr, 0 /*
> > > complain */);
> > > +  if (trial != error_mark_node)
> > > +    return "reinterpret_cast";
> > 
> > I think you'll want tf_none instead of 0 /* complain */ in these.
> > 
> > 	Marek
> 
> Thanks.
> 
> Here's an updated version of the patch.
> 
> Changes since v1:
> - updated expected fixit-formatting (the new fix-it printer in
>   r247548 handles this properly now)
> - added new test cases as suggested by Florian
> - use "tf_none" rather than "0 /* complain */"
> 
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
> 
> OK for trunk?
> 
> gcc/cp/ChangeLog:
> 	* parser.c (get_cast_suggestion): New function.
> 	(maybe_add_cast_fixit): New function.
> 	(cp_parser_cast_expression): Capture the location of the
> closing
> 	parenthesis.  Call maybe_add_cast_fixit when emitting warnings
> 	about old-style casts.
> 
> gcc/testsuite/ChangeLog:
> 	* g++.dg/other/old-style-cast-fixits.C: New test case.
> ---
>  gcc/cp/parser.c                                    | 93
> ++++++++++++++++++++-
>  gcc/testsuite/g++.dg/other/old-style-cast-fixits.C | 95
> ++++++++++++++++++++++
>  2 files changed, 186 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/other/old-style-cast
> -fixits.C
> 
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index 4714bc6..2f83aa9 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -8633,6 +8633,85 @@ cp_parser_tokens_start_cast_expression
> (cp_parser *parser)
>      }
>  }
>  
> +/* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR,
> trying them
> +   in the order: const_cast, static_cast, reinterpret_cast.
> +
> +   Don't suggest dynamic_cast.
> +
> +   Return the first legal cast kind found, or NULL otherwise.  */
> +
> +static const char *
> +get_cast_suggestion (tree dst_type, tree orig_expr)
> +{
> +  tree trial;
> +
> +  /* Reuse the parser logic by attempting to build the various kinds
> of
> +     cast, with "complain" disabled.
> +     Identify the first such cast that is valid.  */
> +
> +  /* Don't attempt to run such logic within template processing.  */
> +  if (processing_template_decl)
> +    return NULL;
> +
> +  /* First try const_cast.  */
> +  trial = build_const_cast (dst_type, orig_expr, tf_none);
> +  if (trial != error_mark_node)
> +    return "const_cast";
> +
> +  /* If that fails, try static_cast.  */
> +  trial = build_static_cast (dst_type, orig_expr, tf_none);
> +  if (trial != error_mark_node)
> +    return "static_cast";
> +
> +  /* Finally, try reinterpret_cast.  */
> +  trial = build_reinterpret_cast (dst_type, orig_expr, tf_none);
> +  if (trial != error_mark_node)
> +    return "reinterpret_cast";
> +
> +  /* No such cast possible.  */
> +  return NULL;
> +}
> +
> +/* If -Wold-style-cast is enabled, add fix-its to RICHLOC,
> +   suggesting how to convert a C-style cast of the form:
> +
> +     (DST_TYPE)ORIG_EXPR
> +
> +   to a C++-style cast.
> +
> +   The primary range of RICHLOC is asssumed to be that of the
> original
> +   expression.  OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the
> locations
> +   of the parens in the C-style cast.  */
> +
> +static void
> +maybe_add_cast_fixit (rich_location *rich_loc, location_t
> open_paren_loc,
> +		      location_t close_paren_loc, tree orig_expr,
> +		      tree dst_type)
> +{
> +  /* This function is non-trivial, so bail out now if the warning
> isn't
> +     going to be emitted.  */
> +  if (!warn_old_style_cast)
> +    return;
> +
> +  /* Try to find a legal C++ cast, trying them in order:
> +     const_cast, static_cast, reinterpret_cast.  */
> +  const char *cast_suggestion = get_cast_suggestion (dst_type,
> orig_expr);
> +  if (!cast_suggestion)
> +    return;
> +
> +  /* Replace the open paren with "CAST_SUGGESTION<".  */
> +  pretty_printer pp;
> +  pp_printf (&pp, "%s<", cast_suggestion);
> +  rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text
> (&pp));
> +
> +  /* Replace the close paren with "> (".  */
> +  rich_loc->add_fixit_replace (close_paren_loc, "> (");
> +
> +  /* Add a closing paren after the expr (the primary range of
> RICH_LOC).  */
> +  rich_loc->add_fixit_insert_after (")");
> +}
> +
> +
>  /* Parse a cast-expression.
>  
>     cast-expression:
> @@ -8668,6 +8747,7 @@ cp_parser_cast_expression (cp_parser *parser,
> bool address_p, bool cast_p,
>        /* Consume the `('.  */
>        cp_token *open_paren = cp_lexer_consume_token (parser->lexer);
>        location_t open_paren_loc = open_paren->location;
> +      location_t close_paren_loc = UNKNOWN_LOCATION;
>  
>        /* A very tricky bit is that `(struct S) { 3 }' is a
>  	 compound-literal (which we permit in C++ as an extension).
> @@ -8730,7 +8810,10 @@ cp_parser_cast_expression (cp_parser *parser,
> bool address_p, bool cast_p,
>  	  /* Look for the type-id.  */
>  	  type = cp_parser_type_id (parser);
>  	  /* Look for the closing `)'.  */
> -	  cp_parser_require (parser, CPP_CLOSE_PAREN,
> RT_CLOSE_PAREN);
> +	  cp_token *close_paren
> +	    = cp_parser_require (parser, CPP_CLOSE_PAREN,
> RT_CLOSE_PAREN);
> +	  if (close_paren)
> +	    close_paren_loc = close_paren->location;
>  	  parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
>  	}
>  
> @@ -8760,7 +8843,13 @@ cp_parser_cast_expression (cp_parser *parser,
> bool address_p, bool cast_p,
>  		  && !in_system_header_at (input_location)
>  		  && !VOID_TYPE_P (type)
>  		  && current_lang_name != lang_name_c)
> -		warning (OPT_Wold_style_cast, "use of old-style
> cast");
> +		{
> +		  gcc_rich_location rich_loc (input_location);
> +		  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);
> +		}
>  
>  	      /* Only type conversions to integral or enumeration
> types
>  		 can be used in constant-expressions.  */
> diff --git a/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> new file mode 100644
> index 0000000..a10b623
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> @@ -0,0 +1,95 @@
> +// { dg-options "-Wold-style-cast -fdiagnostics-show-caret" }
> +
> +struct foo {};
> +struct bar { const foo *field; };
> +
> +void test_1 (void *ptr)
> +{
> +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> +  /* { dg-begin-multiline-output "" }
> +   foo *f = (foo *)ptr;
> +                   ^~~
> +            ----------
> +            static_cast<foo *> (ptr)
> +     { dg-end-multiline-output "" } */
> +}
> +
> +void test_2 (const foo *ptr)
> +{
> +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> +  /* { dg-begin-multiline-output "" }
> +   foo *f = (foo *)ptr;
> +                   ^~~
> +            ----------
> +            const_cast<foo *> (ptr)
> +     { dg-end-multiline-output "" } */
> +}
> +
> +void test_3 (bar *ptr)
> +{
> +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> +  /* { dg-begin-multiline-output "" }
> +   foo *f = (foo *)ptr;
> +                   ^~~
> +            ----------
> +            reinterpret_cast<foo *> (ptr)
> +     { dg-end-multiline-output "" } */
> +}
> +
> +void test_4 (bar *ptr)
> +{
> +  foo *f = (foo *)ptr->field; // { dg-warning "old-style cast" }
> +  /* { dg-begin-multiline-output "" }
> +   foo *f = (foo *)ptr->field;
> +                        ^~~~~
> +            -----------------
> +            const_cast<foo *> (ptr->field)
> +     { dg-end-multiline-output "" } */
> +}
> +
> +void test_5 ()
> +{
> +  bar b_inst;
> +  foo *f = (foo *)&b_inst; // { dg-warning "old-style cast" }
> +  /* { dg-begin-multiline-output "" }
> +   foo *f = (foo *)&b_inst;
> +                    ^~~~~~
> +            --------------
> +            reinterpret_cast<foo *> (&b_inst)
> +     { dg-end-multiline-output "" } */
> +}
> +
> +/* We don't offer suggestions for templates.  */
> +
> +template <typename T>
> +void test_6 (void *ptr)
> +{
> +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> +  /* { dg-begin-multiline-output "" }
> +   foo *f = (foo *)ptr;
> +                   ^~~
> +     { dg-end-multiline-output "" } */
> +}
> +
> +/* We don't offer suggestions where a single C++-style cast can't be
> +   used.  */
> +
> +void test_7 (const void *ptr)
> +{
> +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> +  /* { dg-begin-multiline-output "" }
> +   foo *f = (foo *)ptr;
> +                   ^~~
> +     { dg-end-multiline-output "" } */
> +}
> +
> +/* Likewise, no single C++-style cast is usable here.  */
> +
> +void test_8 (const bar &b_inst)
> +{
> +  foo *f = (foo *)&b_inst;  // { dg-warning "old-style cast" }
> +  /* { dg-begin-multiline-output "" }
> +   foo *f = (foo *)&b_inst;
> +                    ^~~~~~
> +     { dg-end-multiline-output "" } */
> +}

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

* [PING^2] re [PATCH v2] C++: Add fix-it hints for -Wold-style-cast
  2017-05-26 19:54         ` [PING] re " David Malcolm
@ 2017-06-05 16:41           ` David Malcolm
  2017-06-20 14:03             ` [PING^3] " David Malcolm
  0 siblings, 1 reply; 15+ messages in thread
From: David Malcolm @ 2017-06-05 16:41 UTC (permalink / raw)
  To: Nathan Sidwell; +Cc: Marek Polacek, Volker Reichelt, gcc-patches

Ping re this patch:

 https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00204.html

On Fri, 2017-05-26 at 15:35 -0400, David Malcolm wrote:
> On Wed, 2017-05-03 at 09:51 -0400, David Malcolm wrote:
> > On Thu, 2017-04-27 at 23:03 +0200, Marek Polacek wrote:
> > > On Thu, Apr 27, 2017 at 05:10:24PM -0400, David Malcolm wrote:
> > > > +  /* First try const_cast.  */
> > > > +  trial = build_const_cast (dst_type, orig_expr, 0 /* complain
> > > > */);
> > > > +  if (trial != error_mark_node)
> > > > +    return "const_cast";
> > > > +
> > > > +  /* If that fails, try static_cast.  */
> > > > +  trial = build_static_cast (dst_type, orig_expr, 0 /*
> > > > complain
> > > > */);
> > > > +  if (trial != error_mark_node)
> > > > +    return "static_cast";
> > > > +
> > > > +  /* Finally, try reinterpret_cast.  */
> > > > +  trial = build_reinterpret_cast (dst_type, orig_expr, 0 /*
> > > > complain */);
> > > > +  if (trial != error_mark_node)
> > > > +    return "reinterpret_cast";
> > > 
> > > I think you'll want tf_none instead of 0 /* complain */ in these.
> > > 
> > > 	Marek
> > 
> > Thanks.
> > 
> > Here's an updated version of the patch.
> > 
> > Changes since v1:
> > - updated expected fixit-formatting (the new fix-it printer in
> >   r247548 handles this properly now)
> > - added new test cases as suggested by Florian
> > - use "tf_none" rather than "0 /* complain */"
> > 
> > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
> > 
> > OK for trunk?
> > 
> > gcc/cp/ChangeLog:
> > 	* parser.c (get_cast_suggestion): New function.
> > 	(maybe_add_cast_fixit): New function.
> > 	(cp_parser_cast_expression): Capture the location of the
> > closing
> > 	parenthesis.  Call maybe_add_cast_fixit when emitting warnings
> > 	about old-style casts.
> > 
> > gcc/testsuite/ChangeLog:
> > 	* g++.dg/other/old-style-cast-fixits.C: New test case.
> > ---
> >  gcc/cp/parser.c                                    | 93
> > ++++++++++++++++++++-
> >  gcc/testsuite/g++.dg/other/old-style-cast-fixits.C | 95
> > ++++++++++++++++++++++
> >  2 files changed, 186 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/other/old-style-cast
> > -fixits.C
> > 
> > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> > index 4714bc6..2f83aa9 100644
> > --- a/gcc/cp/parser.c
> > +++ b/gcc/cp/parser.c
> > @@ -8633,6 +8633,85 @@ cp_parser_tokens_start_cast_expression
> > (cp_parser *parser)
> >      }
> >  }
> >  
> > +/* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR,
> > trying them
> > +   in the order: const_cast, static_cast, reinterpret_cast.
> > +
> > +   Don't suggest dynamic_cast.
> > +
> > +   Return the first legal cast kind found, or NULL otherwise.  */
> > +
> > +static const char *
> > +get_cast_suggestion (tree dst_type, tree orig_expr)
> > +{
> > +  tree trial;
> > +
> > +  /* Reuse the parser logic by attempting to build the various
> > kinds
> > of
> > +     cast, with "complain" disabled.
> > +     Identify the first such cast that is valid.  */
> > +
> > +  /* Don't attempt to run such logic within template processing. 
> >  */
> > +  if (processing_template_decl)
> > +    return NULL;
> > +
> > +  /* First try const_cast.  */
> > +  trial = build_const_cast (dst_type, orig_expr, tf_none);
> > +  if (trial != error_mark_node)
> > +    return "const_cast";
> > +
> > +  /* If that fails, try static_cast.  */
> > +  trial = build_static_cast (dst_type, orig_expr, tf_none);
> > +  if (trial != error_mark_node)
> > +    return "static_cast";
> > +
> > +  /* Finally, try reinterpret_cast.  */
> > +  trial = build_reinterpret_cast (dst_type, orig_expr, tf_none);
> > +  if (trial != error_mark_node)
> > +    return "reinterpret_cast";
> > +
> > +  /* No such cast possible.  */
> > +  return NULL;
> > +}
> > +
> > +/* If -Wold-style-cast is enabled, add fix-its to RICHLOC,
> > +   suggesting how to convert a C-style cast of the form:
> > +
> > +     (DST_TYPE)ORIG_EXPR
> > +
> > +   to a C++-style cast.
> > +
> > +   The primary range of RICHLOC is asssumed to be that of the
> > original
> > +   expression.  OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the
> > locations
> > +   of the parens in the C-style cast.  */
> > +
> > +static void
> > +maybe_add_cast_fixit (rich_location *rich_loc, location_t
> > open_paren_loc,
> > +		      location_t close_paren_loc, tree orig_expr,
> > +		      tree dst_type)
> > +{
> > +  /* This function is non-trivial, so bail out now if the warning
> > isn't
> > +     going to be emitted.  */
> > +  if (!warn_old_style_cast)
> > +    return;
> > +
> > +  /* Try to find a legal C++ cast, trying them in order:
> > +     const_cast, static_cast, reinterpret_cast.  */
> > +  const char *cast_suggestion = get_cast_suggestion (dst_type,
> > orig_expr);
> > +  if (!cast_suggestion)
> > +    return;
> > +
> > +  /* Replace the open paren with "CAST_SUGGESTION<".  */
> > +  pretty_printer pp;
> > +  pp_printf (&pp, "%s<", cast_suggestion);
> > +  rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text
> > (&pp));
> > +
> > +  /* Replace the close paren with "> (".  */
> > +  rich_loc->add_fixit_replace (close_paren_loc, "> (");
> > +
> > +  /* Add a closing paren after the expr (the primary range of
> > RICH_LOC).  */
> > +  rich_loc->add_fixit_insert_after (")");
> > +}
> > +
> > +
> >  /* Parse a cast-expression.
> >  
> >     cast-expression:
> > @@ -8668,6 +8747,7 @@ cp_parser_cast_expression (cp_parser *parser,
> > bool address_p, bool cast_p,
> >        /* Consume the `('.  */
> >        cp_token *open_paren = cp_lexer_consume_token (parser
> > ->lexer);
> >        location_t open_paren_loc = open_paren->location;
> > +      location_t close_paren_loc = UNKNOWN_LOCATION;
> >  
> >        /* A very tricky bit is that `(struct S) { 3 }' is a
> >  	 compound-literal (which we permit in C++ as an
> > extension).
> > @@ -8730,7 +8810,10 @@ cp_parser_cast_expression (cp_parser
> > *parser,
> > bool address_p, bool cast_p,
> >  	  /* Look for the type-id.  */
> >  	  type = cp_parser_type_id (parser);
> >  	  /* Look for the closing `)'.  */
> > -	  cp_parser_require (parser, CPP_CLOSE_PAREN,
> > RT_CLOSE_PAREN);
> > +	  cp_token *close_paren
> > +	    = cp_parser_require (parser, CPP_CLOSE_PAREN,
> > RT_CLOSE_PAREN);
> > +	  if (close_paren)
> > +	    close_paren_loc = close_paren->location;
> >  	  parser->in_type_id_in_expr_p =
> > saved_in_type_id_in_expr_p;
> >  	}
> >  
> > @@ -8760,7 +8843,13 @@ cp_parser_cast_expression (cp_parser
> > *parser,
> > bool address_p, bool cast_p,
> >  		  && !in_system_header_at (input_location)
> >  		  && !VOID_TYPE_P (type)
> >  		  && current_lang_name != lang_name_c)
> > -		warning (OPT_Wold_style_cast, "use of old-style
> > cast");
> > +		{
> > +		  gcc_rich_location rich_loc (input_location);
> > +		  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);
> > +		}
> >  
> >  	      /* Only type conversions to integral or enumeration
> > types
> >  		 can be used in constant-expressions.  */
> > diff --git a/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> > b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> > new file mode 100644
> > index 0000000..a10b623
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> > @@ -0,0 +1,95 @@
> > +// { dg-options "-Wold-style-cast -fdiagnostics-show-caret" }
> > +
> > +struct foo {};
> > +struct bar { const foo *field; };
> > +
> > +void test_1 (void *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +            ----------
> > +            static_cast<foo *> (ptr)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +void test_2 (const foo *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +            ----------
> > +            const_cast<foo *> (ptr)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +void test_3 (bar *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +            ----------
> > +            reinterpret_cast<foo *> (ptr)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +void test_4 (bar *ptr)
> > +{
> > +  foo *f = (foo *)ptr->field; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr->field;
> > +                        ^~~~~
> > +            -----------------
> > +            const_cast<foo *> (ptr->field)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +void test_5 ()
> > +{
> > +  bar b_inst;
> > +  foo *f = (foo *)&b_inst; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)&b_inst;
> > +                    ^~~~~~
> > +            --------------
> > +            reinterpret_cast<foo *> (&b_inst)
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +/* We don't offer suggestions for templates.  */
> > +
> > +template <typename T>
> > +void test_6 (void *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +/* We don't offer suggestions where a single C++-style cast can't
> > be
> > +   used.  */
> > +
> > +void test_7 (const void *ptr)
> > +{
> > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)ptr;
> > +                   ^~~
> > +     { dg-end-multiline-output "" } */
> > +}
> > +
> > +/* Likewise, no single C++-style cast is usable here.  */
> > +
> > +void test_8 (const bar &b_inst)
> > +{
> > +  foo *f = (foo *)&b_inst;  // { dg-warning "old-style cast" }
> > +  /* { dg-begin-multiline-output "" }
> > +   foo *f = (foo *)&b_inst;
> > +                    ^~~~~~
> > +     { dg-end-multiline-output "" } */
> > +}

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

* [PING^3] re [PATCH v2] C++: Add fix-it hints for -Wold-style-cast
  2017-06-05 16:41           ` [PING^2] " David Malcolm
@ 2017-06-20 14:03             ` David Malcolm
  0 siblings, 0 replies; 15+ messages in thread
From: David Malcolm @ 2017-06-20 14:03 UTC (permalink / raw)
  To: gcc-patches; +Cc: Marek Polacek, Volker Reichelt, Nathan Sidwell

Ping re this patch:

  https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00204.html

(more description can be seen in v1 of the patch here:
  https://gcc.gnu.org/ml/gcc-patches/2017-04/msg01429.html
)


On Mon, 2017-06-05 at 12:41 -0400, David Malcolm wrote:
> Ping re this patch:
> 
>  https://gcc.gnu.org/ml/gcc-patches/2017-05/msg00204.html
> 
> On Fri, 2017-05-26 at 15:35 -0400, David Malcolm wrote:
> > On Wed, 2017-05-03 at 09:51 -0400, David Malcolm wrote:
> > > On Thu, 2017-04-27 at 23:03 +0200, Marek Polacek wrote:
> > > > On Thu, Apr 27, 2017 at 05:10:24PM -0400, David Malcolm wrote:
> > > > > +  /* First try const_cast.  */
> > > > > +  trial = build_const_cast (dst_type, orig_expr, 0 /*
> > > > > complain
> > > > > */);
> > > > > +  if (trial != error_mark_node)
> > > > > +    return "const_cast";
> > > > > +
> > > > > +  /* If that fails, try static_cast.  */
> > > > > +  trial = build_static_cast (dst_type, orig_expr, 0 /*
> > > > > complain
> > > > > */);
> > > > > +  if (trial != error_mark_node)
> > > > > +    return "static_cast";
> > > > > +
> > > > > +  /* Finally, try reinterpret_cast.  */
> > > > > +  trial = build_reinterpret_cast (dst_type, orig_expr, 0 /*
> > > > > complain */);
> > > > > +  if (trial != error_mark_node)
> > > > > +    return "reinterpret_cast";
> > > > 
> > > > I think you'll want tf_none instead of 0 /* complain */ in
> > > > these.
> > > > 
> > > > 	Marek
> > > 
> > > Thanks.
> > > 
> > > Here's an updated version of the patch.
> > > 
> > > Changes since v1:
> > > - updated expected fixit-formatting (the new fix-it printer in
> > >   r247548 handles this properly now)
> > > - added new test cases as suggested by Florian
> > > - use "tf_none" rather than "0 /* complain */"
> > > 
> > > Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
> > > 
> > > OK for trunk?
> > > 
> > > gcc/cp/ChangeLog:
> > > 	* parser.c (get_cast_suggestion): New function.
> > > 	(maybe_add_cast_fixit): New function.
> > > 	(cp_parser_cast_expression): Capture the location of the
> > > closing
> > > 	parenthesis.  Call maybe_add_cast_fixit when emitting warnings
> > > 	about old-style casts.
> > > 
> > > gcc/testsuite/ChangeLog:
> > > 	* g++.dg/other/old-style-cast-fixits.C: New test case.
> > > ---
> > >  gcc/cp/parser.c                                    | 93
> > > ++++++++++++++++++++-
> > >  gcc/testsuite/g++.dg/other/old-style-cast-fixits.C | 95
> > > ++++++++++++++++++++++
> > >  2 files changed, 186 insertions(+), 2 deletions(-)
> > >  create mode 100644 gcc/testsuite/g++.dg/other/old-style-cast
> > > -fixits.C
> > > 
> > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> > > index 4714bc6..2f83aa9 100644
> > > --- a/gcc/cp/parser.c
> > > +++ b/gcc/cp/parser.c
> > > @@ -8633,6 +8633,85 @@ cp_parser_tokens_start_cast_expression
> > > (cp_parser *parser)
> > >      }
> > >  }
> > >  
> > > +/* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR,
> > > trying them
> > > +   in the order: const_cast, static_cast, reinterpret_cast.
> > > +
> > > +   Don't suggest dynamic_cast.
> > > +
> > > +   Return the first legal cast kind found, or NULL otherwise. 
> > >  */
> > > +
> > > +static const char *
> > > +get_cast_suggestion (tree dst_type, tree orig_expr)
> > > +{
> > > +  tree trial;
> > > +
> > > +  /* Reuse the parser logic by attempting to build the various
> > > kinds
> > > of
> > > +     cast, with "complain" disabled.
> > > +     Identify the first such cast that is valid.  */
> > > +
> > > +  /* Don't attempt to run such logic within template processing.
> > >  */
> > > +  if (processing_template_decl)
> > > +    return NULL;
> > > +
> > > +  /* First try const_cast.  */
> > > +  trial = build_const_cast (dst_type, orig_expr, tf_none);
> > > +  if (trial != error_mark_node)
> > > +    return "const_cast";
> > > +
> > > +  /* If that fails, try static_cast.  */
> > > +  trial = build_static_cast (dst_type, orig_expr, tf_none);
> > > +  if (trial != error_mark_node)
> > > +    return "static_cast";
> > > +
> > > +  /* Finally, try reinterpret_cast.  */
> > > +  trial = build_reinterpret_cast (dst_type, orig_expr, tf_none);
> > > +  if (trial != error_mark_node)
> > > +    return "reinterpret_cast";
> > > +
> > > +  /* No such cast possible.  */
> > > +  return NULL;
> > > +}
> > > +
> > > +/* If -Wold-style-cast is enabled, add fix-its to RICHLOC,
> > > +   suggesting how to convert a C-style cast of the form:
> > > +
> > > +     (DST_TYPE)ORIG_EXPR
> > > +
> > > +   to a C++-style cast.
> > > +
> > > +   The primary range of RICHLOC is asssumed to be that of the
> > > original
> > > +   expression.  OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the
> > > locations
> > > +   of the parens in the C-style cast.  */
> > > +
> > > +static void
> > > +maybe_add_cast_fixit (rich_location *rich_loc, location_t
> > > open_paren_loc,
> > > +		      location_t close_paren_loc, tree
> > > orig_expr,
> > > +		      tree dst_type)
> > > +{
> > > +  /* This function is non-trivial, so bail out now if the
> > > warning
> > > isn't
> > > +     going to be emitted.  */
> > > +  if (!warn_old_style_cast)
> > > +    return;
> > > +
> > > +  /* Try to find a legal C++ cast, trying them in order:
> > > +     const_cast, static_cast, reinterpret_cast.  */
> > > +  const char *cast_suggestion = get_cast_suggestion (dst_type,
> > > orig_expr);
> > > +  if (!cast_suggestion)
> > > +    return;
> > > +
> > > +  /* Replace the open paren with "CAST_SUGGESTION<".  */
> > > +  pretty_printer pp;
> > > +  pp_printf (&pp, "%s<", cast_suggestion);
> > > +  rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text
> > > (&pp));
> > > +
> > > +  /* Replace the close paren with "> (".  */
> > > +  rich_loc->add_fixit_replace (close_paren_loc, "> (");
> > > +
> > > +  /* Add a closing paren after the expr (the primary range of
> > > RICH_LOC).  */
> > > +  rich_loc->add_fixit_insert_after (")");
> > > +}
> > > +
> > > +
> > >  /* Parse a cast-expression.
> > >  
> > >     cast-expression:
> > > @@ -8668,6 +8747,7 @@ cp_parser_cast_expression (cp_parser
> > > *parser,
> > > bool address_p, bool cast_p,
> > >        /* Consume the `('.  */
> > >        cp_token *open_paren = cp_lexer_consume_token (parser
> > > ->lexer);
> > >        location_t open_paren_loc = open_paren->location;
> > > +      location_t close_paren_loc = UNKNOWN_LOCATION;
> > >  
> > >        /* A very tricky bit is that `(struct S) { 3 }' is a
> > >  	 compound-literal (which we permit in C++ as an
> > > extension).
> > > @@ -8730,7 +8810,10 @@ cp_parser_cast_expression (cp_parser
> > > *parser,
> > > bool address_p, bool cast_p,
> > >  	  /* Look for the type-id.  */
> > >  	  type = cp_parser_type_id (parser);
> > >  	  /* Look for the closing `)'.  */
> > > -	  cp_parser_require (parser, CPP_CLOSE_PAREN,
> > > RT_CLOSE_PAREN);
> > > +	  cp_token *close_paren
> > > +	    = cp_parser_require (parser, CPP_CLOSE_PAREN,
> > > RT_CLOSE_PAREN);
> > > +	  if (close_paren)
> > > +	    close_paren_loc = close_paren->location;
> > >  	  parser->in_type_id_in_expr_p =
> > > saved_in_type_id_in_expr_p;
> > >  	}
> > >  
> > > @@ -8760,7 +8843,13 @@ cp_parser_cast_expression (cp_parser
> > > *parser,
> > > bool address_p, bool cast_p,
> > >  		  && !in_system_header_at (input_location)
> > >  		  && !VOID_TYPE_P (type)
> > >  		  && current_lang_name != lang_name_c)
> > > -		warning (OPT_Wold_style_cast, "use of old-style
> > > cast");
> > > +		{
> > > +		  gcc_rich_location rich_loc (input_location);
> > > +		  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);
> > > +		}
> > >  
> > >  	      /* Only type conversions to integral or
> > > enumeration
> > > types
> > >  		 can be used in constant-expressions.  */
> > > diff --git a/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> > > b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> > > new file mode 100644
> > > index 0000000..a10b623
> > > --- /dev/null
> > > +++ b/gcc/testsuite/g++.dg/other/old-style-cast-fixits.C
> > > @@ -0,0 +1,95 @@
> > > +// { dg-options "-Wold-style-cast -fdiagnostics-show-caret" }
> > > +
> > > +struct foo {};
> > > +struct bar { const foo *field; };
> > > +
> > > +void test_1 (void *ptr)
> > > +{
> > > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > > +  /* { dg-begin-multiline-output "" }
> > > +   foo *f = (foo *)ptr;
> > > +                   ^~~
> > > +            ----------
> > > +            static_cast<foo *> (ptr)
> > > +     { dg-end-multiline-output "" } */
> > > +}
> > > +
> > > +void test_2 (const foo *ptr)
> > > +{
> > > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > > +  /* { dg-begin-multiline-output "" }
> > > +   foo *f = (foo *)ptr;
> > > +                   ^~~
> > > +            ----------
> > > +            const_cast<foo *> (ptr)
> > > +     { dg-end-multiline-output "" } */
> > > +}
> > > +
> > > +void test_3 (bar *ptr)
> > > +{
> > > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > > +  /* { dg-begin-multiline-output "" }
> > > +   foo *f = (foo *)ptr;
> > > +                   ^~~
> > > +            ----------
> > > +            reinterpret_cast<foo *> (ptr)
> > > +     { dg-end-multiline-output "" } */
> > > +}
> > > +
> > > +void test_4 (bar *ptr)
> > > +{
> > > +  foo *f = (foo *)ptr->field; // { dg-warning "old-style cast" }
> > > +  /* { dg-begin-multiline-output "" }
> > > +   foo *f = (foo *)ptr->field;
> > > +                        ^~~~~
> > > +            -----------------
> > > +            const_cast<foo *> (ptr->field)
> > > +     { dg-end-multiline-output "" } */
> > > +}
> > > +
> > > +void test_5 ()
> > > +{
> > > +  bar b_inst;
> > > +  foo *f = (foo *)&b_inst; // { dg-warning "old-style cast" }
> > > +  /* { dg-begin-multiline-output "" }
> > > +   foo *f = (foo *)&b_inst;
> > > +                    ^~~~~~
> > > +            --------------
> > > +            reinterpret_cast<foo *> (&b_inst)
> > > +     { dg-end-multiline-output "" } */
> > > +}
> > > +
> > > +/* We don't offer suggestions for templates.  */
> > > +
> > > +template <typename T>
> > > +void test_6 (void *ptr)
> > > +{
> > > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > > +  /* { dg-begin-multiline-output "" }
> > > +   foo *f = (foo *)ptr;
> > > +                   ^~~
> > > +     { dg-end-multiline-output "" } */
> > > +}
> > > +
> > > +/* We don't offer suggestions where a single C++-style cast
> > > can't
> > > be
> > > +   used.  */
> > > +
> > > +void test_7 (const void *ptr)
> > > +{
> > > +  foo *f = (foo *)ptr; // { dg-warning "old-style cast" }
> > > +  /* { dg-begin-multiline-output "" }
> > > +   foo *f = (foo *)ptr;
> > > +                   ^~~
> > > +     { dg-end-multiline-output "" } */
> > > +}
> > > +
> > > +/* Likewise, no single C++-style cast is usable here.  */
> > > +
> > > +void test_8 (const bar &b_inst)
> > > +{
> > > +  foo *f = (foo *)&b_inst;  // { dg-warning "old-style cast" }
> > > +  /* { dg-begin-multiline-output "" }
> > > +   foo *f = (foo *)&b_inst;
> > > +                    ^~~~~~
> > > +     { dg-end-multiline-output "" } */
> > > +}

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

* Re: [PATCH] Improved diagnostics for casts and enums
  2017-04-30 17:54     ` Volker Reichelt
@ 2017-06-20 16:10       ` Martin Sebor
  2017-07-10 16:01         ` [PING #2] " Martin Sebor
  0 siblings, 1 reply; 15+ messages in thread
From: Martin Sebor @ 2017-06-20 16:10 UTC (permalink / raw)
  To: Volker Reichelt, gcc-patches; +Cc: Nathan Sidwell, David Malcolm

> So here's the patch that reverts the special enum handling in
> type_to_string and uses %q#T instead of %qT for two casting-related
> diagnostics.
>
> Bootstrapped and regtested on x86_64-pc-linux-gnu.
>
> OK for trunk?

The "E {enum}'" notation is still on trunk so it seems that this
patch has never been committed and I can't find approval of it
in the archive.  To make sure it doesn't get forgotten, please
consider this a ping on Volker's behalf:

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

Thanks
Martin

>
> As one can see from the testsuite changes, there are several
> casting- and conversion-related messages like "invalid conversion from",
> "cannot convert", "invalid cast" that still use the simple %qT
> form. I'll give it a try to use %q#T there as well and prepare a
> separate patch if this really improves the diagnostics.
>
> Regards,
> Volker
>
>
> 2017-04-30  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 247394)
> +++ gcc/cp/parser.c	(working copy)
> @@ -8764,7 +8764,7 @@
>  		  && !VOID_TYPE_P (type)
>  		  && current_lang_name != lang_name_c)
>  		warning (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
>  		 can be used in constant-expressions.  */
> Index: gcc/cp/typeck.c
> ===================================================================
> --- gcc/cp/typeck.c	(revision 247394)
> +++ gcc/cp/typeck.c	(working copy)
> @@ -6631,7 +6631,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 247394)
> +++ gcc/cp/error.c	(working copy)
> @@ -3134,10 +3134,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-04-30  Volker Reichelt  <v.reichelt@netcologne.de>
>
> 	* g++.dg/cpp1z/direct-enum-init1.C: Rever 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 247394)
> +++ 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 } }
> +  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 {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 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 } }
> +  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 {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 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 247394)
> +++ 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] 15+ messages in thread

* Re: [PATCH v2] C++: Add fix-it hints for -Wold-style-cast
  2017-05-03 13:32       ` [PATCH v2] " David Malcolm
  2017-05-26 19:54         ` [PING] re " David Malcolm
@ 2017-06-20 18:39         ` Jason Merrill
  1 sibling, 0 replies; 15+ messages in thread
From: Jason Merrill @ 2017-06-20 18:39 UTC (permalink / raw)
  To: David Malcolm
  Cc: Nathan Sidwell, Marek Polacek, Volker Reichelt, gcc-patches List

On Wed, May 3, 2017 at 9:51 AM, David Malcolm <dmalcolm@redhat.com> wrote:
> On Thu, 2017-04-27 at 23:03 +0200, Marek Polacek wrote:
>> On Thu, Apr 27, 2017 at 05:10:24PM -0400, David Malcolm wrote:
>> > +  /* First try const_cast.  */
>> > +  trial = build_const_cast (dst_type, orig_expr, 0 /* complain
>> > */);
>> > +  if (trial != error_mark_node)
>> > +    return "const_cast";
>> > +
>> > +  /* If that fails, try static_cast.  */
>> > +  trial = build_static_cast (dst_type, orig_expr, 0 /* complain
>> > */);
>> > +  if (trial != error_mark_node)
>> > +    return "static_cast";
>> > +
>> > +  /* Finally, try reinterpret_cast.  */
>> > +  trial = build_reinterpret_cast (dst_type, orig_expr, 0 /*
>> > complain */);
>> > +  if (trial != error_mark_node)
>> > +    return "reinterpret_cast";
>>
>> I think you'll want tf_none instead of 0 /* complain */ in these.
>>
>>       Marek
>
> Thanks.
>
> Here's an updated version of the patch.
>
> Changes since v1:
> - updated expected fixit-formatting (the new fix-it printer in
>   r247548 handles this properly now)
> - added new test cases as suggested by Florian
> - use "tf_none" rather than "0 /* complain */"
>
> Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.
>
> OK for trunk?

OK.

Jason

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

* [PING #2] [PATCH] Improved diagnostics for casts and enums
  2017-06-20 16:10       ` Martin Sebor
@ 2017-07-10 16:01         ` Martin Sebor
  0 siblings, 0 replies; 15+ messages in thread
From: Martin Sebor @ 2017-07-10 16:01 UTC (permalink / raw)
  To: gcc-patches, Nathan Sidwell; +Cc: Volker Reichelt, David Malcolm

Ping #2 of Volker's patch:
   https://gcc.gnu.org/ml/gcc-patches/2017-04/msg01576.html

The patch reverts the format used in the output of enumerated
types from the 'E {enum}' notation introduced in r247347 to just
'E' or to the standard 'enum E' with %#qT.

Nathan, unless you have concerns with or objections to this change,
since you approved r247347, can you please approve this?

Btw., to be consistent, GCC should make use of %#qT for other
kinds of types besides enums so that something like the following:

   struct S { };
   void g (S s) { s = (S)s; }

issues

   warning: useless cast to type ‘struct S’ [-Wuseless-cast]

rather than just

   warning: useless cast to type ‘S’ [-Wuseless-cast]

as it still does now.  More broadly, I wonder if types should
always (or by default) include the class-key or enum keyword
in C++?  In C?

Martin

On 06/20/2017 10:09 AM, Martin Sebor wrote:
>> So here's the patch that reverts the special enum handling in
>> type_to_string and uses %q#T instead of %qT for two casting-related
>> diagnostics.
>>
>> Bootstrapped and regtested on x86_64-pc-linux-gnu.
>>
>> OK for trunk?
>
> The "E {enum}'" notation is still on trunk so it seems that this
> patch has never been committed and I can't find approval of it
> in the archive.  To make sure it doesn't get forgotten, please
> consider this a ping on Volker's behalf:
>
> https://gcc.gnu.org/ml/gcc-patches/2017-04/msg01576.html
>
> Thanks
> Martin
>
>>
>> As one can see from the testsuite changes, there are several
>> casting- and conversion-related messages like "invalid conversion from",
>> "cannot convert", "invalid cast" that still use the simple %qT
>> form. I'll give it a try to use %q#T there as well and prepare a
>> separate patch if this really improves the diagnostics.
>>
>> Regards,
>> Volker
>>
>>
>> 2017-04-30  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 247394)
>> +++ gcc/cp/parser.c    (working copy)
>> @@ -8764,7 +8764,7 @@
>>            && !VOID_TYPE_P (type)
>>            && current_lang_name != lang_name_c)
>>          warning (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
>>           can be used in constant-expressions.  */
>> Index: gcc/cp/typeck.c
>> ===================================================================
>> --- gcc/cp/typeck.c    (revision 247394)
>> +++ gcc/cp/typeck.c    (working copy)
>> @@ -6631,7 +6631,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 247394)
>> +++ gcc/cp/error.c    (working copy)
>> @@ -3134,10 +3134,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-04-30  Volker Reichelt  <v.reichelt@netcologne.de>
>>
>>     * g++.dg/cpp1z/direct-enum-init1.C: Rever 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 247394)
>> +++ 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 } }
>> +  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
>> {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 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 } }
>> +  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
>> {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 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 247394)
>> +++ 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] 15+ messages in thread

end of thread, other threads:[~2017-07-10 16:01 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-27  8:00 [PATCH] Improved diagnostics for casts and enums Volker Reichelt
2017-04-27 12:37 ` Nathan Sidwell
2017-04-27 20:58   ` [PATCH] C++: Add fix-it hints for -Wold-style-cast David Malcolm
2017-04-27 21:05     ` Florian Weimer
2017-04-27 22:05     ` Marek Polacek
2017-05-03 13:32       ` [PATCH v2] " David Malcolm
2017-05-26 19:54         ` [PING] re " David Malcolm
2017-06-05 16:41           ` [PING^2] " David Malcolm
2017-06-20 14:03             ` [PING^3] " David Malcolm
2017-06-20 18:39         ` Jason Merrill
2017-04-27 16:59 ` [PATCH] Improved diagnostics for casts and enums Martin Sebor
2017-04-28  8:42   ` Volker Reichelt
2017-04-30 17:54     ` Volker Reichelt
2017-06-20 16:10       ` Martin Sebor
2017-07-10 16:01         ` [PING #2] " Martin Sebor

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