9
votes
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

1
Most times the standard just says "a diagnostic" which covers both warning and errors.Richard Critten
@ShafikYaghmour: I see, thanks. I assume that MSVC is wrong in the first snippet then? And according to Richard, I assume that g++ and clang++ are compliant in both snippets.Vittorio Romeo
With GCC, to turn standard-mandated diagnostics into an error, but only the standard-mandated ones, use -pedantic-errors, though as mentioned warnings are sufficient to meet the standard's requirements.user743382

1 Answers

4
votes

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.