From fe43c635035edcd29eca0a8e3b08d8bcf14d9ba8 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 30 Apr 2018 17:21:32 -0400 Subject: [PATCH] PR c++/84701 - unsigned typeof. * decl.c (grokdeclarator): Overhaul diagnostics for invalid use of long/short/signed/unsigned. From-SVN: r259780 --- gcc/cp/ChangeLog | 4 ++ gcc/cp/decl.c | 82 +++++++++++++++++----------- gcc/testsuite/g++.dg/cpp1z/decomp3.C | 2 +- gcc/testsuite/g++.dg/ext/typeof13.C | 8 +++ 4 files changed, 62 insertions(+), 34 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/typeof13.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 95f77f4bf98..65f556e0c76 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2018-04-30 Jason Merrill + PR c++/84701 - unsigned typeof. + * decl.c (grokdeclarator): Overhaul diagnostics for invalid use + of long/short/signed/unsigned. + PR c++/85305 - pack in lambda init-capture. * parser.c (cp_parser_initializer): Add subexpression_p parm; don't check_for_bare_parameter_packs in a subexpression. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 07f3a61fed6..6f2fe01d83d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10608,45 +10608,61 @@ grokdeclarator (const cp_declarator *declarator, if (unsigned_p || signed_p || long_p || short_p) { - int ok = 0; - - if ((signed_p || unsigned_p) && TREE_CODE (type) != INTEGER_TYPE) - error ("% or % invalid for %qs", name); - else if (signed_p && unsigned_p) - error ("% and % specified together for %qs", name); - else if (longlong && TREE_CODE (type) != INTEGER_TYPE) - error ("% invalid for %qs", name); - else if (long_p && TREE_CODE (type) == REAL_TYPE) - error ("% invalid for %qs", name); - else if (short_p && TREE_CODE (type) == REAL_TYPE) - error ("% invalid for %qs", name); - else if ((long_p || short_p) && TREE_CODE (type) != INTEGER_TYPE) - error ("% or % invalid for %qs", name); - else if ((long_p || short_p || explicit_char || explicit_int) && explicit_intN) - error ("%, %, %, or % invalid for %qs", name); - else if ((long_p || short_p) && explicit_char) - error ("% or % specified with char for %qs", name); - else if (long_p && short_p) - error ("% and % specified together for %qs", name); - else if (type == char16_type_node || type == char32_type_node) + location_t loc; + const char *key; + if (unsigned_p) { - if (signed_p || unsigned_p) - error ("% or % invalid for %qs", name); - else if (short_p || long_p) - error ("% or % invalid for %qs", name); + key = "unsigned"; + loc = declspecs->locations[ds_unsigned]; } - else + else if (signed_p) + { + key = "signed"; + loc = declspecs->locations[ds_signed]; + } + else if (longlong) + { + key = "long long"; + loc = declspecs->locations[ds_long_long]; + } + else if (long_p) { - ok = 1; - if (!explicit_int && !defaulted_int && !explicit_char && !explicit_intN && pedantic) + key = "long"; + loc = declspecs->locations[ds_long]; + } + else /* if (short_p) */ + { + key = "short"; + loc = declspecs->locations[ds_short]; + } + + int ok = 0; + + if (signed_p && unsigned_p) + error_at (loc, "% and % specified together"); + else if (long_p && short_p) + error_at (loc, "% and % specified together"); + else if (TREE_CODE (type) != INTEGER_TYPE + || type == char16_type_node || type == char32_type_node + || ((long_p || short_p) + && (explicit_char || explicit_intN))) + error_at (loc, "%qs specified with %qT", key, type); + else if (!explicit_int && !defaulted_int + && !explicit_char && !explicit_intN) + { + if (typedef_decl) { - pedwarn (input_location, OPT_Wpedantic, - "long, short, signed or unsigned used invalidly for %qs", - name); - if (flag_pedantic_errors) - ok = 0; + pedwarn (loc, OPT_Wpedantic, "%qs specified with %qT", + key, type); + ok = !flag_pedantic_errors; } + else if (declspecs->decltype_p) + error_at (loc, "%qs specified with %", key); + else + error_at (loc, "%qs specified with %", key); } + else + ok = 1; /* Discard the type modifiers if they are invalid. */ if (! ok) diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C index 1886cdbe90d..4d75e938098 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp3.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp3.C @@ -29,7 +29,7 @@ test (A &b, B c) // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } __restrict auto [ t ] = c; // { dg-error "invalid use of 'restrict'" } // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } - long long auto [ u ] = c; // { dg-error "'long long' invalid for 'structured binding'" } + long long auto [ u ] = c; // { dg-error "'long long' specified with 'auto'" } // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } virtual auto [ v ] = c; // { dg-error "'virtual' outside class declaration" } // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } diff --git a/gcc/testsuite/g++.dg/ext/typeof13.C b/gcc/testsuite/g++.dg/ext/typeof13.C new file mode 100644 index 00000000000..820d50d23a3 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/typeof13.C @@ -0,0 +1,8 @@ +// PR c++/84701 +// { dg-options "-pedantic" } + +typedef short foo_t; +foo_t s = -1; /* FFFF */ + +unsigned u = (unsigned foo_t)s; // { dg-warning foo_t } +unsigned u2 = (unsigned __typeof(s))s; // { dg-error typeof } -- 2.30.2