Bug 65801

Summary: [5/6 Regression] Allow -Wno-narrowing to silence stricter C++11 narrowing rules
Product: gcc Reporter: Jan Engelhardt <jengelh>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: enhancement CC: allan, egallager, jakub, jason, manu, paolo.carlini, redi
Priority: P3 Keywords: diagnostic
Version: 5.0   
Target Milestone: 5.2   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2015-04-18 00:00:00
Attachments: Draft patch
Draft patch 2

Description Jan Engelhardt 2015-04-18 18:00:32 UTC
This code:
---8<---
static struct zai { unsigned int x; } x = {-1};
--->8---
gives this error in C++11 mode:

$ g++-5  -std=gnu++11 -c y.cpp
y.cpp:1:46: error: narrowing conversion of ‘-1’ from ‘int’ to ‘unsigned int’ inside { }


Clang 3.5 offers using -Wno-narrowing to ignore this and continue with the previous semantics of silently converting it, which is helpful if one's C++11 project has to include e.g. zend_API.h (which uses the -1 conversion).

Such a feature is missing from gcc.

$ gcc-5 -v
gcc version 5.0.1 20150416 (prerelease) [gcc-5-branch revision 222148] (SUSE Linux)
Comment 1 Markus Trippelsdorf 2015-04-18 18:47:41 UTC
Yes. This also breaks building Chromium.

markus@x4 ~ % echo "int main () {int i = { 0xFFFFFFFF };}" | g++ -std=c++11 -Wno-narrowing -x c++ -
<stdin>: In function ‘int main()’:
<stdin>:1:35: error: narrowing conversion of ‘4294967295u’ from ‘unsigned int’ to ‘int’ inside { }

