OK.
On Thu, Sep 29, 2016 at 4:21 PM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > This patch pedwarns in C++17 on register storage class specifier, unless > it is diagnosed errorneous for other reasons and unless it is used in the > GNU global or local register variable extension. Even in C++17, users can > use -Wno-register to suppress the pedwarn, and for C++98-C++14 users can on > the other side use -Wregister to get warning about it. Clang seems to > warn/error out similarly on variables with register storage class under > -Wregister too, is quiet about the uses in register int var __asm ("...") > (global and local), though strangely doesn't complain about register > keywords on function arguments, which this patch diagnoses. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2016-09-29 Jakub Jelinek <ja...@redhat.com> > > Implement P0001R1 - C++17 removal of register storage class specifier > c-family/ > * c.opt (Wregister): New warning. > * c-opts.c (c_common_post_options): Enable -Wregister by > default for C++17. > cp/ > * decl.c (cp_finish_decl): Diagnose register storage class > on vars except when used in GNU global or local register variable > extension. > (grokdeclarator): Diagnose register storage class on parameters. > * except.c (expand_start_catch_block): Set DECL_REGISTER only > after cp_finish_decl call. > testsuite/ > * c-c++-common/Wvarargs-2.c (foo1): Except new warning for C++17. > * c-c++-common/vector-subscript-2.c (vf): Expect new error for > C++17. > * c-c++-common/vector-subscript-5.c (foo): Don't use register > keyword if not __SSE2__. > * c-c++-common/Wvarargs.c (foo1, foo3): Expect new warnings for > C++17. > * g++.dg/compat/struct-layout-1_generate.c (iterative_hash): Remove > register keywords. > * g++.dg/eh/pr29166.C: Add -Wno-register option. > * g++.dg/warn/register-parm-1.C (erroneous_warning, > no_erroneous_warning): Expect new warnings for C++17. > * g++.dg/warn/register-var-2.C (f): Likewise. > * g++.dg/parse/register1.C (f): Expect new error for C++17. > * g++.dg/parse/linkage2.C (foo): Likewise. > * g++.dg/torture/pr36826.C (CoinMin, CoinMax): Avoid register > keyword on parameters for C++17. > * g++.dg/cpp1z/register1.C: New test. > * g++.dg/cpp1z/register2.C: New test. > * g++.dg/cpp1z/register3.C: New test. > > --- gcc/c-family/c.opt.jj 2016-09-26 12:06:37.000000000 +0200 > +++ gcc/c-family/c.opt 2016-09-29 14:54:17.712047430 +0200 > @@ -842,6 +842,10 @@ Wredundant-decls > C ObjC C++ ObjC++ Var(warn_redundant_decls) Warning > Warn about multiple declarations of the same object. > > +Wregister > +C++ ObjC++ Var(warn_register) Warning > +Warn about uses of register storage specifier. > + > Wreorder > C++ ObjC++ Var(warn_reorder) Warning LangEnabledBy(C++ ObjC++,Wall) > Warn when the compiler reorders code. > --- gcc/c-family/c-opts.c.jj 2016-08-19 11:04:38.000000000 +0200 > +++ gcc/c-family/c-opts.c 2016-09-29 15:06:06.213254295 +0200 > @@ -871,6 +871,10 @@ c_common_post_options (const char **pfil > warn_shift_negative_value = (extra_warnings > && (cxx_dialect >= cxx11 || flag_isoc99)); > > + /* -Wregister is enabled by default in C++17. */ > + if (!global_options_set.x_warn_register) > + warn_register = cxx_dialect >= cxx1z; > + > /* Declone C++ 'structors if -Os. */ > if (flag_declone_ctor_dtor == -1) > flag_declone_ctor_dtor = optimize_size; > --- gcc/cp/decl.c.jj 2016-09-23 19:37:41.000000000 +0200 > +++ gcc/cp/decl.c 2016-09-29 16:05:03.724470275 +0200 > @@ -6711,6 +6711,19 @@ cp_finish_decl (tree decl, tree init, bo > if (type == error_mark_node) > return; > > + /* Warn about register storage specifiers except when in GNU global > + or local register variable extension. */ > + if (VAR_P (decl) && DECL_REGISTER (decl) && asmspec_tree == NULL_TREE) > + { > + if (cxx_dialect >= cxx1z) > + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wregister, > + "ISO C++1z does not allow %<register%> storage " > + "class specifier"); > + else > + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wregister, > + "%<register%> storage class specifier used"); > + } > + > /* If a name was specified, get the string. */ > if (at_namespace_scope_p ()) > asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree); > @@ -11634,7 +11647,20 @@ grokdeclarator (const cp_declarator *dec > and in case doing stupid register allocation. */ > > if (storage_class == sc_register) > - DECL_REGISTER (decl) = 1; > + { > + DECL_REGISTER (decl) = 1; > + /* Warn about register storage specifiers on PARM_DECLs. */ > + if (TREE_CODE (decl) == PARM_DECL) > + { > + if (cxx_dialect >= cxx1z) > + pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wregister, > + "ISO C++1z does not allow %<register%> storage " > + "class specifier"); > + else > + warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wregister, > + "%<register%> storage class specifier used"); > + } > + } > else if (storage_class == sc_extern) > DECL_THIS_EXTERN (decl) = 1; > else if (storage_class == sc_static) > --- gcc/cp/except.c.jj 2016-04-28 21:03:09.000000000 +0200 > +++ gcc/cp/except.c 2016-09-29 15:08:49.891226456 +0200 > @@ -540,9 +540,9 @@ expand_start_catch_block (tree decl) > if (init_type != TREE_TYPE (init)) > init = build1 (NOP_EXPR, init_type, init); > exp = create_temporary_var (init_type); > - DECL_REGISTER (exp) = 1; > cp_finish_decl (exp, init, /*init_const_expr=*/false, > NULL_TREE, LOOKUP_ONLYCONVERTING); > + DECL_REGISTER (exp) = 1; > initialize_handler_parm (decl, exp); > } > > --- gcc/testsuite/c-c++-common/Wvarargs-2.c.jj 2012-05-02 09:38:12.000000000 > +0200 > +++ gcc/testsuite/c-c++-common/Wvarargs-2.c 2016-09-29 16:27:44.273604641 > +0200 > @@ -23,7 +23,7 @@ foo0 (int a, int b, ...) > } > > void > -foo1 (int a, register int b, ...) > +foo1 (int a, register int b, ...) // { dg-warning "ISO C\\+\\+1z does > not allow 'register' storage class specifier" "" { target c++1z } } > { > va_list vp; > /* 'b' is declared with register storage, but don't warn > --- gcc/testsuite/c-c++-common/vector-subscript-2.c.jj 2012-05-02 > 09:38:12.000000000 +0200 > +++ gcc/testsuite/c-c++-common/vector-subscript-2.c 2016-09-29 > 16:00:38.539756931 +0200 > @@ -7,6 +7,6 @@ > > float vf(int i) > { > - register vector float a; > + register vector float a; // { dg-error "ISO C++1z does not allow > 'register' storage class specifier" "" { target c++1z } } > return a[0]; > } > --- gcc/testsuite/c-c++-common/vector-subscript-5.c.jj 2016-05-24 > 18:14:11.000000000 +0200 > +++ gcc/testsuite/c-c++-common/vector-subscript-5.c 2016-09-29 > 16:01:31.002106721 +0200 > @@ -5,7 +5,10 @@ typedef int U __attribute__ ((vector_siz > int > foo (int i) > { > - register U u > +#if __SSE2__ > + register > +#endif > + U u > #if __SSE2__ > asm ("xmm0") > #endif > --- gcc/testsuite/c-c++-common/Wvarargs.c.jj 2016-02-12 00:50:55.000000000 > +0100 > +++ gcc/testsuite/c-c++-common/Wvarargs.c 2016-09-29 16:29:07.213576262 > +0200 > @@ -23,7 +23,7 @@ foo0 (int a, int b, ...) > } > > void > -foo1 (int a, register int b, ...) > +foo1 (int a, register int b, ...) // { dg-warning "ISO C\\+\\+1z does > not allow 'register' storage class specifier" "" { target c++1z } } > { > va_list vp; > /* 'b' is declared with register storage, but don't warn > @@ -45,7 +45,7 @@ foo2 (int a, int b, ...) > } > > void > -foo3 (int a, register int b, ...) > +foo3 (int a, register int b, ...) // { dg-warning "ISO C\\+\\+1z does > not allow 'register' storage class specifier" "" { target c++1z } } > { > va_list vp; > /* 'b' is declared with register storage, so warn. */ > --- gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c.jj 2015-12-16 > 09:02:09.000000000 +0100 > +++ gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c 2016-09-29 > 15:42:13.290440870 +0200 > @@ -1028,12 +1028,12 @@ acceptable. Do NOT use for cryptographi > > static hashval_t > iterative_hash (const void *k_in /* the key */, > - register size_t length /* the length of the key */, > - register hashval_t initval /* the previous hash, or > - an arbitrary value */) > + size_t length /* the length of the key */, > + hashval_t initval /* the previous hash, or > + an arbitrary value */) > { > - register const unsigned char *k = (const unsigned char *)k_in; > - register hashval_t a,b,c,len; > + const unsigned char *k = (const unsigned char *)k_in; > + hashval_t a,b,c,len; > > /* Set up the internal state */ > len = length; > --- gcc/testsuite/g++.dg/eh/pr29166.C.jj 2008-09-05 12:55:05.000000000 > +0200 > +++ gcc/testsuite/g++.dg/eh/pr29166.C 2016-09-29 15:42:51.224971251 +0200 > @@ -1,5 +1,6 @@ > // PR 29166: r4-r7 corrupted when unwinding. > // { dg-do run } > +// { dg-additional-options "-Wno-register" } > > class Ex > { > --- gcc/testsuite/g++.dg/warn/register-parm-1.C.jj 2014-12-19 > 13:18:35.000000000 +0100 > +++ gcc/testsuite/g++.dg/warn/register-parm-1.C 2016-09-29 16:20:31.061976063 > +0200 > @@ -1,9 +1,9 @@ > // PR c++/60955 > // { dg-options "-Wextra" } > > -unsigned int erroneous_warning(register int a) { > +unsigned int erroneous_warning(register int a) { // { dg-warning "ISO > C\\+\\+1z does not allow 'register' storage class specifier" "" { target > c++1z } } > if ((a) & 0xff) return 1; else return 0; > } > -unsigned int no_erroneous_warning(register int a) { > +unsigned int no_erroneous_warning(register int a) { // { dg-warning "ISO > C\\+\\+1z does not allow 'register' storage class specifier" "" { target > c++1z } } > if (a & 0xff) return 1; else return 0; > } > --- gcc/testsuite/g++.dg/warn/register-var-2.C.jj 2008-09-05 > 12:55:03.000000000 +0200 > +++ gcc/testsuite/g++.dg/warn/register-var-2.C 2016-09-29 16:16:29.313973189 > +0200 > @@ -9,6 +9,6 @@ void g(int *); > > void f(void) > { > - register int x; > + register int x; /* { dg-warning "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } */ > g(&x); /* { dg-warning "address requested for 'x', which is declared > 'register'" } */ > } > --- gcc/testsuite/g++.dg/parse/register1.C.jj 2008-09-05 12:55:04.000000000 > +0200 > +++ gcc/testsuite/g++.dg/parse/register1.C 2016-09-29 16:16:25.642018699 > +0200 > @@ -8,7 +8,7 @@ public: > operator int() { return i; } > }; > > -C f (register C x) > +C f (register C x) // { dg-error "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } > { > return x + 31; > } > --- gcc/testsuite/g++.dg/parse/linkage2.C.jj 2008-09-05 12:55:04.000000000 > +0200 > +++ gcc/testsuite/g++.dg/parse/linkage2.C 2016-09-29 16:16:23.164049410 > +0200 > @@ -1,3 +1,3 @@ > // PR c++/27884 > > -extern "C" void foo(register int *my_perl); > +extern "C" void foo(register int *my_perl); // { dg-error "ISO C\\+\\+1z > does not allow 'register' storage class specifier" "" { target c++1z } } > --- gcc/testsuite/g++.dg/torture/pr36826.C.jj 2008-10-23 13:21:06.000000000 > +0200 > +++ gcc/testsuite/g++.dg/torture/pr36826.C 2016-09-29 15:54:18.920457225 > +0200 > @@ -1,5 +1,10 @@ > +#if __cplusplus > 201402L > +template <class T> T CoinMax(const T x1, const T x2); > +template <class T> T CoinMin(const T x1, const T x2); > +#else > template <class T> T CoinMax(register const T x1, register const T x2); > template <class T> T CoinMin(register const T x1, register const T x2); > +#endif > class CoinIndexedVector; > class ClpModel { > protected: > --- gcc/testsuite/g++.dg/cpp1z/register1.C.jj 2016-09-29 15:38:59.976834015 > +0200 > +++ gcc/testsuite/g++.dg/cpp1z/register1.C 2016-09-29 16:15:12.972919348 > +0200 > @@ -0,0 +1,29 @@ > +// P0001R1 - C++17 removal of register keyword > +// { dg-do compile } > + > +#if defined(__i386__) || defined(__x86_64__) > +#define REG1 "ebx" > +#define REG2 "edi" > +#endif > + > +#ifdef REG1 > +register int a __asm (REG1); // { dg-bogus "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } > +#endif > +register int b; // { dg-error "ISO C\\+\\+1z does not > allow 'register' storage class specifier" "" { target c++1z } } > +register int c (); // { dg-error "storage class 'register' > invalid for function" } > +int foo (register int d) // { dg-error "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } > +{ > + return d; > +} > +int bar () > +{ > +#ifdef REG2 > + register int e __asm (REG2); // { dg-bogus "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } > +#else > + int e; > +#endif > + register int f; // { dg-error "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } > + e = 6; > + f = 7; > + return e + f; > +} > --- gcc/testsuite/g++.dg/cpp1z/register2.C.jj 2016-09-29 15:39:44.739279874 > +0200 > +++ gcc/testsuite/g++.dg/cpp1z/register2.C 2016-09-29 16:15:35.781636660 > +0200 > @@ -0,0 +1,30 @@ > +// P0001R1 - C++17 removal of register keyword > +// { dg-do compile } > +// { dg-options "-Wno-register" } > + > +#if defined(__i386__) || defined(__x86_64__) > +#define REG1 "ebx" > +#define REG2 "edi" > +#endif > + > +#ifdef REG1 > +register int a __asm (REG1); // { dg-bogus "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } > +#endif > +register int b; // { dg-bogus "ISO C\\+\\+1z does not > allow 'register' storage class specifier" "" { target c++1z } } > +register int c (); // { dg-error "storage class 'register' > invalid for function" } > +int foo (register int d) // { dg-bogus "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } > +{ > + return d; > +} > +int bar () > +{ > +#ifdef REG2 > + register int e __asm (REG2); // { dg-bogus "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } > +#else > + int e; > +#endif > + register int f; // { dg-bogus "ISO C\\+\\+1z does not allow > 'register' storage class specifier" "" { target c++1z } } > + e = 6; > + f = 7; > + return e + f; > +} > --- gcc/testsuite/g++.dg/cpp1z/register3.C.jj 2016-09-29 15:40:32.064694004 > +0200 > +++ gcc/testsuite/g++.dg/cpp1z/register3.C 2016-09-29 16:24:04.311331969 > +0200 > @@ -0,0 +1,30 @@ > +// P0001R1 - C++17 removal of register keyword > +// { dg-do compile { target c++14_down } } > +// { dg-options "-Wregister" } > + > +#if defined(__i386__) || defined(__x86_64__) > +#define REG1 "ebx" > +#define REG2 "edi" > +#endif > + > +#ifdef REG1 > +register int a __asm (REG1); // { dg-bogus "'register' storage class > specifier used" } > +#endif > +register int b; // { dg-warning "'register' storage > class specifier used" } > +register int c (); // { dg-error "storage class 'register' > invalid for function" } > +int foo (register int d) // { dg-warning "'register' storage class > specifier used" } > +{ > + return d; > +} > +int bar () > +{ > +#ifdef REG2 > + register int e __asm (REG2); // { dg-bogus "'register' storage class > specifier used" } > +#else > + int e; > +#endif > + register int f; // { dg-warning "'register' storage class > specifier used" } > + e = 6; > + f = 7; > + return e + f; > +} > > Jakub