* [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
* [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®rtested 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
* [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®rtested 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®rtested 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®rtested 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®rtested 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 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®rtested on x86_64-pc-linux-gnu. > > OK for trunk? OK. Jason ^ 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
* 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
* 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
* [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).