c++c++11gcc4.9gcc5

g++4.9 and g++5 different behaviour when narrowing in initializing list


Consider this code:

#include <iostream>

int main()
{
    int i{10.1}; // narrowing, should not compile
    std::cout << i << std::endl;
}

According to the C++11 standard, it should not compile (narrowing in brace initialization is forbidden.)

Now, compiling with g++4.9.2 -std=c++11 only emits a warning

warning: narrowing conversion of '1.01e+1' from 'double' to 'int' inside { } [-Wnarrowing]

Removing the -std=c++11 flag results in a warning regarding the brace init, but not any narrowing:

warning: extended initializer lists only available with -std=c++11 or -std=gnu++11

On the other hand, g++5 doesn't compile it, provided you compile with g++5 -std=c++11. However, if -std=c++11 is omitted, then even g++5 happily compiles it, giving just a warning related to the brace init, not to the narrowing:

warning: extended initializer lists only available with -std=c++11 or -std=gnu++11

The above behaviour seems buggy, g++4.9 should not compile the code, and it is more than weird that g++5 compiles it if you forget to specify -std=c++11. Is this a known problem?


Solution

  • The standard never says anything "should not compile" (except for #error). Certain ill-formed programs must emit a diagnostic and issuing a warning satisfies that.

    You can cause gcc to stop compilation on all diagnostics by using the switch -Werror. It can be narrowed to specific warnings, e.g. -Werror=narrowing.

    If you are compiling in GNU++ or whatever the default mode is instead of C++11 then the compiler can do whatever it likes, including accepting narrowing conversions without complaint.

    Reference: N3936 [intro.compliance]/2

    • If a program contains a violation of any diagnosable rule [...], a conforming implementation shall issue at least one diagnostic message.

    • If a program contains a violation of a rule for which no diagnostic is required, this International Standard places no requirement on implementations with respect to that program.

    [defns.diagnostic]

    diagnostic message

    message belonging to an implementation-defined subset of the implementation’s output messages

    Note also from the first bullet point that it is not required that the number or content of messages corresponds to the number or content of the violations.

    The standard leaves it completely up to the compiler to decide how to organize its errors and/or warnings, with the proviso that for certain violations it can't silently ignore it.