While the standard is clear that this is an error,
accepting -Wno-narrowing as in 4.8, 4.9 and clang looks acceptable to me.
Comment 2 Jason Merrill 2015-04-20 03:58:01 UTC
This changed with Paolo's r213776.  These examples suggest that the change to constant handling WRT -Wnarrowing was a mistake.
Comment 3 Paolo Carlini 2015-04-20 09:41:40 UTC
Ok, thus what shall we do? Shall we go back to my minimal patch which only touched enums? https://gcc.gnu.org/ml/gcc-patches/2014-08/msg00880.html
Comment 4 Marek Polacek 2015-04-20 09:48:46 UTC
Couldn't you simply turn the error_at into pedwarn?
Comment 5 Paolo Carlini 2015-04-20 10:21:05 UTC
Well, at the time I think we agreed that we wanted to be strict at least about enums... Otherwise, yes, we can do that plus setting ok = true in that case too, thus collapsing the last two ifs (+ reverting the docs change and adjusting the testsuite).
Comment 6 Jason Merrill 2015-04-20 15:02:05 UTC
(In reply to Paolo Carlini from comment #5)
> Well, at the time I think we agreed that we wanted to be strict at least
> about enums... Otherwise, yes, we can do that plus setting ok = true in that
> case too, thus collapsing the last two ifs (+ reverting the docs change and
> adjusting the testsuite).

I think that for constants, we want it to be an error without -Wno-narrowing.  I wonder if the best way to get that is to set pedantic_errors around the pedwarn call?
Comment 7 Paolo Carlini 2015-04-20 15:04:52 UTC
Yes, I was thinking that in such cases clang does something we don't normally do (ie, an hard error by default suppressible with a -Wno-*). Let me see if we can achieve that as you suggested.
Comment 8 Paolo Carlini 2015-04-20 15:29:26 UTC
Jason, as far as I can see *nowhere* else in the compiler we fiddle with flag_pedantic_errors, all the tweaks I tried look super hackish to me :( If we are Ok with just going back to pedwarns the attached passes testing...
Comment 9 Paolo Carlini 2015-04-20 15:30:37 UTC
Created attachment 35367 [details]
Draft patch
Comment 10 Paolo Carlini 2015-04-20 19:20:24 UTC
I'm also attaching what I have for the forced pedantic-errors idea.
Comment 11 Paolo Carlini 2015-04-20 19:21:06 UTC
Created attachment 35370 [details]
Draft patch 2
Comment 12 Jason Merrill 2015-04-20 20:30:09 UTC
(In reply to Paolo Carlini from comment #11)
> Draft patch 2

I think let's go with this.  It's odd, but not complex and does what we want.
Comment 13 Paolo Carlini 2015-04-20 20:45:53 UTC
Ok, I'll commit it in an hour or so to trunk. Is it too late for 5.1?
Comment 14 Jakub Jelinek 2015-04-20 20:47:59 UTC
(In reply to Paolo Carlini from comment #13)
> Ok, I'll commit it in an hour or so to trunk. Is it too late for 5.1?

It is IMHO too late for that, but not too late for 5.2.
Comment 15 paolo@gcc.gnu.org 2015-04-20 21:47:30 UTC
Author: paolo
Date: Mon Apr 20 21:46:59 2015
New Revision: 222249

URL: https://gcc.gnu.org/viewcvs?rev=222249&root=gcc&view=rev
Log:
/cp
2015-04-20  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/65801
	* typeck2.c (check_narrowing): In C++11 mode too, -Wno-narrowing
	suppresses the diagnostic.

2015-04-20  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/65801
	* doc/invoke.texi ([-Wnarrowing]): Update.

/testsuite
2015-04-20  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/65801
	* g++.dg/cpp0x/Wnarrowing2.C: New.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/Wnarrowing2.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/typeck2.c
    trunk/gcc/doc/invoke.texi
    trunk/gcc/testsuite/ChangeLog
Comment 16 Manuel López-Ibáñez 2015-04-21 10:51:30 UTC
What is printed with -Wno-error=narrowing ?
Comment 17 Markus Trippelsdorf 2015-04-21 11:03:08 UTC
(In reply to Manuel López-Ibáñez from comment #16)
> What is printed with -Wno-error=narrowing ?

Try it yourself?
Just a warning.
Comment 18 Manuel López-Ibáñez 2015-04-21 11:09:24 UTC
(In reply to Manuel López-Ibáñez from comment #16)
> What is printed with -Wno-error=narrowing ?

I'm also a bit afraid of how setting pedantic-errors in this way interacts with the #pragma GCC diagnostics. Wouldn't it be better to reclassify -Wnarrowing as an error (see diagnostic_classify_diagnostic) then simulate a #pragma GCC diagnostics pop to restore the previous state? The problem is the order in which the re-classification happens, which should appear as if it happened in the command-line and not at the point of warning, but diagnostic_classify_diagnostic assumes #pragmas are handled in the order given in the source code.

Another alternative, perhaps simpler, would be to have a different option -Wnarrowing-strict, which by default is -Werror=narrowing-strict (see Werror-implicit-function-declaration) and it is enabled by -Wnarrowing. This way, everything should work as expected (unless latent bugs in the options handling machinery for not passing the error/warning state correctly when enabling dependant options).

An even simpler options is to put this under -fpermissive so people realize that what they are doing is very wrong according to the standard (if it is not very wrong, then why error and not just pedwarn?).
Comment 19 Manuel López-Ibáñez 2015-04-21 11:10:37 UTC
(In reply to Markus Trippelsdorf from comment #17)
> (In reply to Manuel López-Ibáñez from comment #16)
> > What is printed with -Wno-error=narrowing ?
> 
> Try it yourself?
> Just a warning.

Thanks, well at least that works. I guess if someone notices a problem with the #pragmas, a better solution can be found later.
Comment 20 Jonathan Wakely 2015-04-21 11:17:51 UTC
The problem with -fpermissive is that it doesn't just allow things like narrowing that are valid in C++03 but also allows all kind of ancient constructs that no sane person wants.
Comment 21 paolo@gcc.gnu.org 2015-04-30 16:32:08 UTC
Author: paolo
Date: Thu Apr 30 16:31:36 2015
New Revision: 222636

URL: https://gcc.gnu.org/viewcvs?rev=222636&root=gcc&view=rev
Log:
/cp
2015-04-30  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/65801
	* typeck2.c (check_narrowing): In C++11 mode too, -Wno-narrowing
	suppresses the diagnostic.

2015-04-30  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/65801
	* doc/invoke.texi ([-Wnarrowing]): Update.

/testsuite
2015-04-30  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/65801
	* g++.dg/cpp0x/Wnarrowing2.C: New.

Added:
    branches/gcc-5-branch/gcc/testsuite/g++.dg/cpp0x/Wnarrowing2.C
Modified:
    branches/gcc-5-branch/gcc/ChangeLog
    branches/gcc-5-branch/gcc/cp/ChangeLog
    branches/gcc-5-branch/gcc/cp/typeck2.c
    branches/gcc-5-branch/gcc/doc/invoke.texi
    branches/gcc-5-branch/gcc/testsuite/ChangeLog
Comment 22 Paolo Carlini 2015-04-30 16:33:05 UTC
Fixed for 5.2 too.
Comment 23 Evangelos Foutras 2015-05-04 14:20:40 UTC
Please note that narrowing conversions don't seem to work the same way they did in GCC 4.9; I've filed PR c++/66007 for this change in behavior.