Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Narrowing conversion from `int` (constant expression) to `unsigned int` - MSVC vs gcc vs clang

constexpr int i = 100;
struct F { F(unsigned int){} };
int main() { F{i}; }

The snippet above:

  • Compiles with no warnings on g++ 7 with -Wall -Wextra -Wpedantic.

  • Compiles with no warnings on clang++ 4 with -Wall -Wextra -Wpedantic.

  • Fails to compile on MSVC 2017:

    conversion from 'const int' to 'unsigned int' requires a narrowing conversion

Q: is MSVC wrong here?

live example on godbolt.org


int i = 100;
struct F { F(unsigned int){} };
int main() { F{i}; }
  • Compiles with warnings on g++ 7 with -Wall -Wextra -Wpedantic:

    narrowing conversion of 'i' from 'int' to 'unsigned int'

  • Fails to compile clang++ 4 with -Wall -Wextra -Wpedantic:

    non-constant-expression cannot be narrowed from type 'int' to 'unsigned int' in initializer list

  • Fails to compile on MSVC 2017:

    conversion from 'const int' to 'unsigned int' requires a narrowing conversion

Q: is g++ wrong here? (i.e. should it produce an hard error?)

live example on godbolt.org

like image 726
Vittorio Romeo Avatar asked Mar 28 '17 17:03

Vittorio Romeo


1 Answers

There is never a requirement that any C++ program produce a hard error. There are requirements to print diagnostics. The form of the diagnostic is unspecified by the standard: an old joke is that printing out a single space satisifies the diagnostic requirements of the standard. That would be a quality of implementation issue.

There are ill-formed programs upon which the standard places no restrictions on their behavior, and sometimes a mandatory diagnostic.

There are cases where a program is ill-formed and a diagnostic is required. One way to handle that is to produce a message saying it is an error, then do not generate any binary to run. Another way is to produce a message saying it is a warning, then produce a binary that can be run.

So, g++ is not wrong under the standard for merely printing out a warning.

The resulting program is technically all undefined behavior; g++ could format your hard drive when it runs without violating the standard. That would be considered a quality of implementation issue.

Shafik's answer here covers the first question. i is constant expression and its value fits the target type; there should be no warning or error about the narrowing conversion.

The C++ standard does not defend you against hostile compilers.

Reportedly, -pedantic-errors can be passed to g++ to have it generate hard errors instead of warnings when the standard mandates the resulting program would be ill-formed.

like image 76
Yakk - Adam Nevraumont Avatar answered Oct 15 '22 12:10

Yakk - Adam Nevraumont