Bug 60955 - [4.9/5 Regression] Erroneous warning about taking address of register with std=c++1y
Summary: [4.9/5 Regression] Erroneous warning about taking address of register with st...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: 4.9.3
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-04-24 19:09 UTC by Matt Godbolt
Modified: 2014-12-19 09:25 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-04-26 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matt Godbolt 2014-04-24 19:09:24 UTC
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.
Comment 1 Matt Godbolt 2014-04-24 19:36:23 UTC
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
Comment 2 Harald van Dijk 2014-04-26 15:44:56 UTC
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.
Comment 3 Manuel López-Ibáñez 2014-04-26 16:40:37 UTC
(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.
Comment 4 Manuel López-Ibáñez 2014-04-26 16:42:28 UTC
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);
Comment 5 Paolo Carlini 2014-12-05 11:55:29 UTC
This is a regression. Manuel, are you going to pursue the issue further and send to the mailing list a complete patch?
Comment 6 Manuel López-Ibáñez 2014-12-05 12:16:59 UTC
(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?
Comment 7 Paolo Carlini 2014-12-10 16:24:23 UTC
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...
Comment 8 paolo@gcc.gnu.org 2014-12-18 17:54:27 UTC
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
Comment 9 paolo@gcc.gnu.org 2014-12-19 09:13:38 UTC
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
Comment 10 Paolo Carlini 2014-12-19 09:25:21 UTC
Fixed mainline and 4.9.3.