Why is this narrowing conversion not detected?
Asked Answered
T

1

16

when constructing variables using the list-initialization (like int x{ 5 };) the standard §8.5.4 says:

If a narrowing conversion […] is required to convert any of the arguments, the program is ill-formed. (7) A narrowing conversion is an implicit conversion - (7.4) from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.

So why does this compile?

char c{ 'A' };
char x{ c + c };

As a reminder, c + c yields an int

static_assert(std::is_same_v<decltype(c + c), int>, "");

so the compiler should complain about a narrowing conversion which is certainly not a constant expression.


Interestingly, declaring x to be an unsigned char correctly fails to compile:

char c{ 'A' };
unsigned char x{ c + c }; 

C2397 conversion from 'int' to 'unsigned char' requires a narrowing conversion

As does introducing a temporary:

char c{ 'A' };
int sum{ c + c };
char x{ sum }; //C2397 conversion from 'int' to 'char' requires [...]

So why does the first version compile? I'm using Visual Studio Community 2017 Version 15.9.5 and compile it with /wall and all warnings are errors enabled in a x64 debug build. Setting the standard C++11, C++14 and C++17 all compile.


I filed the bug report here

Tel answered 19/6, 2019 at 10:42 Comment(3)
clang gives an error for this, while gcc gives a warning.Abrahamabrahams
what compilation flags are you using? Are-Wall or -Wnarrowing used? (or their visual studio equivalents.)Parette
Seems like Biagio Festa's answer is the correct one with a visual studio bug.Parette
E
12

Yes. You are right: the program is ill-formed.

In such a case (standard §1.4):

a conforming implementation shall issue at least one diagnostic message.

Indeed, gcc produces a warning message. clang directly rejects the code as a compiler error.

This specific topic has already been discussed here for gcc1.

Visual Studio is supposed to produce a diagnostic message (I suggest you check your compilation options. Did you disable warnings? Are you compiling with C++(11/14/17)?, ...). If this is not the case, it's an implementation bug.

Update:

Visual Studio v19.20 does not produce any diagnostic message (even with /Wall flag).

A bug report has been filled here.


1 For additional information regarding gcc implementation for narrowing check here.

Ever answered 19/6, 2019 at 11:8 Comment(4)
Which C++ standard are you using? If you fill a bug report, I think it could be useful to add the link as a comment to this answer. ThanksEver
I actually switched through C++11 - C++14 - C++17 to see if it makes a difference, but there was none so I just tagged C++11 for the post.Tel
Yeah you just need C++11 or aboveEver
And yes, I wrote a short summary as well as linking this post. Shall it be helpful.Tel

© 2022 - 2024 — McMap. All rights reserved.