This short snippet, when compiled with GCC4.9.0 and -Wextra and -std=c++1y, gives an erroneous warning about taking the address of a register: === $ cat test2.cc // compile with -Wextra -std=c++1y unsigned int erroneous_warning(register int a) { if ((a) & 0xff) return 1; else return 0; } unsigned int no_erroneous_warning(register int a) { if (a & 0xff) return 1; else return 0; } $ g++ -Wextra -std=c++11 -c test2.cc test2.cc: In function ‘unsigned int erroneous_warning(int)’: test2.cc:3:10: warning: address requested for ‘a’, which is declared ‘register’ [-Wextra] if ((a) & 0xff) return 1; else return 0; ^ $ g++ -v Using built-in specs. COLLECT_GCC=/home/mgodbolt/.fighome/runtime/gcc/4.9.0-2/bin/g++ COLLECT_LTO_WRAPPER=/mnt/data/fighome/runtime/gcc/4.9.0-2/bin/../libexec/gcc/x86_64-linux-gnu/4.9.0/lto-wrapper Target: x86_64-linux-gnu Configured with: ../gcc-4.9.0/configure --prefix /data/teamcity/work/sud-chibld05-002-RHEL6/9d49ff0b2777552a/scratch/gcc/4.9.0/staging --build=x86_64-linux-gnu --disable-multilibs --enable-clocale=gnu --enable-languages=c,c++ --enable-ld=yes --enable-gold=yes --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-linker-build-id --enable-lto --enable-plugins --enable-threads=posix --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-pkgversion=DRW-internal-build --with-system-zlib --disable-werror --with-libelf=/data/teamcity/work/sud-chibld05-002-RHEL6/9d49ff0b2777552a/scratch/gcc/4.9.0/build/libelf-0.8.13 Thread model: posix gcc version 4.9.0 (DRW-internal-build) === When compiled with -std=c++11 the warning disappears. Note the extra parentheses are also needed to trigger the warning.
The previous snippet wasn't quite as minimal as it could be. This single line also reproduces it: unsigned int erroneous_warning(register int a) { return (a); } Jonathan Wakely mentioned this may be related to this bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57573
This is caused by the implementation of C++1y decltype(auto), where seemingly redundant parentheses around an identifier must not simply be removed, because they may be significant. int a; decltype(auto) b = a; // means int b = a; decltype(auto) c = (a); // means int &c = a; GCC implements this by transforming (a) into static_cast<int &>(a) (force_paren_expr in gcc/cp/semantics.c), which would normally be a no-op, but causes the warning when a is declared using the "register" keyword.
(In reply to Harald van Dijk from comment #2) > This is caused by the implementation of C++1y decltype(auto), where > seemingly redundant parentheses around an identifier must not simply be > removed, because they may be significant. > > int a; > decltype(auto) b = a; // means int b = a; > decltype(auto) c = (a); // means int &c = a; > > GCC implements this by transforming (a) into static_cast<int &>(a) > (force_paren_expr in gcc/cp/semantics.c), which would normally be a no-op, > but causes the warning when a is declared using the "register" keyword. It is pretty awful that C++14 has made extra parentheses to become significant. But yes, this explains this bug and also PR57573. It would be nice if expressions could be marked as compiler-generated, like we have DECL_ARTIFICIAL for declarations. But you could set TREE_NO_WARNING(expr) = true and check that in the warning code.
Perhaps also this special case could also be removed by using TREE_NO_WARNING. diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index c91612c..d8374d9 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6291,7 +6291,10 @@ maybe_warn_about_useless_cast (tree type, tree expr, tsubst_flags_t complain) if (warn_useless_cast && complain & tf_warning) { - if (REFERENCE_REF_P (expr)) + /* In C++14 mode, this interacts badly with force_paren_expr. And it + isn't necessary in any mode, because the code below handles + glvalues properly. For 4.9, just skip it in C++14 mode. */ + if (cxx_dialect < cxx1y && REFERENCE_REF_P (expr)) expr = TREE_OPERAND (expr, 0);
This is a regression. Manuel, are you going to pursue the issue further and send to the mailing list a complete patch?
(In reply to Paolo Carlini from comment #5) > This is a regression. Manuel, are you going to pursue the issue further and > send to the mailing list a complete patch? I don't even remember the details of this. The above doesn't actually look like a patch of mine, perhaps the patch that introduced the regression?
I think you are right. Now I wonder if the comment means that for the next release series, aka current mainline, we can seriously try to remove the whole conditional...
Author: paolo Date: Thu Dec 18 17:53:55 2014 New Revision: 218871 URL: https://gcc.gnu.org/viewcvs?rev=218871&root=gcc&view=rev Log: /cp 2014-12-18 Paolo Carlini <paolo.carlini@oracle.com> PR c++/60955 * pt.c (struct warning_sentinel): Move it... * cp-tree.h: ... here. * semantics.c (force_paren_expr): Use it. /testsuite 2014-12-18 Paolo Carlini <paolo.carlini@oracle.com> PR c++/60955 * g++.dg/warn/register-parm-1.C: New. Added: trunk/gcc/testsuite/g++.dg/warn/register-parm-1.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-tree.h trunk/gcc/cp/pt.c trunk/gcc/cp/semantics.c trunk/gcc/testsuite/ChangeLog
Author: paolo Date: Fri Dec 19 09:13:05 2014 New Revision: 218894 URL: https://gcc.gnu.org/viewcvs?rev=218894&root=gcc&view=rev Log: /cp 2014-12-19 Paolo Carlini <paolo.carlini@oracle.com> PR c++/60955 * pt.c (struct warning_sentinel): Move it... * cp-tree.h: ... here. * semantics.c (force_paren_expr): Use it. /testsuite 2014-12-19 Paolo Carlini <paolo.carlini@oracle.com> PR c++/60955 * g++.dg/warn/register-parm-1.C: New. Added: branches/gcc-4_9-branch/gcc/testsuite/g++.dg/warn/register-parm-1.C Modified: branches/gcc-4_9-branch/gcc/cp/ChangeLog branches/gcc-4_9-branch/gcc/cp/cp-tree.h branches/gcc-4_9-branch/gcc/cp/pt.c branches/gcc-4_9-branch/gcc/cp/semantics.c branches/gcc-4_9-branch/gcc/testsuite/ChangeLog
Fixed mainline and 4.9.3.